summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi76
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-cdp.dtsi8
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-mtp.dtsi8
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-qrd.dtsi18
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/msmtriton.dtsi5
-rw-r--r--arch/arm/configs/msmfalcon-perf_defconfig1
-rw-r--r--arch/arm/configs/msmfalcon_defconfig1
-rw-r--r--arch/arm64/configs/msmfalcon-perf_defconfig1
-rw-r--r--arch/arm64/configs/msmfalcon_defconfig1
-rw-r--r--drivers/gpu/msm/adreno_iommu.c11
-rw-r--r--drivers/gpu/msm/kgsl.c25
-rw-r--r--drivers/gpu/msm/kgsl_sharedmem.h3
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c91
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c18
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c23
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c147
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h3
-rw-r--r--drivers/misc/hdcp.c171
-rw-r--r--drivers/misc/qcom/qdsp6v2/Makefile3
-rw-r--r--drivers/misc/qcom/qdsp6v2/audio_amrnb.c50
-rw-r--r--drivers/misc/qcom/qdsp6v2/audio_amrwb.c50
-rw-r--r--drivers/misc/qcom/qdsp6v2/audio_g711alaw.c396
-rw-r--r--drivers/misc/qcom/qdsp6v2/audio_g711mlaw.c396
-rw-r--r--drivers/misc/qcom/qdsp6v2/g711alaw_in.c382
-rw-r--r--drivers/misc/qcom/qdsp6v2/g711mlaw_in.c385
-rw-r--r--drivers/mmc/card/block.c13
-rw-r--r--drivers/mmc/core/core.c6
-rw-r--r--drivers/mmc/host/cmdq_hci.c10
-rw-r--r--drivers/mmc/host/sdhci.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa.c10
-rw-r--r--drivers/usb/gadget/Kconfig9
-rw-r--r--drivers/usb/gadget/function/Makefile2
-rw-r--r--drivers/usb/gadget/function/f_qdss.h8
-rw-r--r--drivers/usb/gadget/function/f_rmnet.c776
-rw-r--r--drivers/usb/gadget/function/u_ctrl_qti.c172
-rw-r--r--drivers/usb/gadget/function/u_data_ipa.c8
-rw-r--r--drivers/usb/gadget/function/u_data_ipa.h10
-rw-r--r--drivers/usb/gadget/function/u_rmnet.h48
-rw-r--r--drivers/video/fbdev/msm/mdss.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c94
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c116
-rw-r--r--drivers/video/fbdev/msm/mdss_hdcp_1x.c522
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c33
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h10
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c17
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c35
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c1
-rw-r--r--include/linux/clk/msm-clk-provider.h4
-rw-r--r--include/linux/clk/msm-clk.h7
-rw-r--r--include/linux/sched.h2
-rw-r--r--include/sound/apr_audio-v2.h27
-rw-r--r--include/sound/q6asm-v2.h13
-rw-r--r--include/uapi/linux/Kbuild2
-rw-r--r--include/uapi/linux/msm_audio_g711.h17
-rw-r--r--include/uapi/linux/msm_audio_g711_dec.h16
-rw-r--r--include/uapi/media/msm_media_info.h220
-rw-r--r--include/uapi/sound/compress_params.h24
-rw-r--r--kernel/sched/core.c3
-rw-r--r--kernel/sched/hmp.c195
-rw-r--r--kernel/sched/sched.h3
-rw-r--r--mm/page_isolation.c3
-rw-r--r--net/rmnet_data/rmnet_data_handlers.c2
-rw-r--r--sound/soc/codecs/Makefile7
-rw-r--r--sound/soc/codecs/audio-ext-clk-up.c577
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c21
-rw-r--r--sound/soc/msm/msm8998.c59
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c153
-rw-r--r--sound/soc/msm/qdsp6v2/q6afe.c4
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c171
-rw-r--r--sound/soc/soc-dapm.c3
75 files changed, 4285 insertions, 1440 deletions
diff --git a/arch/arm/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi b/arch/arm/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi
index 69067f5f1cc7..364b83320015 100644
--- a/arch/arm/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi
+++ b/arch/arm/boot/dts/qcom/fg-gen3-batterydata-ascent-3450mah.dtsi
@@ -11,53 +11,53 @@
*/
qcom,ascent_3450mah {
- /* #Ascent_860_82209_0000_3450mAh_averaged_MasterSlave_Jul20th2016*/
+ /* Ascent_with_connector_3450mAh_averaged_MasterSlave_Nov28th2016 */
qcom,max-voltage-uv = <4350000>;
qcom,fg-cc-cv-threshold-mv = <4340>;
qcom,nom-batt-capacity-mah = <3450>;
qcom,batt-id-kohm = <60>;
qcom,battery-beta = <3435>;
- qcom,battery-type = "ascent_860_82209_0000_3450mah";
- qcom,checksum = <0xD1D9>;
- qcom,gui-version = "PMI8998GUI - 0.0.0.82";
+ qcom,battery-type = "ascent_3450mah_averaged_masterslave_nov28th2016";
+ qcom,checksum = <0x2232>;
+ qcom,gui-version = "PMI8998GUI - 2.0.0.52";
qcom,fg-profile-data = [
- 2C 1F 3F FC
- E9 03 A1 FD
- 58 1D FD F5
- 27 12 2C 14
- 3F 18 FF 22
- 9B 45 A3 52
+ 9C 1F 85 05
+ 82 0A 73 FC
+ 2B 1D 6A EA
+ F2 03 63 0C
+ C8 17 F3 22
+ E0 45 1F 52
+ 5C 00 00 00
+ 10 00 00 00
+ 00 00 4A C4
+ C7 BC 48 C2
+ 0F 00 08 00
+ 92 00 5D ED
+ 8D FD B1 F3
+ 27 00 A6 12
+ 77 F4 0F 3B
+ 24 06 09 20
+ 27 00 14 00
+ 83 1F EE 05
+ 1F 0A 45 FD
+ 6B 1D 52 E5
+ EC 0B 31 14
+ 44 18 49 23
+ 18 45 A6 53
55 00 00 00
0E 00 00 00
- 00 00 1C AC
- F7 CD 71 B5
- 1A 00 0C 00
- 3C EB 54 E4
- EC 05 7F FA
- 76 05 F5 02
- CA F3 82 3A
- 2A 09 40 40
- 07 00 05 00
- 58 1F 42 06
- 85 03 35 F4
- 4D 1D 37 F2
- 23 0A 79 15
- B7 18 32 23
- 26 45 72 53
- 55 00 00 00
- 0D 00 00 00
- 00 00 13 CC
- 03 00 98 BD
- 16 00 00 00
- 3C EB 54 E4
- 9F FC A3 F3
- 0F FC DF FA
- FF E5 A9 23
- CB 33 08 33
+ 00 00 61 CC
+ B7 C3 0F BC
+ 0F 00 00 00
+ 92 00 5D ED
+ E3 06 81 F3
+ 75 FD 9C 03
+ 43 DB B3 22
+ CB 33 CC FF
07 10 00 00
- 81 0D 99 45
- 16 00 19 00
- 75 01 0A FA
+ 99 0D 99 45
+ 0F 00 40 00
+ AB 01 0A FA
FF 00 00 00
00 00 00 00
00 00 00 00
diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd.dtsi
index 03abb5d69b52..8c51aa643382 100644
--- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd.dtsi
@@ -206,7 +206,7 @@
reg = <0x0>;
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
- qcom,mount-angle = <90>;
+ qcom,mount-angle = <270>;
qcom,led-flash-src = <&led_flash0>;
qcom,actuator-src = <&actuator0>;
qcom,ois-src = <&ois0>;
@@ -294,7 +294,7 @@
reg = <0x02>;
qcom,csiphy-sd-index = <2>;
qcom,csid-sd-index = <2>;
- qcom,mount-angle = <270>;
+ qcom,mount-angle = <90>;
qcom,eeprom-src = <&eeprom2>;
qcom,led-flash-src = <&led_flash1>;
qcom,actuator-src = <&actuator1>;
diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-cdp.dtsi
index 32f9dcdecb0c..76326e7ae86f 100644
--- a/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-cdp.dtsi
@@ -69,12 +69,12 @@
};
&sdhc_2 {
- vdd-supply = <&pm8998_l21>;
- qcom,vdd-voltage-level = <2950000 2960000>;
+ vdd-supply = <&pm2falcon_l5>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <200 800000>;
- vdd-io-supply = <&pm8998_l13>;
- qcom,vdd-io-voltage-level = <1808000 2960000>;
+ vdd-io-supply = <&pm2falcon_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <200 22000>;
pinctrl-names = "active", "sleep";
diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-mtp.dtsi
index e73ffc884210..5c55732e0de7 100644
--- a/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-mtp.dtsi
@@ -70,12 +70,12 @@
};
&sdhc_2 {
- vdd-supply = <&pm8998_l21>;
- qcom,vdd-voltage-level = <2950000 2960000>;
+ vdd-supply = <&pm2falcon_l5>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <200 800000>;
- vdd-io-supply = <&pm8998_l13>;
- qcom,vdd-io-voltage-level = <1808000 2960000>;
+ vdd-io-supply = <&pm2falcon_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <200 22000>;
pinctrl-names = "active", "sleep";
diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-qrd.dtsi
index cd0e20a295d9..0c49c4246f10 100644
--- a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-qrd.dtsi
@@ -21,8 +21,10 @@
&ufsphy1 {
vdda-phy-supply = <&pm2falcon_l1>;
- vdda-pll-supply = <&pmfalcon_l10>;
- vddp-ref-clk-supply = <&pmfalcon_l8>;
+ vdda-pll-supply = <&pmfalcon_l1>;
+ vddp-ref-clk-supply = <&pmfalcon_l1>;
+ vdda-phy-max-uv = <925000>;
+ vdda-phy-min-uv = <800000>;
vdda-phy-max-microamp = <51400>;
vdda-pll-max-microamp = <14600>;
vddp-ref-clk-max-microamp = <100>;
@@ -34,11 +36,9 @@
vdd-hba-supply = <&gdsc_ufs>;
vdd-hba-fixed-regulator;
vcc-supply = <&pm2falcon_l4>;
- vccq-supply = <&pmfalcon_l8>;
vccq2-supply = <&pmfalcon_l8>;
- vcc-max-microamp = <750000>;
- vccq-max-microamp = <560000>;
- vccq2-max-microamp = <750000>;
+ vcc-max-microamp = <500000>;
+ vccq2-max-microamp = <600000>;
status = "ok";
};
@@ -71,10 +71,12 @@
};
&sdhc_2 {
- qcom,vdd-voltage-level = <2950000 2960000>;
+ vdd-supply = <&pm2falcon_l5>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <200 800000>;
- qcom,vdd-io-voltage-level = <1808000 2960000>;
+ vdd-io-supply = <&pm2falcon_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <200 22000>;
pinctrl-names = "active", "sleep";
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index 79cdc2b701e1..6ef443c4de11 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -1293,8 +1293,6 @@
#include "msm-gdsc-falcon.dtsi"
&gdsc_usb30 {
- clock-names = "core_clk";
- clocks = <&clock_gcc GCC_USB30_MASTER_CLK>;
status = "ok";
};
@@ -1351,9 +1349,6 @@
};
&gdsc_mdss {
- clock-names = "bus_clk", "rot_clk";
- clocks = <&clock_mmss MMSS_MDSS_AXI_CLK>,
- <&clock_mmss MMSS_MDSS_ROT_CLK>;
proxy-supply = <&gdsc_mdss>;
qcom,proxy-consumer-enable;
status = "ok";
diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi
index e7416ebb8f58..2a22772c8d1d 100644
--- a/arch/arm/boot/dts/qcom/msmtriton.dtsi
+++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi
@@ -787,8 +787,6 @@
#include "msmfalcon-common.dtsi"
&gdsc_usb30 {
- clock-names = "core_clk";
- clocks = <&clock_gcc GCC_USB30_MASTER_CLK>;
status = "ok";
};
@@ -837,9 +835,6 @@
};
&gdsc_mdss {
- clock-names = "bus_clk", "rot_clk";
- clocks = <&clock_mmss MMSS_MDSS_AXI_CLK>,
- <&clock_mmss MMSS_MDSS_ROT_CLK>;
proxy-supply = <&gdsc_mdss>;
qcom,proxy-consumer-enable;
status = "ok";
diff --git a/arch/arm/configs/msmfalcon-perf_defconfig b/arch/arm/configs/msmfalcon-perf_defconfig
index 1f8d22153a32..272f760117a7 100644
--- a/arch/arm/configs/msmfalcon-perf_defconfig
+++ b/arch/arm/configs/msmfalcon-perf_defconfig
@@ -602,6 +602,5 @@ CONFIG_CRYPTO_DEV_QCRYPTO=y
CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=y
CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
-CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCOM_ICE=y
CONFIG_XZ_DEC=y
diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig
index 06faf702156f..c09e02e53a07 100644
--- a/arch/arm/configs/msmfalcon_defconfig
+++ b/arch/arm/configs/msmfalcon_defconfig
@@ -641,6 +641,5 @@ CONFIG_CRYPTO_DEV_QCRYPTO=y
CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=y
CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
-CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCOM_ICE=y
CONFIG_XZ_DEC=y
diff --git a/arch/arm64/configs/msmfalcon-perf_defconfig b/arch/arm64/configs/msmfalcon-perf_defconfig
index 1074672d252f..4d26ad79196d 100644
--- a/arch/arm64/configs/msmfalcon-perf_defconfig
+++ b/arch/arm64/configs/msmfalcon-perf_defconfig
@@ -616,7 +616,6 @@ CONFIG_CRYPTO_DEV_QCRYPTO=y
CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=y
CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
-CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCOM_ICE=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
diff --git a/arch/arm64/configs/msmfalcon_defconfig b/arch/arm64/configs/msmfalcon_defconfig
index 6d8d9eeab2d5..c568f005e70b 100644
--- a/arch/arm64/configs/msmfalcon_defconfig
+++ b/arch/arm64/configs/msmfalcon_defconfig
@@ -681,7 +681,6 @@ CONFIG_CRYPTO_DEV_QCRYPTO=y
CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=y
CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
-CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCOM_ICE=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
diff --git a/drivers/gpu/msm/adreno_iommu.c b/drivers/gpu/msm/adreno_iommu.c
index aa00dcb84185..4bb7f6286664 100644
--- a/drivers/gpu/msm/adreno_iommu.c
+++ b/drivers/gpu/msm/adreno_iommu.c
@@ -856,6 +856,17 @@ int adreno_iommu_set_pt_ctx(struct adreno_ringbuffer *rb,
int result = 0;
int cpu_path = 0;
+ /* Just do the context switch incase of NOMMU */
+ if (kgsl_mmu_get_mmutype(device) == KGSL_MMU_TYPE_NONE) {
+ if ((!(flags & ADRENO_CONTEXT_SWITCH_FORCE_GPU)) &&
+ adreno_isidle(device))
+ _set_ctxt_cpu(rb, drawctxt);
+ else
+ result = _set_ctxt_gpu(rb, drawctxt);
+
+ return result;
+ }
+
if (rb->drawctxt_active)
cur_pt = rb->drawctxt_active->base.proc_priv->pagetable;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 699d99651f2c..993f22b26294 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -353,8 +353,10 @@ static int kgsl_mem_entry_track_gpuaddr(struct kgsl_device *device,
/*
* If SVM is enabled for this object then the address needs to be
* assigned elsewhere
+ * Also do not proceed further in case of NoMMU.
*/
- if (kgsl_memdesc_use_cpu_map(&entry->memdesc))
+ if (kgsl_memdesc_use_cpu_map(&entry->memdesc) ||
+ (kgsl_mmu_get_mmutype(device) == KGSL_MMU_TYPE_NONE))
return 0;
pagetable = kgsl_memdesc_is_secured(&entry->memdesc) ?
@@ -491,21 +493,18 @@ void kgsl_context_dump(struct kgsl_context *context)
EXPORT_SYMBOL(kgsl_context_dump);
/* Allocate a new context ID */
-static int _kgsl_get_context_id(struct kgsl_device *device,
- struct kgsl_context *context)
+static int _kgsl_get_context_id(struct kgsl_device *device)
{
int id;
idr_preload(GFP_KERNEL);
write_lock(&device->context_lock);
- id = idr_alloc(&device->context_idr, context, 1,
+ /* Allocate the slot but don't put a pointer in it yet */
+ id = idr_alloc(&device->context_idr, NULL, 1,
KGSL_MEMSTORE_MAX, GFP_NOWAIT);
write_unlock(&device->context_lock);
idr_preload_end();
- if (id > 0)
- context->id = id;
-
return id;
}
@@ -529,7 +528,7 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv,
char name[64];
int ret = 0, id;
- id = _kgsl_get_context_id(device, context);
+ id = _kgsl_get_context_id(device);
if (id == -ENOSPC) {
/*
* Before declaring that there are no contexts left try
@@ -538,7 +537,7 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv,
*/
flush_workqueue(device->events_wq);
- id = _kgsl_get_context_id(device, context);
+ id = _kgsl_get_context_id(device);
}
if (id < 0) {
@@ -550,6 +549,8 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv,
return id;
}
+ context->id = id;
+
kref_init(&context->refcount);
/*
* Get a refernce to the process private so its not destroyed, until
@@ -1733,6 +1734,12 @@ long kgsl_ioctl_drawctxt_create(struct kgsl_device_private *dev_priv,
goto done;
}
trace_kgsl_context_create(dev_priv->device, context, param->flags);
+
+ /* Commit the pointer to the context in context_idr */
+ write_lock(&device->context_lock);
+ idr_replace(&device->context_idr, context, context->id);
+ write_unlock(&device->context_lock);
+
param->drawctxt_id = context->id;
done:
return result;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 03f278ead20f..c1c2afa68756 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -284,7 +284,8 @@ static inline int kgsl_allocate_global(struct kgsl_device *device,
memdesc->flags = flags;
memdesc->priv = priv;
- if ((memdesc->priv & KGSL_MEMDESC_CONTIG) != 0)
+ if (((memdesc->priv & KGSL_MEMDESC_CONTIG) != 0) ||
+ (kgsl_mmu_get_mmutype(device) == KGSL_MMU_TYPE_NONE))
ret = kgsl_sharedmem_alloc_contig(device, memdesc,
(size_t) size);
else {
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
index f001706236ab..0ec16e606545 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
@@ -358,6 +358,7 @@ static struct device_attribute attrs[] = {
static struct synaptics_rmi4_fwu_handle *fwu;
DECLARE_COMPLETION(fwu_dsx_remove_complete);
+DEFINE_MUTEX(dsx_fwu_sysfs_mutex);
static unsigned int extract_uint_le(const unsigned char *ptr)
{
@@ -1589,28 +1590,49 @@ static ssize_t fwu_sysfs_show_image(struct file *data_file,
char *buf, loff_t pos, size_t count)
{
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ ssize_t retval;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
if (count < fwu->config_size) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Not enough space (%zu bytes) in buffer\n",
__func__, count);
- return -EINVAL;
+ retval = -EINVAL;
+ goto show_image_exit;
}
memcpy(buf, fwu->read_config_buf, fwu->config_size);
-
- return fwu->config_size;
+ retval = fwu->config_size;
+show_image_exit:
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+ return retval;
}
static ssize_t fwu_sysfs_store_image(struct file *data_file,
struct kobject *kobj, struct bin_attribute *attributes,
char *buf, loff_t pos, size_t count)
{
+ ssize_t retval;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
if (count > (fwu->image_size - fwu->data_pos)) {
dev_err(fwu->rmi4_data->pdev->dev.parent,
"%s: Not enough space in buffer\n",
__func__);
- return -EINVAL;
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (!fwu->ext_data_source) {
+ dev_err(fwu->rmi4_data->pdev->dev.parent,
+ "%s: Need to set imagesize\n",
+ __func__);
+ retval = -EINVAL;
+ goto exit;
}
memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
@@ -1619,16 +1641,21 @@ static ssize_t fwu_sysfs_store_image(struct file *data_file,
fwu->data_pos += count;
+exit:
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
return count;
}
static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- int retval;
+ ssize_t retval;
unsigned int input;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
if (sscanf(buf, "%u", &input) != 1) {
retval = -EINVAL;
goto exit;
@@ -1657,6 +1684,9 @@ exit:
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->data_pos = 0;
+ fwu->image_size = 0;
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
return retval;
}
@@ -1667,6 +1697,9 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
unsigned int input;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
if (sscanf(buf, "%u", &input) != 1) {
retval = -EINVAL;
goto exit;
@@ -1700,6 +1733,9 @@ exit:
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->data_pos = 0;
+ fwu->image_size = 0;
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
return retval;
}
@@ -1710,6 +1746,9 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev,
unsigned int input;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
if (sscanf(buf, "%u", &input) != 1) {
retval = -EINVAL;
goto exit;
@@ -1733,6 +1772,9 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev,
exit:
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
+ fwu->data_pos = 0;
+ fwu->image_size = 0;
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
return retval;
}
@@ -1749,7 +1791,11 @@ static ssize_t fwu_sysfs_read_config_store(struct device *dev,
if (input != 1)
return -EINVAL;
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
retval = fwu_do_read_config();
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+
if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read config\n",
@@ -1770,7 +1816,10 @@ static ssize_t fwu_sysfs_config_area_store(struct device *dev,
if (retval)
return retval;
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
fwu->config_area = config_area;
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
return count;
}
@@ -1778,17 +1827,30 @@ static ssize_t fwu_sysfs_config_area_store(struct device *dev,
static ssize_t fwu_sysfs_image_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ ssize_t retval;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
if (strnlen(fwu->rmi4_data->fw_name, SYNA_FW_NAME_MAX_LEN) > 0)
- return snprintf(buf, PAGE_SIZE, "%s\n",
+ retval = snprintf(buf, PAGE_SIZE, "%s\n",
fwu->rmi4_data->fw_name);
else
- return snprintf(buf, PAGE_SIZE, "No firmware name given\n");
+ retval = snprintf(buf, PAGE_SIZE, "No firmware name given\n");
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+ return retval;
}
static ssize_t fwu_sysfs_image_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- if (sscanf(buf, "%s", fwu->image_name) != 1)
+ ssize_t retval;
+
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+ retval = sscanf(buf, "%49s", fwu->image_name);
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+
+ if (retval != 1)
return -EINVAL;
return count;
@@ -1801,9 +1863,12 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev,
unsigned long size;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
+ return -EBUSY;
+
retval = sstrtoul(buf, 10, &size);
if (retval)
- return retval;
+ goto exit;
fwu->image_size = size;
fwu->data_pos = 0;
@@ -1814,10 +1879,14 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev,
dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to alloc mem for image data\n",
__func__);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto exit;
}
- return count;
+ retval = count;
+exit:
+ mutex_unlock(&dsx_fwu_sysfs_mutex);
+ return retval;
}
static ssize_t fwu_sysfs_block_size_show(struct device *dev,
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
index 437af72a6a55..de27e585f63d 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -71,8 +71,8 @@ static long msm_jpeg_compat_ioctl(struct file *filp, unsigned int cmd,
int rc;
struct msm_jpeg_device *pgmn_dev = filp->private_data;
- JPEG_DBG("%s:%d] cmd=%d pgmn_dev=0x%lx arg=0x%lx\n", __func__,
- __LINE__, _IOC_NR(cmd), (unsigned long)pgmn_dev,
+ JPEG_DBG("%s:%d] cmd=%d pgmn_dev=0x%pK arg=0x%lx\n", __func__,
+ __LINE__, _IOC_NR(cmd), pgmn_dev,
(unsigned long)arg);
rc = __msm_jpeg_compat_ioctl(pgmn_dev, cmd, arg);
@@ -87,8 +87,8 @@ static long msm_jpeg_ioctl(struct file *filp, unsigned int cmd,
int rc;
struct msm_jpeg_device *pgmn_dev = filp->private_data;
- JPEG_DBG("%s:%d] cmd=%d pgmn_dev=0x%lx arg=0x%lx\n", __func__,
- __LINE__, _IOC_NR(cmd), (unsigned long)pgmn_dev,
+ JPEG_DBG("%s:%d] cmd=%d pgmn_dev=0x%pK arg=0x%lx\n", __func__,
+ __LINE__, _IOC_NR(cmd), pgmn_dev,
(unsigned long)arg);
rc = __msm_jpeg_ioctl(pgmn_dev, cmd, arg);
@@ -114,9 +114,9 @@ int msm_jpeg_subdev_init(struct v4l2_subdev *jpeg_sd)
struct msm_jpeg_device *pgmn_dev =
(struct msm_jpeg_device *)jpeg_sd->host_priv;
- JPEG_DBG("%s:%d: jpeg_sd=0x%lx pgmn_dev=0x%lx\n",
+ JPEG_DBG("%s:%d: jpeg_sd=0x%lx pgmn_dev=0x%pK\n",
__func__, __LINE__, (unsigned long)jpeg_sd,
- (unsigned long)pgmn_dev);
+ pgmn_dev);
rc = __msm_jpeg_open(pgmn_dev);
JPEG_DBG("%s:%d: rc=%d\n",
__func__, __LINE__, rc);
@@ -132,7 +132,7 @@ static long msm_jpeg_subdev_ioctl(struct v4l2_subdev *sd,
JPEG_DBG("%s: cmd=%d\n", __func__, cmd);
- JPEG_DBG("%s: pgmn_dev 0x%lx", __func__, (unsigned long)pgmn_dev);
+ JPEG_DBG("%s: pgmn_dev 0x%pK", __func__, pgmn_dev);
JPEG_DBG("%s: Calling __msm_jpeg_ioctl\n", __func__);
@@ -146,7 +146,7 @@ void msm_jpeg_subdev_release(struct v4l2_subdev *jpeg_sd)
int rc;
struct msm_jpeg_device *pgmn_dev =
(struct msm_jpeg_device *)jpeg_sd->host_priv;
- JPEG_DBG("%s:pgmn_dev=0x%lx", __func__, (unsigned long)pgmn_dev);
+ JPEG_DBG("%s:pgmn_dev=0x%pK", __func__, pgmn_dev);
rc = __msm_jpeg_release(pgmn_dev);
JPEG_DBG("%s:rc=%d", __func__, rc);
}
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
index 071ce0a41ed9..e40869d41a5d 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
@@ -847,7 +847,7 @@ int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, uint32_t m_cmds,
uint32_t data;
while (m_cmds--) {
- if (hw_cmd_p->offset > max_size) {
+ if (hw_cmd_p->offset >= max_size) {
JPEG_PR_ERR("%s:%d] %d exceed hw region %d\n", __func__,
__LINE__, hw_cmd_p->offset, max_size);
return -EFAULT;
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
index 63d7e715162b..3301fc446193 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
@@ -128,6 +128,21 @@ static inline void msm_jpegdma_schedule_next_config(struct jpegdma_ctx *ctx)
}
/*
+ * msm_jpegdma_cast_long_to_buff_ptr - Cast long to buffer pointer.
+ * @vaddr: vaddr as long
+ * @buff_ptr_head: buffer pointer head
+ */
+static inline void msm_jpegdma_cast_long_to_buff_ptr(unsigned long vaddr,
+ struct msm_jpeg_dma_buff **buff_ptr_head)
+{
+#ifdef CONFIG_COMPAT
+ *buff_ptr_head = compat_ptr(vaddr);
+#else
+ *buff_ptr_head = (struct msm_jpeg_dma_buff *) vaddr;
+#endif
+}
+
+/*
* msm_jpegdma_get_format_idx - Get jpeg dma format lookup index.
* @ctx: Pointer to dma ctx.
* @f: v4l2 format.
@@ -410,10 +425,12 @@ static void *msm_jpegdma_get_userptr(void *alloc_ctx,
{
struct msm_jpegdma_device *dma = alloc_ctx;
struct msm_jpegdma_buf_handle *buf;
- struct msm_jpeg_dma_buff __user *up_buff = compat_ptr(vaddr);
+ struct msm_jpeg_dma_buff __user *up_buff;
struct msm_jpeg_dma_buff kp_buff;
int ret;
+ msm_jpegdma_cast_long_to_buff_ptr(vaddr, &up_buff);
+
if (!access_ok(VERIFY_READ, up_buff,
sizeof(struct msm_jpeg_dma_buff)) ||
get_user(kp_buff.fd, &up_buff->fd)) {
@@ -813,10 +830,12 @@ static int msm_jpegdma_qbuf(struct file *file, void *fh,
struct v4l2_buffer *buf)
{
struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh);
- struct msm_jpeg_dma_buff __user *up_buff = compat_ptr(buf->m.userptr);
+ struct msm_jpeg_dma_buff __user *up_buff;
struct msm_jpeg_dma_buff kp_buff;
int ret;
+ msm_jpegdma_cast_long_to_buff_ptr(buf->m.userptr, &up_buff);
+
if (!access_ok(VERIFY_READ, up_buff,
sizeof(struct msm_jpeg_dma_buff)) ||
get_user(kp_buff.fd, &up_buff->fd) ||
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 b9018a226f2f..7e452e9e4ee2 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
@@ -220,6 +220,7 @@ void msm_cpp_deinit_bandwidth_mgr(struct cpp_device *cpp_dev)
static int msm_cpp_update_bandwidth_setting(struct cpp_device *cpp_dev,
uint64_t ab, uint64_t ib) {
int rc;
+
if (cpp_dev->bus_master_flag)
rc = msm_cpp_update_bandwidth(cpp_dev, ab, ib);
else
@@ -242,6 +243,7 @@ static void msm_enqueue(struct msm_device_queue *queue,
struct list_head *entry)
{
unsigned long flags;
+
spin_lock_irqsave(&queue->lock, flags);
queue->len++;
if (queue->len > queue->max) {
@@ -302,6 +304,7 @@ static void msm_cpp_timer_queue_update(struct cpp_device *cpp_dev)
{
uint32_t i;
unsigned long flags;
+
CPP_DBG("Frame done qlen %d\n", cpp_dev->processing_q.len);
if (cpp_dev->processing_q.len <= 1) {
msm_cpp_clear_timer(cpp_dev);
@@ -323,6 +326,7 @@ static void msm_cpp_timer_queue_update(struct cpp_device *cpp_dev)
static uint32_t msm_cpp_read(void __iomem *cpp_base)
{
uint32_t tmp, retry = 0;
+
do {
tmp = msm_camera_io_r(cpp_base + MSM_CPP_MICRO_FIFO_TX_STAT);
} while (((tmp & 0x2) == 0x0) && (retry++ < 10));
@@ -409,14 +413,22 @@ static unsigned long msm_cpp_queue_buffer_info(struct cpp_device *cpp_dev,
pr_err("error allocating memory\n");
goto error;
}
- buff->map_info.buff_info = *buffer_info;
+ buff->map_info.buff_info = *buffer_info;
buff->map_info.buf_fd = buffer_info->fd;
- rc = cam_smmu_get_phy_addr(cpp_dev->iommu_hdl, buffer_info->fd,
- CAM_SMMU_MAP_RW, &buff->map_info.phy_addr,
- (size_t *)&buff->map_info.len);
+
+ if (buff_queue->security_mode == SECURE_MODE)
+ rc = cam_smmu_get_stage2_phy_addr(cpp_dev->iommu_hdl,
+ buffer_info->fd, CAM_SMMU_MAP_RW,
+ cpp_dev->ion_client, &buff->map_info.phy_addr,
+ (size_t *)&buff->map_info.len);
+ else
+ rc = cam_smmu_get_phy_addr(cpp_dev->iommu_hdl,
+ buffer_info->fd, CAM_SMMU_MAP_RW,
+ &buff->map_info.phy_addr,
+ (size_t *)&buff->map_info.len);
if (rc < 0) {
- pr_err("ION mmap failed\n");
+ pr_err("ION mmap for CPP buffer failed\n");
kzfree(buff);
goto error;
}
@@ -430,10 +442,17 @@ error:
}
static void msm_cpp_dequeue_buffer_info(struct cpp_device *cpp_dev,
+ struct msm_cpp_buff_queue_info_t *buff_queue,
struct msm_cpp_buffer_map_list_t *buff)
{
int ret = -1;
- ret = cam_smmu_put_phy_addr(cpp_dev->iommu_hdl, buff->map_info.buf_fd);
+
+ if (buff_queue->security_mode == SECURE_MODE)
+ ret = cam_smmu_put_stage2_phy_addr(cpp_dev->iommu_hdl,
+ buff->map_info.buf_fd);
+ else
+ ret = cam_smmu_put_phy_addr(cpp_dev->iommu_hdl,
+ buff->map_info.buf_fd);
if (ret < 0)
pr_err("Error: cannot put the iommu handle back to ion fd\n");
@@ -466,6 +485,7 @@ static unsigned long msm_cpp_fetch_buffer_info(struct cpp_device *cpp_dev,
buffer_info);
*fd = buffer_info->fd;
}
+
return phy_addr;
}
@@ -477,12 +497,12 @@ static int32_t msm_cpp_dequeue_buff_info_list(struct cpp_device *cpp_dev,
buff_head = &buff_queue_info->native_buff_head;
list_for_each_entry_safe(buff, save, buff_head, entry) {
- msm_cpp_dequeue_buffer_info(cpp_dev, buff);
+ msm_cpp_dequeue_buffer_info(cpp_dev, buff_queue_info, buff);
}
buff_head = &buff_queue_info->vb2_buff_head;
list_for_each_entry_safe(buff, save, buff_head, entry) {
- msm_cpp_dequeue_buffer_info(cpp_dev, buff);
+ msm_cpp_dequeue_buffer_info(cpp_dev, buff_queue_info, buff);
}
return 0;
@@ -502,7 +522,8 @@ static int32_t msm_cpp_dequeue_buff(struct cpp_device *cpp_dev,
list_for_each_entry_safe(buff, save, buff_head, entry) {
if (buff->map_info.buff_info.index == buff_index) {
- msm_cpp_dequeue_buffer_info(cpp_dev, buff);
+ msm_cpp_dequeue_buffer_info(cpp_dev, buff_queue_info,
+ buff);
break;
}
}
@@ -522,6 +543,8 @@ static int32_t msm_cpp_add_buff_queue_entry(struct cpp_device *cpp_dev,
buff_queue_info->used = 1;
buff_queue_info->session_id = session_id;
buff_queue_info->stream_id = stream_id;
+ buff_queue_info->security_mode =
+ cpp_dev->security_mode;
INIT_LIST_HEAD(&buff_queue_info->vb2_buff_head);
INIT_LIST_HEAD(&buff_queue_info->native_buff_head);
return 0;
@@ -548,6 +571,7 @@ static int32_t msm_cpp_free_buff_queue_entry(struct cpp_device *cpp_dev,
buff_queue_info->used = 0;
buff_queue_info->session_id = 0;
buff_queue_info->stream_id = 0;
+ buff_queue_info->security_mode = NON_SECURE_MODE;
INIT_LIST_HEAD(&buff_queue_info->vb2_buff_head);
INIT_LIST_HEAD(&buff_queue_info->native_buff_head);
return 0;
@@ -557,6 +581,7 @@ static int32_t msm_cpp_create_buff_queue(struct cpp_device *cpp_dev,
uint32_t num_buffq)
{
struct msm_cpp_buff_queue_info_t *buff_queue;
+
buff_queue = kzalloc(
sizeof(struct msm_cpp_buff_queue_info_t) * num_buffq,
GFP_KERNEL);
@@ -602,6 +627,7 @@ static int32_t msm_cpp_poll(void __iomem *cpp_base, u32 val)
{
uint32_t tmp, retry = 0;
int32_t rc = 0;
+
do {
tmp = msm_cpp_read(cpp_base);
if (tmp != 0xDEADBEEF)
@@ -796,6 +822,7 @@ static irqreturn_t msm_cpp_irq(int irq_num, void *data)
uint32_t tx_fifo[MSM_CPP_TX_FIFO_LEVEL];
struct cpp_device *cpp_dev = data;
struct msm_cpp_tasklet_queue_cmd *queue_cmd;
+
irq_status = msm_camera_io_r(cpp_dev->base + MSM_CPP_MICRO_IRQGEN_STAT);
if (irq_status & 0x8) {
@@ -1028,6 +1055,7 @@ reg_enable_failed:
static void cpp_release_hardware(struct cpp_device *cpp_dev)
{
int32_t rc;
+
if (cpp_dev->state != CPP_STATE_BOOT) {
msm_camera_unregister_irq(cpp_dev->pdev, cpp_dev->irq, cpp_dev);
tasklet_kill(&cpp_dev->cpp_tasklet);
@@ -1061,7 +1089,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
goto end;
}
pr_debug("%s:%d] FW file: %s\n", __func__, __LINE__, fw_name_bin);
- if (NULL == cpp_dev->fw) {
+ if (cpp_dev->fw == NULL) {
pr_err("%s:%d] fw NULL", __func__, __LINE__);
rc = -EINVAL;
goto end;
@@ -1192,7 +1220,8 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
int rc;
uint32_t i;
struct cpp_device *cpp_dev = NULL;
- CPP_DBG("E\n");
+
+ CPP_DBG("E");
if (!sd || !fh) {
pr_err("Wrong input parameters sd %pK fh %pK!",
@@ -1246,6 +1275,14 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
return rc;
}
cpp_dev->state = CPP_STATE_IDLE;
+
+ CPP_DBG("Invoking msm_ion_client_create()\n");
+ cpp_dev->ion_client = msm_ion_client_create("cpp");
+ if (cpp_dev->ion_client == NULL) {
+ pr_err("msm_ion_client_create() failed\n");
+ mutex_unlock(&cpp_dev->mutex);
+ rc = -ENOMEM;
+ }
}
mutex_unlock(&cpp_dev->mutex);
return 0;
@@ -1338,6 +1375,12 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
msm_cpp_empty_list(processing_q, list_frame);
msm_cpp_empty_list(eventData_q, list_eventdata);
cpp_dev->state = CPP_STATE_OFF;
+
+ if (cpp_dev->ion_client) {
+ CPP_DBG("Invoking ion_client_destroy()\n");
+ ion_client_destroy(cpp_dev->ion_client);
+ cpp_dev->ion_client = NULL;
+ }
}
mutex_unlock(&cpp_dev->mutex);
@@ -1415,7 +1458,8 @@ static int msm_cpp_notify_frame_done(struct cpp_device *cpp_dev,
SWAP_IDENTITY_FOR_BATCH_ON_PREVIEW(processed_frame,
iden, processed_frame->duplicate_identity);
- memset(&buff_mgr_info, 0 ,
+
+ memset(&buff_mgr_info, 0,
sizeof(struct msm_buf_mngr_info));
buff_mgr_info.session_id = ((iden >> 16) & 0xFFFF);
@@ -1460,7 +1504,7 @@ static int msm_cpp_notify_frame_done(struct cpp_device *cpp_dev,
SWAP_IDENTITY_FOR_BATCH_ON_PREVIEW(processed_frame,
iden, processed_frame->identity);
- memset(&buff_mgr_info, 0 ,
+ memset(&buff_mgr_info, 0,
sizeof(struct msm_buf_mngr_info));
buff_mgr_info.session_id = ((iden >> 16) & 0xFFFF);
@@ -1500,6 +1544,7 @@ static int msm_cpp_dump_frame_cmd(struct msm_cpp_frame_info_t *frame_info)
{
int i, i1, i2;
struct cpp_device *cpp_dev = cpp_timer.data.cpp_dev;
+
CPP_DBG("-- start: cpp frame cmd for identity=0x%x, frame_id=%d --\n",
frame_info->identity, frame_info->frame_id);
@@ -1935,6 +1980,7 @@ static int msm_cpp_check_buf_type(struct msm_buf_mngr_info *buff_mgr_info,
{
int32_t num_output_bufs = 0;
uint32_t i = 0;
+
if (buff_mgr_info->type == MSM_CAMERA_BUF_MNGR_BUF_USER) {
new_frame->batch_info.cont_idx =
buff_mgr_info->index;
@@ -2009,7 +2055,7 @@ static void msm_cpp_update_frame_msg_phy_address(struct cpp_device *cpp_dev,
dup_we_mmu_pf_ptr_off = cpp_dev->payload_params.dup_we_mmu_pf_ptr_off;
ref_we_mmu_pf_ptr_off = cpp_dev->payload_params.ref_we_mmu_pf_ptr_off;
- pr_debug("%s: feature_mask 0x%x\n", __func__, new_frame->feature_mask);
+ pr_debug("feature_mask 0x%x\n", new_frame->feature_mask);
/* Update individual module status from feature mask */
tnr_enabled = ((new_frame->feature_mask & TNR_MASK) >> 2);
@@ -2460,6 +2506,7 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev,
/* get buffer for duplicate output */
if (new_frame->duplicate_output) {
int32_t iden = new_frame->duplicate_identity;
+
CPP_DBG("duplication enabled, dup_id=0x%x",
new_frame->duplicate_identity);
@@ -2599,7 +2646,7 @@ static int msm_cpp_cfg(struct cpp_device *cpp_dev,
int32_t rc = 0;
int32_t i = 0;
int32_t num_buff = sizeof(k_frame_info.output_buffer_info)/
- sizeof(struct msm_cpp_buffer_info_t);
+ sizeof(struct msm_cpp_buffer_info_t);
if (copy_from_user(&k_frame_info,
(void __user *)ioctl_ptr->ioctl_ptr,
sizeof(k_frame_info)))
@@ -2660,6 +2707,7 @@ static int msm_cpp_copy_from_ioctl_ptr(void *dst_ptr,
struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
{
int ret;
+
if ((ioctl_ptr->ioctl_ptr == NULL) || (ioctl_ptr->len == 0)) {
pr_err("%s: Wrong ioctl_ptr %pK / len %zu\n", __func__,
ioctl_ptr, ioctl_ptr->len);
@@ -2683,6 +2731,7 @@ static int msm_cpp_copy_from_ioctl_ptr(void *dst_ptr,
struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
{
int ret;
+
if ((ioctl_ptr->ioctl_ptr == NULL) || (ioctl_ptr->len == 0)) {
pr_err("%s: Wrong ioctl_ptr %pK / len %zu\n", __func__,
ioctl_ptr, ioctl_ptr->len);
@@ -2758,14 +2807,15 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg,
break;
default: {
if (ioctl_ptr == NULL) {
- pr_err("Wrong ioctl_ptr for cmd %u\n", cmd);
+ pr_err("Wrong ioctl_ptr %pK for cmd %u\n",
+ ioctl_ptr, cmd);
return -EINVAL;
}
*ioctl_ptr = arg;
if ((*ioctl_ptr == NULL) ||
- (*ioctl_ptr)->ioctl_ptr == NULL) {
- pr_err("Error invalid ioctl argument cmd %u", cmd);
+ ((*ioctl_ptr)->ioctl_ptr == NULL)) {
+ pr_err("Wrong arg %pK for cmd %u\n", arg, cmd);
return -EINVAL;
}
break;
@@ -3007,7 +3057,7 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd,
mutex_unlock(&cpp_dev->mutex);
return -EINVAL;
}
- if (VIDIOC_MSM_CPP_DELETE_STREAM_BUFF == cmd) {
+ if (cmd == VIDIOC_MSM_CPP_DELETE_STREAM_BUFF) {
for (j = 0; j < k_stream_buff_info.num_buffs; j++) {
msm_cpp_dequeue_buff(cpp_dev, buff_queue_info,
k_stream_buff_info.buffer_info[j].index,
@@ -3030,6 +3080,7 @@ STREAM_BUFF_END:
case VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO: {
uint32_t identity;
struct msm_cpp_buff_queue_info_t *buff_queue_info;
+
CPP_DBG("VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO\n");
if (ioctl_ptr->len != sizeof(uint32_t)) {
mutex_unlock(&cpp_dev->mutex);
@@ -3078,6 +3129,7 @@ STREAM_BUFF_END:
struct msm_device_queue *queue = &cpp_dev->eventData_q;
struct msm_queue_cmd *event_qcmd;
struct msm_cpp_frame_info_t *process_frame;
+
CPP_DBG("VIDIOC_MSM_CPP_GET_EVENTPAYLOAD\n");
event_qcmd = msm_dequeue(queue, list_eventdata, POP_FRONT);
if (!event_qcmd) {
@@ -3106,6 +3158,7 @@ STREAM_BUFF_END:
uint32_t msm_cpp_core_clk_idx;
struct msm_cpp_clock_settings_t clock_settings;
unsigned long clock_rate = 0;
+
CPP_DBG("VIDIOC_MSM_CPP_SET_CLOCK\n");
if (ioctl_ptr->len == 0) {
pr_err("ioctl_ptr->len is 0\n");
@@ -3184,6 +3237,7 @@ STREAM_BUFF_END:
break;
case VIDIOC_MSM_CPP_QUEUE_BUF: {
struct msm_pproc_queue_buf_info queue_buf_info;
+
CPP_DBG("VIDIOC_MSM_CPP_QUEUE_BUF\n");
if (ioctl_ptr->len != sizeof(struct msm_pproc_queue_buf_info)) {
@@ -3266,9 +3320,27 @@ STREAM_BUFF_END:
break;
case VIDIOC_MSM_CPP_IOMMU_ATTACH: {
if (cpp_dev->iommu_state == CPP_IOMMU_STATE_DETACHED) {
- rc = cam_smmu_ops(cpp_dev->iommu_hdl, CAM_SMMU_ATTACH);
+ struct msm_camera_smmu_attach_type cpp_attach_info;
+
+ memset(&cpp_attach_info, 0, sizeof(cpp_attach_info));
+ rc = msm_cpp_copy_from_ioctl_ptr(&cpp_attach_info,
+ ioctl_ptr);
if (rc < 0) {
- pr_err("%s:%dError iommu_attach_device failed\n",
+ ERR_COPY_FROM_USER();
+ return -EINVAL;
+ }
+
+ cpp_dev->security_mode = cpp_attach_info.attach;
+
+ if (cpp_dev->security_mode == SECURE_MODE) {
+ rc = cam_smmu_ops(cpp_dev->iommu_hdl,
+ CAM_SMMU_ATTACH_SEC_CPP);
+ } else {
+ rc = cam_smmu_ops(cpp_dev->iommu_hdl,
+ CAM_SMMU_ATTACH);
+ }
+ if (rc < 0) {
+ pr_err("%s:%diommu_attach_device failed\n",
__func__, __LINE__);
rc = -EINVAL;
break;
@@ -3284,10 +3356,28 @@ STREAM_BUFF_END:
case VIDIOC_MSM_CPP_IOMMU_DETACH: {
if ((cpp_dev->iommu_state == CPP_IOMMU_STATE_ATTACHED) &&
(cpp_dev->stream_cnt == 0)) {
- rc = cam_smmu_ops(cpp_dev->iommu_hdl, CAM_SMMU_DETACH);
+
+ struct msm_camera_smmu_attach_type cpp_attach_info;
+
+ memset(&cpp_attach_info, 0, sizeof(cpp_attach_info));
+ rc = msm_cpp_copy_from_ioctl_ptr(&cpp_attach_info,
+ ioctl_ptr);
if (rc < 0) {
- pr_err("%s:%dError iommu atach failed\n",
- __func__, __LINE__);
+ ERR_COPY_FROM_USER();
+ return -EINVAL;
+ }
+
+ cpp_dev->security_mode = cpp_attach_info.attach;
+
+ if (cpp_dev->security_mode == SECURE_MODE)
+ rc = cam_smmu_ops(cpp_dev->iommu_hdl,
+ CAM_SMMU_DETACH_SEC_CPP);
+ else
+ rc = cam_smmu_ops(cpp_dev->iommu_hdl,
+ CAM_SMMU_DETACH);
+ if (rc < 0) {
+ pr_err("%s:%diommu detach failed\n", __func__,
+ __LINE__);
rc = -EINVAL;
break;
}
@@ -3367,6 +3457,7 @@ static long msm_cpp_subdev_do_ioctl(
struct cpp_device *cpp_dev = v4l2_get_subdevdata(sd);
struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
struct msm_cpp_frame_info_t inst_info;
+
memset(&inst_info, 0, sizeof(struct msm_cpp_frame_info_t));
for (i = 0; i < MAX_ACTIVE_CPP_INSTANCE; i++) {
if (cpp_dev->cpp_subscribe_list[i].vfh == vfh) {
@@ -3735,6 +3826,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file,
struct msm_cpp_frame_info32_t inst_info;
struct v4l2_fh *vfh = NULL;
uint32_t i;
+
vfh = file->private_data;
memset(&inst_info, 0, sizeof(struct msm_cpp_frame_info32_t));
for (i = 0; i < MAX_ACTIVE_CPP_INSTANCE; i++) {
@@ -3978,6 +4070,7 @@ static int msm_cpp_update_gdscr_status(struct cpp_device *cpp_dev,
{
int rc = 0;
int value = 0;
+
if (!cpp_dev) {
pr_err("%s: cpp device invalid\n", __func__);
rc = -EINVAL;
@@ -4080,6 +4173,7 @@ static int cpp_probe(struct platform_device *pdev)
struct cpp_device *cpp_dev;
int rc = 0;
int i = 0;
+
CPP_DBG("E");
cpp_dev = kzalloc(sizeof(struct cpp_device), GFP_KERNEL);
@@ -4251,6 +4345,8 @@ static int cpp_probe(struct platform_device *pdev)
cpp_timer_callback, (unsigned long)&cpp_timer);
cpp_dev->fw_name_bin = NULL;
cpp_dev->max_timeout_trial_cnt = MSM_CPP_MAX_TIMEOUT_TRIAL;
+
+
if (rc == 0)
CPP_DBG("SUCCESS.");
else
@@ -4293,6 +4389,7 @@ static int cpp_device_remove(struct platform_device *dev)
{
struct v4l2_subdev *sd = platform_get_drvdata(dev);
struct cpp_device *cpp_dev;
+
if (!sd) {
pr_err("%s: Subdevice is NULL\n", __func__);
return 0;
@@ -4303,6 +4400,7 @@ static int cpp_device_remove(struct platform_device *dev)
pr_err("%s: cpp device is NULL\n", __func__);
return 0;
}
+
if (cpp_dev->fw) {
release_firmware(cpp_dev->fw);
cpp_dev->fw = NULL;
@@ -4366,6 +4464,7 @@ DEFINE_SIMPLE_ATTRIBUTE(cpp_debugfs_error, NULL,
static int msm_cpp_enable_debugfs(struct cpp_device *cpp_dev)
{
struct dentry *debugfs_base;
+
debugfs_base = debugfs_create_dir("msm_cpp", NULL);
if (!debugfs_base)
return -ENOMEM;
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index d5abe0202717..f46cc10cef46 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -169,6 +169,7 @@ struct msm_cpp_buff_queue_info_t {
uint32_t used;
uint16_t session_id;
uint16_t stream_id;
+ enum smmu_attach_mode security_mode;
struct list_head vb2_buff_head;
struct list_head native_buff_head;
};
@@ -234,6 +235,8 @@ struct cpp_device {
uint32_t min_clk_rate;
int iommu_hdl;
+ struct ion_client *ion_client;
+ enum smmu_attach_mode security_mode;
/* Reusing proven tasklet from msm isp */
atomic_t irq_cnt;
uint8_t taskletq_idx;
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c
index 56ddf8467d16..011d5bd88d90 100644
--- a/drivers/misc/hdcp.c
+++ b/drivers/misc/hdcp.c
@@ -65,7 +65,8 @@
#define REPEATER_AUTH_SEND_ACK_MESSAGE_ID 15
#define REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID 16
#define REPEATER_AUTH_STREAM_READY_MESSAGE_ID 17
-#define HDCP2P2_MAX_MESSAGES 18
+#define SKE_SEND_TYPE_ID 18
+#define HDCP2P2_MAX_MESSAGES 19
#define HDCP1_SET_KEY_MESSAGE_ID 202
#define HDCP1_SET_ENC_MESSAGE_ID 205
@@ -94,7 +95,7 @@
* minimum wait as per standard is 200 ms. keep it 300 ms
* to be on safe side.
*/
-#define SLEEP_SET_HW_KEY_MS 300
+#define SLEEP_SET_HW_KEY_MS 220
#define QSEECOM_ALIGN_SIZE 0x40
#define QSEECOM_ALIGN_MASK (QSEECOM_ALIGN_SIZE - 1)
@@ -187,6 +188,9 @@ static const struct hdcp_msg_data hdcp_msg_lookup[HDCP2P2_MAX_MESSAGES] = {
[SKE_SEND_EKS_MESSAGE_ID] = { 2,
{ {"Edkey_ks", 0x69318, 16}, {"riv", 0x69328, 8} },
0 },
+ [SKE_SEND_TYPE_ID] = { 1,
+ { {"type", 0x69494, 1} },
+ 0 },
[REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID] = { 4,
{ {"RxInfo", 0x69330, 2}, {"seq_num_V", 0x69332, 3},
{"V'", 0x69335, 16}, {"ridlist", 0x69345, 155} },
@@ -499,8 +503,10 @@ struct hdcp_lib_handle {
uint32_t tz_ctxhandle;
uint32_t hdcp_timeout;
uint32_t timeout_left;
+ uint32_t wait_timeout;
bool no_stored_km_flag;
bool feature_supported;
+ bool authenticated;
void *client_ctx;
struct hdcp_client_ops *client_ops;
struct mutex msg_lock;
@@ -521,7 +527,7 @@ struct hdcp_lib_handle {
enum hdcp_device_type device_type;
struct task_struct *thread;
- struct completion topo_wait;
+ struct completion poll_wait;
struct kthread_worker worker;
struct kthread_work wk_init;
@@ -529,7 +535,7 @@ struct hdcp_lib_handle {
struct kthread_work wk_msg_recvd;
struct kthread_work wk_timeout;
struct kthread_work wk_clean;
- struct kthread_work wk_topology;
+ struct kthread_work wk_wait;
struct kthread_work wk_stream;
int (*hdcp_app_init)(struct hdcp_lib_handle *handle);
@@ -574,6 +580,7 @@ static const char *hdcp_lib_message_name(int msg_id)
{15, "REPEATER_AUTH_SEND_ACK"},
{16, "REPEATER_AUTH_STREAM_MANAGE"},
{17, "REPEATER_AUTH_STREAM_READY"},
+ {18, "SKE_SEND_TYPE_ID"},
};
int i;
@@ -612,8 +619,14 @@ static int hdcp_lib_get_next_message(struct hdcp_lib_handle *handle,
case LC_SEND_L_PRIME_MESSAGE_ID:
return SKE_SEND_EKS_MESSAGE_ID;
case SKE_SEND_EKS_MESSAGE_ID:
+ if (!handle->repeater_flag)
+ return SKE_SEND_TYPE_ID;
+ case SKE_SEND_TYPE_ID:
case REPEATER_AUTH_STREAM_READY_MESSAGE_ID:
case REPEATER_AUTH_SEND_ACK_MESSAGE_ID:
+ if (!handle->repeater_flag)
+ return INVALID_MESSAGE_ID;
+
if (data->cmd == HDMI_HDCP_WKUP_CMD_SEND_MESSAGE)
return REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID;
else
@@ -628,6 +641,33 @@ static int hdcp_lib_get_next_message(struct hdcp_lib_handle *handle,
}
}
+static void hdcp_lib_wait_for_response(struct hdcp_lib_handle *handle,
+ struct hdmi_hdcp_wakeup_data *data)
+{
+ switch (handle->last_msg) {
+ case AKE_SEND_H_PRIME_MESSAGE_ID:
+ if (handle->no_stored_km_flag)
+ handle->wait_timeout = HZ;
+ else
+ handle->wait_timeout = HZ / 4;
+ break;
+ case AKE_SEND_PAIRING_INFO_MESSAGE_ID:
+ handle->wait_timeout = HZ / 4;
+ break;
+ case REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID:
+ if (!handle->authenticated)
+ handle->wait_timeout = HZ * 3;
+ else
+ handle->wait_timeout = 0;
+ break;
+ default:
+ handle->wait_timeout = 0;
+ }
+
+ if (handle->wait_timeout)
+ queue_kthread_work(&handle->worker, &handle->wk_wait);
+}
+
static void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle,
struct hdmi_hdcp_wakeup_data *data)
{
@@ -639,43 +679,42 @@ static void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle,
data->abort_mask = REAUTH_REQ | LINK_INTEGRITY_FAILURE;
- if (data->cmd == HDMI_HDCP_WKUP_CMD_SEND_MESSAGE ||
- data->cmd == HDMI_HDCP_WKUP_CMD_RECV_MESSAGE ||
- data->cmd == HDMI_HDCP_WKUP_CMD_LINK_POLL) {
+ if (data->cmd == HDMI_HDCP_WKUP_CMD_RECV_MESSAGE ||
+ data->cmd == HDMI_HDCP_WKUP_CMD_LINK_POLL)
handle->last_msg = hdcp_lib_get_next_message(handle, data);
+ if (handle->last_msg != INVALID_MESSAGE_ID &&
+ data->cmd != HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS &&
+ data->cmd != HDMI_HDCP_WKUP_CMD_STATUS_FAILED) {
+ u32 msg_num, rx_status;
+ const struct hdcp_msg_part *msg;
+
pr_debug("lib->client: %s (%s)\n",
hdmi_hdcp_cmd_to_str(data->cmd),
hdcp_lib_message_name(handle->last_msg));
- if (handle->last_msg > INVALID_MESSAGE_ID &&
- handle->last_msg < HDCP2P2_MAX_MESSAGES) {
- u32 msg_num, rx_status;
- const struct hdcp_msg_part *msg;
-
- data->message_data = &hdcp_msg_lookup[handle->last_msg];
+ data->message_data = &hdcp_msg_lookup[handle->last_msg];
- msg_num = data->message_data->num_messages;
- msg = data->message_data->messages;
- rx_status = data->message_data->rx_status;
+ msg_num = data->message_data->num_messages;
+ msg = data->message_data->messages;
+ rx_status = data->message_data->rx_status;
- pr_debug("rxstatus 0x%x\n", rx_status);
- pr_debug("%10s | %6s | %4s\n", "name", "offset", "len");
+ pr_debug("%10s | %6s | %4s\n", "name", "offset", "len");
- for (i = 0; i < msg_num; i++)
- pr_debug("%10s | %6x | %4d\n",
- msg[i].name, msg[i].offset,
- msg[i].length);
- }
+ for (i = 0; i < msg_num; i++)
+ pr_debug("%10s | %6x | %4d\n",
+ msg[i].name, msg[i].offset,
+ msg[i].length);
} else {
- pr_debug("lib->client: %s\n",
- hdmi_hdcp_cmd_to_str(data->cmd));
+ pr_debug("lib->client: %s\n", hdmi_hdcp_cmd_to_str(data->cmd));
}
rc = handle->client_ops->wakeup(data);
if (rc)
pr_err("error sending %s to client\n",
hdmi_hdcp_cmd_to_str(data->cmd));
+
+ hdcp_lib_wait_for_response(handle, data);
}
static inline void hdcp_lib_send_message(struct hdcp_lib_handle *handle)
@@ -1286,6 +1325,8 @@ static int hdcp_lib_txmtr_init_legacy(struct hdcp_lib_handle *handle)
hdcp_lib_message_name((int)rsp_buf->message[0]),
jiffies_to_msecs(jiffies));
+ handle->last_msg = (int)rsp_buf->message[0];
+
/* send the response to HDMI driver */
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
memcpy(handle->listener_buf, (unsigned char *)rsp_buf->message,
@@ -1404,6 +1445,8 @@ static int hdcp_lib_start_auth(struct hdcp_lib_handle *handle)
hdcp_lib_message_name((int)rsp_buf->message[0]),
jiffies_to_msecs(jiffies));
+ handle->last_msg = (int)rsp_buf->message[0];
+
/* send the response to HDMI driver */
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
memcpy(handle->listener_buf, (unsigned char *)rsp_buf->message,
@@ -1470,6 +1513,8 @@ static void hdcp_lib_stream(struct hdcp_lib_handle *handle)
pr_debug("message received from TZ: %s\n",
hdcp_lib_message_name((int)rsp_buf->msg[0]));
+ handle->last_msg = (int)rsp_buf->msg[0];
+
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
memcpy(handle->listener_buf, (unsigned char *)rsp_buf->msg,
rsp_buf->msglen);
@@ -1550,11 +1595,11 @@ static void hdcp_lib_check_worker_status(struct hdcp_lib_handle *handle)
if (handle->worker.current_work == &handle->wk_clean)
pr_debug("clean work executing\n");
- if (!list_empty(&handle->wk_topology.node))
- pr_debug("topology work queued\n");
+ if (!list_empty(&handle->wk_wait.node))
+ pr_debug("wait work queued\n");
- if (handle->worker.current_work == &handle->wk_topology)
- pr_debug("topology work executing\n");
+ if (handle->worker.current_work == &handle->wk_wait)
+ pr_debug("wait work executing\n");
if (!list_empty(&handle->wk_stream.node))
pr_debug("stream work queued\n");
@@ -1613,7 +1658,7 @@ static void hdcp_lib_update_exec_type(void *ctx, bool tethered)
mutex_unlock(&handle->wakeup_mutex);
}
-static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
+static int hdcp_lib_wakeup_thread(struct hdcp_lib_wakeup_data *data)
{
struct hdcp_lib_handle *handle;
int rc = 0;
@@ -1630,8 +1675,9 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
handle->wakeup_cmd = data->cmd;
handle->timeout_left = data->timeout;
- pr_debug("client->lib: %s\n",
- hdcp_lib_cmd_to_str(handle->wakeup_cmd));
+ pr_debug("client->lib: %s (%s)\n",
+ hdcp_lib_cmd_to_str(data->cmd),
+ hdcp_lib_message_name(handle->last_msg));
rc = hdcp_lib_check_valid_state(handle);
if (rc)
@@ -1655,8 +1701,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
}
mutex_unlock(&handle->msg_lock);
- if (!completion_done(&handle->topo_wait))
- complete_all(&handle->topo_wait);
+ if (!completion_done(&handle->poll_wait))
+ complete_all(&handle->poll_wait);
switch (handle->wakeup_cmd) {
case HDCP_LIB_WKUP_CMD_START:
@@ -1719,22 +1765,30 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle)
cdata.context = handle->client_ctx;
switch (handle->last_msg_sent) {
- case SKE_SEND_EKS_MESSAGE_ID:
- if (handle->repeater_flag) {
- if (!atomic_read(&handle->hdcp_off))
- queue_kthread_work(&handle->worker,
- &handle->wk_topology);
- }
-
+ case SKE_SEND_TYPE_ID:
if (!hdcp_lib_enable_encryption(handle)) {
+ handle->authenticated = true;
+
cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS;
hdcp_lib_wakeup_client(handle, &cdata);
+ }
+ /* poll for link check */
+ cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL;
+ break;
+ case SKE_SEND_EKS_MESSAGE_ID:
+ if (handle->repeater_flag) {
/* poll for link check */
cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL;
} else {
- if (!atomic_read(&handle->hdcp_off))
- HDCP_LIB_EXECUTE(clean);
+ memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
+ handle->listener_buf[0] = SKE_SEND_TYPE_ID;
+ handle->msglen = 2;
+ cdata.cmd = HDMI_HDCP_WKUP_CMD_SEND_MESSAGE;
+ cdata.send_msg_buf = handle->listener_buf;
+ cdata.send_msg_len = handle->msglen;
+ handle->last_msg = hdcp_lib_get_next_message(handle,
+ &cdata);
}
break;
case REPEATER_AUTH_SEND_ACK_MESSAGE_ID:
@@ -1915,6 +1969,8 @@ static void hdcp_lib_clean(struct hdcp_lib_handle *handle)
return;
}
+ handle->authenticated = false;
+
hdcp_lib_txmtr_deinit(handle);
if (!handle->legacy_app)
hdcp_lib_session_deinit(handle);
@@ -2040,6 +2096,13 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
(rc == 0) && (rsp_buf->status == 0)) {
pr_debug("Got Auth_Stream_Ready, nothing sent to rx\n");
+ if (!hdcp_lib_enable_encryption(handle)) {
+ handle->authenticated = true;
+
+ cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS;
+ hdcp_lib_wakeup_client(handle, &cdata);
+ }
+
cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL;
goto exit;
}
@@ -2057,6 +2120,8 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
hdcp_lib_message_name((int)rsp_buf->msg[0]),
jiffies_to_msecs(jiffies));
+ handle->last_msg = (int)rsp_buf->msg[0];
+
/* set the flag if response is AKE_No_Stored_km */
if (((int)rsp_buf->msg[0] == AKE_NO_STORED_KM_MESSAGE_ID)) {
pr_debug("Setting no_stored_km_flag\n");
@@ -2101,12 +2166,11 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
hdcp_lib_msg_recvd(handle);
}
-static void hdcp_lib_topology_work(struct kthread_work *work)
+static void hdcp_lib_wait_work(struct kthread_work *work)
{
u32 timeout;
struct hdcp_lib_handle *handle = container_of(work,
- struct hdcp_lib_handle,
- wk_topology);
+ struct hdcp_lib_handle, wk_wait);
if (!handle) {
pr_err("invalid input\n");
@@ -2123,14 +2187,17 @@ static void hdcp_lib_topology_work(struct kthread_work *work)
return;
}
- reinit_completion(&handle->topo_wait);
- timeout = wait_for_completion_timeout(&handle->topo_wait, HZ * 3);
+ reinit_completion(&handle->poll_wait);
+ timeout = wait_for_completion_timeout(&handle->poll_wait,
+ handle->wait_timeout);
if (!timeout) {
- pr_err("topology receiver id list timeout\n");
+ pr_err("wait timeout\n");
if (!atomic_read(&handle->hdcp_off))
HDCP_LIB_EXECUTE(clean);
}
+
+ handle->wait_timeout = 0;
}
bool hdcp1_check_if_supported_load_app(void)
@@ -2266,7 +2333,7 @@ int hdcp_library_register(struct hdcp_register_data *data)
/* populate ops to be called by client */
data->txmtr_ops->feature_supported = hdcp_lib_client_feature_supported;
- data->txmtr_ops->wakeup = hdcp_lib_wakeup;
+ data->txmtr_ops->wakeup = hdcp_lib_wakeup_thread;
data->txmtr_ops->update_exec_type = hdcp_lib_update_exec_type;
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
@@ -2296,10 +2363,10 @@ int hdcp_library_register(struct hdcp_register_data *data)
init_kthread_work(&handle->wk_msg_recvd, hdcp_lib_msg_recvd_work);
init_kthread_work(&handle->wk_timeout, hdcp_lib_manage_timeout_work);
init_kthread_work(&handle->wk_clean, hdcp_lib_cleanup_work);
- init_kthread_work(&handle->wk_topology, hdcp_lib_topology_work);
+ init_kthread_work(&handle->wk_wait, hdcp_lib_wait_work);
init_kthread_work(&handle->wk_stream, hdcp_lib_query_stream_work);
- init_completion(&handle->topo_wait);
+ init_completion(&handle->poll_wait);
handle->listener_buf = kzalloc(MAX_TX_MESSAGE_SIZE, GFP_KERNEL);
if (!(handle->listener_buf)) {
diff --git a/drivers/misc/qcom/qdsp6v2/Makefile b/drivers/misc/qcom/qdsp6v2/Makefile
index 7006ff4a272f..90a123adbb7f 100644
--- a/drivers/misc/qcom/qdsp6v2/Makefile
+++ b/drivers/misc/qcom/qdsp6v2/Makefile
@@ -1,5 +1,6 @@
-obj-$(CONFIG_MSM_QDSP6V2_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o g711mlaw_in.o g711alaw_in.o audio_utils.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_alac.o audio_ape.o audio_utils_aio.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_g711mlaw.o audio_g711alaw.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o audio_hwacc_effects.o
obj-$(CONFIG_MSM_ULTRASOUND) += ultrasound/
diff --git a/drivers/misc/qcom/qdsp6v2/audio_amrnb.c b/drivers/misc/qcom/qdsp6v2/audio_amrnb.c
index 78bcdb74af0e..9e4f74bfacd9 100644
--- a/drivers/misc/qcom/qdsp6v2/audio_amrnb.c
+++ b/drivers/misc/qcom/qdsp6v2/audio_amrnb.c
@@ -14,6 +14,9 @@
* GNU General Public License for more details.
*
*/
+
+#include <linux/types.h>
+#include <linux/compat.h>
#include "audio_utils_aio.h"
static struct miscdevice audio_amrnb_misc;
@@ -68,6 +71,52 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return rc;
}
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct q6audio_aio *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START: {
+ pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+ audio, audio->ac->session);
+ if (audio->feedback == NON_TUNNEL_MODE) {
+ /* Configure PCM output block */
+ rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+ audio->pcm_cfg.sample_rate,
+ audio->pcm_cfg.channel_count);
+ if (rc < 0) {
+ pr_err("%s: pcm output block config failed rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ }
+
+ rc = audio_aio_enable(audio);
+ audio->eos_rsp = 0;
+ audio->eos_flag = 0;
+ if (!rc) {
+ audio->enabled = 1;
+ } else {
+ audio->enabled = 0;
+ pr_err("%s: Audio Start procedure failed rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ pr_debug("AUDIO_START success enable[%d]\n", audio->enabled);
+ if (audio->stopped == 1)
+ audio->stopped = 0;
+ break;
+ }
+ default:
+ pr_debug("%s[%pK]: Calling compat ioctl\n", __func__, audio);
+ rc = audio->codec_compat_ioctl(file, cmd, arg);
+ }
+ return rc;
+}
+
+
static int audio_open(struct inode *inode, struct file *file)
{
struct q6audio_aio *audio = NULL;
@@ -155,6 +204,7 @@ static const struct file_operations audio_amrnb_fops = {
.release = audio_aio_release,
.unlocked_ioctl = audio_ioctl,
.fsync = audio_aio_fsync,
+ .compat_ioctl = audio_compat_ioctl,
};
static struct miscdevice audio_amrnb_misc = {
diff --git a/drivers/misc/qcom/qdsp6v2/audio_amrwb.c b/drivers/misc/qcom/qdsp6v2/audio_amrwb.c
index 2283cf26bda9..2403dbbe426b 100644
--- a/drivers/misc/qcom/qdsp6v2/audio_amrwb.c
+++ b/drivers/misc/qcom/qdsp6v2/audio_amrwb.c
@@ -15,6 +15,8 @@
*
*/
+#include <linux/compat.h>
+#include <linux/types.h>
#include "audio_utils_aio.h"
static struct miscdevice audio_amrwb_misc;
@@ -71,6 +73,53 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return rc;
}
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct q6audio_aio *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START: {
+ pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+ audio, audio->ac->session);
+ if (audio->feedback == NON_TUNNEL_MODE) {
+ /* Configure PCM output block */
+ rc = q6asm_enc_cfg_blk_pcm(audio->ac,
+ audio->pcm_cfg.sample_rate,
+ audio->pcm_cfg.channel_count);
+ if (rc < 0) {
+ pr_err("%s: pcm output block config failed rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ }
+
+ rc = audio_aio_enable(audio);
+ audio->eos_rsp = 0;
+ audio->eos_flag = 0;
+ if (!rc) {
+ audio->enabled = 1;
+ } else {
+ audio->enabled = 0;
+ pr_err("%s: Audio Start procedure failed rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ pr_debug("%s: AUDIO_START sessionid[%d]enable[%d]\n", __func__,
+ audio->ac->session,
+ audio->enabled);
+ if (audio->stopped == 1)
+ audio->stopped = 0;
+ break;
+ }
+ default:
+ pr_debug("%s[%pK]: Calling compat ioctl\n", __func__, audio);
+ rc = audio->codec_compat_ioctl(file, cmd, arg);
+ }
+ return rc;
+}
+
static int audio_open(struct inode *inode, struct file *file)
{
struct q6audio_aio *audio = NULL;
@@ -159,6 +208,7 @@ static const struct file_operations audio_amrwb_fops = {
.release = audio_aio_release,
.unlocked_ioctl = audio_ioctl,
.fsync = audio_aio_fsync,
+ .compat_ioctl = audio_compat_ioctl,
};
static struct miscdevice audio_amrwb_misc = {
diff --git a/drivers/misc/qcom/qdsp6v2/audio_g711alaw.c b/drivers/misc/qcom/qdsp6v2/audio_g711alaw.c
new file mode 100644
index 000000000000..6f02654d3d4c
--- /dev/null
+++ b/drivers/misc/qcom/qdsp6v2/audio_g711alaw.c
@@ -0,0 +1,396 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+*/
+
+#include <linux/types.h>
+#include <linux/msm_audio_g711_dec.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_g711alaw_misc;
+static struct ws_mgr audio_g711_ws_mgr;
+
+static const struct file_operations audio_g711_debug_fops = {
+ .read = audio_aio_debug_read,
+ .open = audio_aio_debug_open,
+};
+
+static struct dentry *config_debugfs_create_file(const char *name, void *data)
+{
+ return debugfs_create_file(name, S_IFREG | S_IRUGO,
+ NULL, (void *)data, &audio_g711_debug_fops);
+}
+
+static int g711_channel_map(u8 *channel_mapping, uint32_t channels);
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+ void *arg)
+{
+ struct q6audio_aio *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START: {
+ struct asm_g711_dec_cfg g711_dec_cfg;
+ struct msm_audio_g711_dec_config *g711_dec_config;
+ u8 channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+
+ memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+ memset(&g711_dec_cfg, 0, sizeof(g711_dec_cfg));
+
+ if (g711_channel_map(channel_mapping,
+ audio->pcm_cfg.channel_count)) {
+ pr_err("%s: setting channel map failed %d\n",
+ __func__, audio->pcm_cfg.channel_count);
+ }
+
+ pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+ audio, audio->ac->session);
+ if (audio->feedback == NON_TUNNEL_MODE) {
+ /* Configure PCM output block */
+ rc = q6asm_enc_cfg_blk_pcm_v2(audio->ac,
+ audio->pcm_cfg.sample_rate,
+ audio->pcm_cfg.channel_count,
+ 16, /*bits per sample*/
+ false, false, channel_mapping);
+ if (rc < 0) {
+ pr_err("%s: pcm output block config failed rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ }
+ g711_dec_config =
+ (struct msm_audio_g711_dec_config *)audio->codec_cfg;
+ g711_dec_cfg.sample_rate = g711_dec_config->sample_rate;
+ /* Configure Media format block */
+ rc = q6asm_media_format_block_g711(audio->ac, &g711_dec_cfg,
+ audio->ac->stream_id);
+ if (rc < 0) {
+ pr_err("%s: cmd media format block failed rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ rc = audio_aio_enable(audio);
+ audio->eos_rsp = 0;
+ audio->eos_flag = 0;
+ if (!rc) {
+ audio->enabled = 1;
+ } else {
+ audio->enabled = 0;
+ pr_err("%s: Audio Start procedure failed rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ pr_debug("%s: AUDIO_START success enable[%d]\n",
+ __func__, audio->enabled);
+ if (audio->stopped == 1)
+ audio->stopped = 0;
+ break;
+ }
+ default:
+ pr_debug("%s: Unknown ioctl cmd = %d", __func__, cmd);
+ break;
+ }
+ return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct q6audio_aio *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START: {
+ rc = audio_ioctl_shared(file, cmd, (void *)arg);
+ break;
+ }
+ case AUDIO_GET_G711_DEC_CONFIG: {
+ if (copy_to_user((void *)arg, audio->codec_cfg,
+ sizeof(struct msm_audio_g711_dec_config))) {
+ pr_err("%s: copy_to_user for AUDIO_GET_G711_DEC_CONFIG failed\n",
+ __func__);
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case AUDIO_SET_G711_DEC_CONFIG: {
+ if (copy_from_user(audio->codec_cfg, (void *)arg,
+ sizeof(struct msm_audio_g711_dec_config))) {
+ pr_err("%s: copy_from_user for AUDIO_SET_G711_DEC_CONFIG failed\n",
+ __func__);
+ rc = -EFAULT;
+ }
+ break;
+ }
+ default: {
+ rc = audio->codec_ioctl(file, cmd, arg);
+ if (rc)
+ pr_err("%s: Failed in audio_aio_ioctl: %d cmd=%d\n",
+ __func__, rc, cmd);
+ break;
+ }
+ }
+ return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_g711_dec_config_32 {
+ u32 sample_rate;
+};
+
+enum {
+ AUDIO_SET_G711_DEC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+ (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_g711_dec_config_32),
+ AUDIO_GET_G711_DEC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+ (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_g711_dec_config_32)
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct q6audio_aio *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START: {
+ rc = audio_ioctl_shared(file, cmd, (void *)arg);
+ break;
+ }
+ case AUDIO_GET_G711_DEC_CONFIG_32: {
+ struct msm_audio_g711_dec_config *g711_dec_config;
+ struct msm_audio_g711_dec_config_32 g711_dec_config_32;
+
+ memset(&g711_dec_config_32, 0, sizeof(g711_dec_config_32));
+
+ g711_dec_config =
+ (struct msm_audio_g711_dec_config *)audio->codec_cfg;
+ g711_dec_config_32.sample_rate = g711_dec_config->sample_rate;
+
+ if (copy_to_user((void *)arg, &g711_dec_config_32,
+ sizeof(g711_dec_config_32))) {
+ pr_err("%s: copy_to_user for AUDIO_GET_G711_DEC_CONFIG_32 failed\n",
+ __func__);
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case AUDIO_SET_G711_DEC_CONFIG_32: {
+ struct msm_audio_g711_dec_config *g711_dec_config;
+ struct msm_audio_g711_dec_config_32 g711_dec_config_32;
+
+ memset(&g711_dec_config_32, 0, sizeof(g711_dec_config_32));
+
+ if (copy_from_user(&g711_dec_config_32, (void *)arg,
+ sizeof(g711_dec_config_32))) {
+ pr_err("%s: copy_from_user for AUDIO_SET_G711_DEC_CONFIG_32 failed\n",
+ __func__);
+ rc = -EFAULT;
+ break;
+ }
+
+ g711_dec_config =
+ (struct msm_audio_g711_dec_config *)audio->codec_cfg;
+ g711_dec_config->sample_rate = g711_dec_config_32.sample_rate;
+
+ break;
+ }
+ default: {
+ rc = audio->codec_compat_ioctl(file, cmd, arg);
+ if (rc)
+ pr_err("%s: Failed in audio_aio_compat_ioctl: %d cmd=%d\n",
+ __func__, rc, cmd);
+ break;
+ }
+ }
+ return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+ struct q6audio_aio *audio = NULL;
+ int rc = 0;
+ /* 4 bytes represents decoder number, 1 byte for terminate string */
+ char name[sizeof "msm_g711_" + 5];
+
+ audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+ if (!audio)
+ return -ENOMEM;
+ audio->codec_cfg = kzalloc(sizeof(struct msm_audio_g711_dec_config),
+ GFP_KERNEL);
+ if (!audio->codec_cfg) {
+ kfree(audio);
+ return -ENOMEM;
+ }
+
+ audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+ audio->miscdevice = &audio_g711alaw_misc;
+ audio->wakelock_voted = false;
+ audio->audio_ws_mgr = &audio_g711_ws_mgr;
+
+ init_waitqueue_head(&audio->event_wait);
+
+ audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+ (void *)audio);
+
+ if (!audio->ac) {
+ pr_err("%s: Could not allocate memory for audio client\n",
+ __func__);
+ kfree(audio->codec_cfg);
+ kfree(audio);
+ return -ENOMEM;
+ }
+ rc = audio_aio_open(audio, file);
+ if (rc < 0) {
+ pr_err("%s: audio_aio_open rc=%d\n",
+ __func__, rc);
+ goto fail;
+ }
+ /* open in T/NT mode */ /*foramt:G711_ALAW*/
+ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+ rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+ FORMAT_G711_ALAW_FS);
+ if (rc < 0) {
+ pr_err("%s: NT mode Open failed rc=%d\n", __func__, rc);
+ goto fail;
+ }
+ audio->feedback = NON_TUNNEL_MODE;
+ /* open G711 decoder, expected frames is always 1*/
+ audio->buf_cfg.frames_per_buf = 0x01;
+ audio->buf_cfg.meta_info_enable = 0x01;
+ } else if ((file->f_mode & FMODE_WRITE) &&
+ !(file->f_mode & FMODE_READ)) {
+ rc = q6asm_open_write(audio->ac, FORMAT_G711_ALAW_FS);
+ if (rc < 0) {
+ pr_err("%s: T mode Open failed rc=%d\n", __func__, rc);
+ goto fail;
+ }
+ audio->feedback = TUNNEL_MODE;
+ audio->buf_cfg.meta_info_enable = 0x00;
+ } else {
+ pr_err("%s: %d mode is not supported mode\n",
+ __func__, file->f_mode);
+ rc = -EACCES;
+ goto fail;
+ }
+
+ snprintf(name, sizeof(name), "msm_g711_%04x", audio->ac->session);
+ audio->dentry = config_debugfs_create_file(name, (void *)audio);
+
+ if (IS_ERR_OR_NULL(audio->dentry))
+ pr_debug("%s: debugfs_create_file failed\n", __func__);
+ pr_debug("%s: g711dec success mode[%d]session[%d]\n", __func__,
+ audio->feedback,
+ audio->ac->session);
+ return rc;
+fail:
+ q6asm_audio_client_free(audio->ac);
+ kfree(audio->codec_cfg);
+ kfree(audio);
+ return rc;
+}
+
+static int g711_channel_map(u8 *channel_mapping, uint32_t channels)
+{
+ u8 *lchannel_mapping;
+
+ lchannel_mapping = channel_mapping;
+ pr_debug("%s: channels passed: %d\n", __func__, channels);
+ if (channels == 1) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ } else if (channels == 2) {
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channels == 3) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ } else if (channels == 4) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[3] = PCM_CHANNEL_CS;
+ } else if (channels == 5) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[3] = PCM_CHANNEL_LS;
+ lchannel_mapping[4] = PCM_CHANNEL_RS;
+ } else if (channels == 6) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[3] = PCM_CHANNEL_LS;
+ lchannel_mapping[4] = PCM_CHANNEL_RS;
+ lchannel_mapping[5] = PCM_CHANNEL_LFE;
+ } else if (channels == 7) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[3] = PCM_CHANNEL_LS;
+ lchannel_mapping[4] = PCM_CHANNEL_RS;
+ lchannel_mapping[5] = PCM_CHANNEL_CS;
+ lchannel_mapping[6] = PCM_CHANNEL_LFE;
+ } else if (channels == 8) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FLC;
+ lchannel_mapping[2] = PCM_CHANNEL_FRC;
+ lchannel_mapping[3] = PCM_CHANNEL_FL;
+ lchannel_mapping[4] = PCM_CHANNEL_FR;
+ lchannel_mapping[5] = PCM_CHANNEL_LS;
+ lchannel_mapping[6] = PCM_CHANNEL_RS;
+ lchannel_mapping[7] = PCM_CHANNEL_LFE;
+ } else {
+ pr_err("%s: ERROR.unsupported num_ch = %u\n",
+ __func__, channels);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static const struct file_operations audio_g711_fops = {
+ .owner = THIS_MODULE,
+ .open = audio_open,
+ .release = audio_aio_release,
+ .unlocked_ioctl = audio_ioctl,
+ .compat_ioctl = audio_compat_ioctl,
+ .fsync = audio_aio_fsync,
+};
+
+static struct miscdevice audio_g711alaw_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "msm_g711alaw",
+ .fops = &audio_g711_fops,
+};
+
+static int __init audio_g711alaw_init(void)
+{
+ int ret = misc_register(&audio_g711alaw_misc);
+
+ if (ret == 0)
+ device_init_wakeup(audio_g711alaw_misc.this_device, true);
+ audio_g711_ws_mgr.ref_cnt = 0;
+ mutex_init(&audio_g711_ws_mgr.ws_lock);
+
+ return ret;
+}
+static void __exit audio_g711alaw_exit(void)
+{
+ misc_deregister(&audio_g711alaw_misc);
+ mutex_destroy(&audio_g711_ws_mgr.ws_lock);
+}
+
+device_initcall(audio_g711alaw_init);
+__exitcall(audio_g711alaw_exit);
diff --git a/drivers/misc/qcom/qdsp6v2/audio_g711mlaw.c b/drivers/misc/qcom/qdsp6v2/audio_g711mlaw.c
new file mode 100644
index 000000000000..cae2490feb7a
--- /dev/null
+++ b/drivers/misc/qcom/qdsp6v2/audio_g711mlaw.c
@@ -0,0 +1,396 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+*/
+
+#include <linux/types.h>
+#include <linux/msm_audio_g711_dec.h>
+#include <linux/compat.h>
+#include "audio_utils_aio.h"
+
+static struct miscdevice audio_g711mlaw_misc;
+static struct ws_mgr audio_g711_ws_mgr;
+
+static const struct file_operations audio_g711_debug_fops = {
+ .read = audio_aio_debug_read,
+ .open = audio_aio_debug_open,
+};
+
+static struct dentry *config_debugfs_create_file(const char *name, void *data)
+{
+ return debugfs_create_file(name, S_IFREG | S_IRUGO,
+ NULL, (void *)data, &audio_g711_debug_fops);
+}
+
+static int g711_channel_map(u8 *channel_mapping, uint32_t channels);
+
+static long audio_ioctl_shared(struct file *file, unsigned int cmd,
+ void *arg)
+{
+ struct q6audio_aio *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START: {
+ struct asm_g711_dec_cfg g711_dec_cfg;
+ struct msm_audio_g711_dec_config *g711_dec_config;
+ u8 channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+
+ memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+ memset(&g711_dec_cfg, 0, sizeof(g711_dec_cfg));
+
+ if (g711_channel_map(channel_mapping,
+ audio->pcm_cfg.channel_count)) {
+ pr_err("%s: setting channel map failed %d\n",
+ __func__, audio->pcm_cfg.channel_count);
+ }
+
+ pr_debug("%s[%pK]: AUDIO_START session_id[%d]\n", __func__,
+ audio, audio->ac->session);
+ if (audio->feedback == NON_TUNNEL_MODE) {
+ /* Configure PCM output block */
+ rc = q6asm_enc_cfg_blk_pcm_v2(audio->ac,
+ audio->pcm_cfg.sample_rate,
+ audio->pcm_cfg.channel_count,
+ 16, /*bits per sample*/
+ false, false, channel_mapping);
+ if (rc < 0) {
+ pr_err("%s: pcm output block config failed rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ }
+ g711_dec_config =
+ (struct msm_audio_g711_dec_config *)audio->codec_cfg;
+ g711_dec_cfg.sample_rate = g711_dec_config->sample_rate;
+ /* Configure Media format block */
+ rc = q6asm_media_format_block_g711(audio->ac, &g711_dec_cfg,
+ audio->ac->stream_id);
+ if (rc < 0) {
+ pr_err("%s: cmd media format block failed rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ rc = audio_aio_enable(audio);
+ audio->eos_rsp = 0;
+ audio->eos_flag = 0;
+ if (!rc) {
+ audio->enabled = 1;
+ } else {
+ audio->enabled = 0;
+ pr_err("%s: Audio Start procedure failed rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ pr_debug("%s: AUDIO_START success enable[%d]\n",
+ __func__, audio->enabled);
+ if (audio->stopped == 1)
+ audio->stopped = 0;
+ break;
+ }
+ default:
+ pr_debug("%s: Unknown ioctl cmd = %d", __func__, cmd);
+ break;
+ }
+ return rc;
+}
+
+static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct q6audio_aio *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START: {
+ rc = audio_ioctl_shared(file, cmd, (void *)arg);
+ break;
+ }
+ case AUDIO_GET_G711_DEC_CONFIG: {
+ if (copy_to_user((void *)arg, audio->codec_cfg,
+ sizeof(struct msm_audio_g711_dec_config))) {
+ pr_err("%s: AUDIO_GET_G711_DEC_CONFIG failed\n",
+ __func__);
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case AUDIO_SET_G711_DEC_CONFIG: {
+ if (copy_from_user(audio->codec_cfg, (void *)arg,
+ sizeof(struct msm_audio_g711_dec_config))) {
+ pr_err("%s: AUDIO_SET_G711_DEC_CONFIG failed\n",
+ __func__);
+ rc = -EFAULT;
+ }
+ break;
+ }
+ default: {
+ rc = audio->codec_ioctl(file, cmd, arg);
+ if (rc)
+ pr_err("%s: Failed in audio_aio_ioctl: %d cmd=%d\n",
+ __func__, rc, cmd);
+ break;
+ }
+ }
+ return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_g711_dec_config_32 {
+ u32 sample_rate;
+};
+
+enum {
+ AUDIO_SET_G711_DEC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+ (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_g711_dec_config_32),
+ AUDIO_GET_G711_DEC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+ (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_g711_dec_config_32)
+};
+
+static long audio_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct q6audio_aio *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START: {
+ rc = audio_ioctl_shared(file, cmd, (void *)arg);
+ break;
+ }
+ case AUDIO_GET_G711_DEC_CONFIG_32: {
+ struct msm_audio_g711_dec_config *g711_dec_config;
+ struct msm_audio_g711_dec_config_32 g711_dec_config_32;
+
+ memset(&g711_dec_config_32, 0, sizeof(g711_dec_config_32));
+
+ g711_dec_config =
+ (struct msm_audio_g711_dec_config *)audio->codec_cfg;
+ g711_dec_config_32.sample_rate = g711_dec_config->sample_rate;
+
+ if (copy_to_user((void *)arg, &g711_dec_config_32,
+ sizeof(g711_dec_config_32))) {
+ pr_err("%s: copy_to_user for AUDIO_GET_G711_DEC_CONFIG failed\n",
+ __func__);
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case AUDIO_SET_G711_DEC_CONFIG_32: {
+ struct msm_audio_g711_dec_config *g711_dec_config;
+ struct msm_audio_g711_dec_config_32 g711_dec_config_32;
+
+ memset(&g711_dec_config_32, 0, sizeof(g711_dec_config_32));
+
+ if (copy_from_user(&g711_dec_config_32, (void *)arg,
+ sizeof(g711_dec_config_32))) {
+ pr_err("%s: copy_from_user for AUDIO_SET_G711_DEC_CONFIG failed\n",
+ __func__);
+ rc = -EFAULT;
+ break;
+ }
+ g711_dec_config =
+ (struct msm_audio_g711_dec_config *)audio->codec_cfg;
+ g711_dec_config->sample_rate = g711_dec_config_32.sample_rate;
+
+ break;
+ }
+ default: {
+ rc = audio->codec_compat_ioctl(file, cmd, arg);
+ if (rc)
+ pr_err("%s: Failed in audio_aio_compat_ioctl: %d cmd=%d\n",
+ __func__, rc, cmd);
+ break;
+ }
+ }
+ return rc;
+}
+#else
+#define audio_compat_ioctl NULL
+#endif
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+ struct q6audio_aio *audio = NULL;
+ int rc = 0;
+ /* 4 bytes represents decoder number, 1 byte for terminate string */
+ char name[sizeof "msm_g711_" + 5];
+
+ audio = kzalloc(sizeof(struct q6audio_aio), GFP_KERNEL);
+
+ if (!audio)
+ return -ENOMEM;
+ audio->codec_cfg = kzalloc(sizeof(struct msm_audio_g711_dec_config),
+ GFP_KERNEL);
+ if (!audio->codec_cfg) {
+ kfree(audio);
+ return -ENOMEM;
+ }
+
+ audio->pcm_cfg.buffer_size = PCM_BUFSZ_MIN;
+ audio->miscdevice = &audio_g711mlaw_misc;
+ audio->wakelock_voted = false;
+ audio->audio_ws_mgr = &audio_g711_ws_mgr;
+
+ init_waitqueue_head(&audio->event_wait);
+
+ audio->ac = q6asm_audio_client_alloc((app_cb) q6_audio_cb,
+ (void *)audio);
+
+ if (!audio->ac) {
+ pr_err("%s: Could not allocate memory for audio client\n",
+ __func__);
+ kfree(audio->codec_cfg);
+ kfree(audio);
+ return -ENOMEM;
+ }
+ rc = audio_aio_open(audio, file);
+ if (rc < 0) {
+ pr_err("%s: audio_aio_open rc=%d\n",
+ __func__, rc);
+ goto fail;
+ }
+ /* open in T/NT mode */ /*foramt:G711_ALAW*/
+ if ((file->f_mode & FMODE_WRITE) && (file->f_mode & FMODE_READ)) {
+ rc = q6asm_open_read_write(audio->ac, FORMAT_LINEAR_PCM,
+ FORMAT_G711_MLAW_FS);
+ if (rc < 0) {
+ pr_err("%s: NT mode Open failed rc=%d\n", __func__, rc);
+ goto fail;
+ }
+ audio->feedback = NON_TUNNEL_MODE;
+ /* open G711 decoder, expected frames is always 1*/
+ audio->buf_cfg.frames_per_buf = 0x01;
+ audio->buf_cfg.meta_info_enable = 0x01;
+ } else if ((file->f_mode & FMODE_WRITE) &&
+ !(file->f_mode & FMODE_READ)) {
+ rc = q6asm_open_write(audio->ac, FORMAT_G711_MLAW_FS);
+ if (rc < 0) {
+ pr_err("%s: T mode Open failed rc=%d\n", __func__, rc);
+ goto fail;
+ }
+ audio->feedback = TUNNEL_MODE;
+ audio->buf_cfg.meta_info_enable = 0x00;
+ } else {
+ pr_err("%s: %d mode is not supported\n", __func__,
+ file->f_mode);
+ rc = -EACCES;
+ goto fail;
+ }
+
+ snprintf(name, sizeof(name), "msm_g711_%04x", audio->ac->session);
+ audio->dentry = config_debugfs_create_file(name, (void *)audio);
+
+ if (IS_ERR_OR_NULL(audio->dentry))
+ pr_debug("%s: debugfs_create_file failed\n", __func__);
+ pr_debug("%s: g711dec success mode[%d]session[%d]\n", __func__,
+ audio->feedback,
+ audio->ac->session);
+ return rc;
+fail:
+ q6asm_audio_client_free(audio->ac);
+ kfree(audio->codec_cfg);
+ kfree(audio);
+ return rc;
+}
+
+static int g711_channel_map(u8 *channel_mapping, uint32_t channels)
+{
+ u8 *lchannel_mapping;
+
+ lchannel_mapping = channel_mapping;
+ pr_debug("%s: channels passed: %d\n", __func__, channels);
+ if (channels == 1) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ } else if (channels == 2) {
+ lchannel_mapping[0] = PCM_CHANNEL_FL;
+ lchannel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channels == 3) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ } else if (channels == 4) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[3] = PCM_CHANNEL_CS;
+ } else if (channels == 5) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[3] = PCM_CHANNEL_LS;
+ lchannel_mapping[4] = PCM_CHANNEL_RS;
+ } else if (channels == 6) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[3] = PCM_CHANNEL_LS;
+ lchannel_mapping[4] = PCM_CHANNEL_RS;
+ lchannel_mapping[5] = PCM_CHANNEL_LFE;
+ } else if (channels == 7) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[3] = PCM_CHANNEL_LS;
+ lchannel_mapping[4] = PCM_CHANNEL_RS;
+ lchannel_mapping[5] = PCM_CHANNEL_CS;
+ lchannel_mapping[6] = PCM_CHANNEL_LFE;
+ } else if (channels == 8) {
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FLC;
+ lchannel_mapping[2] = PCM_CHANNEL_FRC;
+ lchannel_mapping[3] = PCM_CHANNEL_FL;
+ lchannel_mapping[4] = PCM_CHANNEL_FR;
+ lchannel_mapping[5] = PCM_CHANNEL_LS;
+ lchannel_mapping[6] = PCM_CHANNEL_RS;
+ lchannel_mapping[7] = PCM_CHANNEL_LFE;
+ } else {
+ pr_err("%s: ERROR.unsupported num_ch = %u\n",
+ __func__, channels);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static const struct file_operations audio_g711_fops = {
+ .owner = THIS_MODULE,
+ .open = audio_open,
+ .release = audio_aio_release,
+ .unlocked_ioctl = audio_ioctl,
+ .compat_ioctl = audio_compat_ioctl,
+ .fsync = audio_aio_fsync,
+};
+
+static struct miscdevice audio_g711mlaw_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "msm_g711mlaw",
+ .fops = &audio_g711_fops,
+};
+
+static int __init audio_g711mlaw_init(void)
+{
+ int ret = misc_register(&audio_g711mlaw_misc);
+
+ if (ret == 0)
+ device_init_wakeup(audio_g711mlaw_misc.this_device, true);
+ audio_g711_ws_mgr.ref_cnt = 0;
+ mutex_init(&audio_g711_ws_mgr.ws_lock);
+
+ return ret;
+}
+
+static void __exit audio_g711mlaw_exit(void)
+{
+ misc_deregister(&audio_g711mlaw_misc);
+ mutex_destroy(&audio_g711_ws_mgr.ws_lock);
+}
+
+device_initcall(audio_g711mlaw_init);
+__exitcall(audio_g711mlaw_exit);
diff --git a/drivers/misc/qcom/qdsp6v2/g711alaw_in.c b/drivers/misc/qcom/qdsp6v2/g711alaw_in.c
new file mode 100644
index 000000000000..ac720b53ff5b
--- /dev/null
+++ b/drivers/misc/qcom/qdsp6v2/g711alaw_in.c
@@ -0,0 +1,382 @@
+/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/msm_audio_g711.h>
+#include <linux/atomic.h>
+#include <linux/compat.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+/* Buffer with meta*/
+#define PCM_BUF_SIZE (4096 + sizeof(struct meta_in))
+
+/* Maximum 10 frames in buffer with meta */
+#define FRAME_SIZE (1 + ((320+sizeof(struct meta_out_dsp)) * 10))
+static long g711_in_ioctl_shared(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct q6audio_in *audio = file->private_data;
+ int rc = 0;
+ int cnt = 0;
+
+ switch (cmd) {
+ case AUDIO_START: {
+ struct msm_audio_g711_enc_config *enc_cfg;
+
+ enc_cfg = (struct msm_audio_g711_enc_config *)audio->enc_cfg;
+ pr_debug("%s:session id %d: default buf alloc[%d]\n", __func__,
+ audio->ac->session, audio->buf_alloc);
+ if (audio->enabled == 1) {
+ rc = 0;
+ break;
+ }
+ rc = audio_in_buf_alloc(audio);
+ if (rc < 0) {
+ pr_err("%s:session id %d: buffer allocation failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ break;
+ }
+ pr_debug("%s: sample rate %d", __func__, enc_cfg->sample_rate);
+ rc = q6asm_enc_cfg_blk_g711(audio->ac,
+ audio->buf_cfg.frames_per_buf,
+ enc_cfg->sample_rate);
+
+ if (rc < 0) {
+ pr_err("%s:session id %d: cmd g711 media format block failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ break;
+ }
+ if (audio->feedback == NON_TUNNEL_MODE) {
+ rc = q6asm_media_format_block_pcm(audio->ac,
+ audio->pcm_cfg.sample_rate,
+ audio->pcm_cfg.channel_count);
+
+ if (rc < 0) {
+ pr_err("%s:session id %d: media format block failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ break;
+ }
+ }
+ pr_debug("%s:session id %d: AUDIO_START enable[%d]\n", __func__,
+ audio->ac->session, audio->enabled);
+ rc = audio_in_enable(audio);
+ if (!rc) {
+ audio->enabled = 1;
+ } else {
+ audio->enabled = 0;
+ pr_err("%s:session id %d: Audio Start procedure failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ break;
+ }
+ while (cnt++ < audio->str_cfg.buffer_count)
+ q6asm_read(audio->ac); /* Push buffer to DSP */
+ rc = 0;
+ pr_debug("%s:session id %d: AUDIO_START success enable[%d]\n",
+ __func__, audio->ac->session, audio->enabled);
+ break;
+ }
+ case AUDIO_STOP: {
+ pr_debug("%s:session id %d: AUDIO_STOP\n", __func__,
+ audio->ac->session);
+ rc = audio_in_disable(audio);
+ if (rc < 0) {
+ pr_err("%s:session id %d: Audio Stop procedure failed rc=%d\n",
+ __func__, audio->ac->session,
+ rc);
+ break;
+ }
+ break;
+ }
+ case AUDIO_SET_G711_ENC_CONFIG: {
+ struct msm_audio_g711_enc_config *cfg;
+ struct msm_audio_g711_enc_config *enc_cfg;
+
+ enc_cfg = (struct msm_audio_g711_enc_config *)audio->enc_cfg;
+
+ cfg = (struct msm_audio_g711_enc_config *)arg;
+ if (cfg == NULL) {
+ pr_err("%s: NULL config pointer\n", __func__);
+ rc = -EINVAL;
+ break;
+ }
+ if (cfg->sample_rate != 8000 &&
+ cfg->sample_rate != 16000) {
+ pr_err("%s:session id %d: invalid sample rate\n",
+ __func__, audio->ac->session);
+ rc = -EINVAL;
+ break;
+ }
+ enc_cfg->sample_rate = cfg->sample_rate;
+ pr_debug("%s:session id %d: sample_rate= 0x%x",
+ __func__,
+ audio->ac->session, enc_cfg->sample_rate);
+ break;
+ }
+ default:
+ pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+ rc = -ENOIOCTLCMD;
+ }
+ return rc;
+}
+
+static long g711_in_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct q6audio_in *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START:
+ case AUDIO_STOP: {
+ rc = g711_in_ioctl_shared(file, cmd, arg);
+ break;
+ }
+ case AUDIO_GET_G711_ENC_CONFIG: {
+ if (copy_to_user((void *)arg, audio->enc_cfg,
+ sizeof(struct msm_audio_g711_enc_config))) {
+ pr_err(
+ "%s: copy_to_user for AUDIO_GET_g711_ENC_CONFIG failed",
+ __func__);
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case AUDIO_SET_G711_ENC_CONFIG: {
+ struct msm_audio_g711_enc_config cfg;
+
+ if (copy_from_user(&cfg, (void *) arg,
+ sizeof(cfg))) {
+ pr_err(
+ "%s: copy_from_user for AUDIO_GET_G711_ENC_CONFIG failed",
+ __func__);
+ rc = -EFAULT;
+ break;
+ }
+ rc = g711_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+ if (rc)
+ pr_err("%s:AUDIO_GET_G711_ENC_CONFIG failed. Rc= %d\n",
+ __func__, rc);
+ break;
+ }
+ default:
+ pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+ rc = -ENOIOCTLCMD;
+ }
+ return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_g711_enc_config32 {
+ uint32_t sample_rate;
+};
+
+enum {
+ AUDIO_SET_G711_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+ (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_g711_enc_config32),
+ AUDIO_GET_G711_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+ (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_g711_enc_config32)
+};
+
+static long g711_in_compat_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct q6audio_in *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START:
+ case AUDIO_STOP: {
+ rc = g711_in_ioctl_shared(file, cmd, arg);
+ break;
+ }
+ case AUDIO_GET_G711_ENC_CONFIG_32: {
+ struct msm_audio_g711_enc_config32 cfg_32;
+ struct msm_audio_g711_enc_config32 *enc_cfg;
+
+ enc_cfg = (struct msm_audio_g711_enc_config32 *)audio->enc_cfg;
+ cfg_32.sample_rate = enc_cfg->sample_rate;
+ if (copy_to_user((void *)arg, &cfg_32,
+ sizeof(cfg_32))) {
+ pr_err("%s: copy_to_user for AUDIO_GET_G711_ENC_CONFIG_32 failed\n",
+ __func__);
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case AUDIO_SET_G711_ENC_CONFIG_32: {
+ struct msm_audio_g711_enc_config32 cfg_32;
+ struct msm_audio_g711_enc_config32 cfg;
+
+ if (copy_from_user(&cfg_32, (void *) arg,
+ sizeof(cfg_32))) {
+ pr_err("%s: copy_from_user for AUDIO_SET_G711_ENC_CONFIG_32 failed\n",
+ __func__);
+ rc = -EFAULT;
+ break;
+ }
+ cfg.sample_rate = cfg_32.sample_rate;
+ cmd = AUDIO_SET_G711_ENC_CONFIG;
+ rc = g711_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+ if (rc)
+ pr_err("%s:AUDIO_SET_G711_ENC_CONFIG failed. rc= %d\n",
+ __func__, rc);
+ break;
+ }
+ default:
+ pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+ rc = -ENOIOCTLCMD;
+ }
+ return rc;
+}
+#else
+#define g711_in_compat_ioctl NULL
+#endif
+
+static int g711_in_open(struct inode *inode, struct file *file)
+{
+ struct q6audio_in *audio = NULL;
+ struct msm_audio_g711_enc_config *enc_cfg;
+ int rc = 0;
+
+ audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
+
+ if (audio == NULL)
+ return -ENOMEM;
+ /* Allocate memory for encoder config param */
+ audio->enc_cfg = kzalloc(sizeof(struct msm_audio_g711_enc_config),
+ GFP_KERNEL);
+ if (audio->enc_cfg == NULL) {
+ kfree(audio);
+ return -ENOMEM;
+ }
+ enc_cfg = audio->enc_cfg;
+
+ mutex_init(&audio->lock);
+ mutex_init(&audio->read_lock);
+ mutex_init(&audio->write_lock);
+ spin_lock_init(&audio->dsp_lock);
+ init_waitqueue_head(&audio->read_wait);
+ init_waitqueue_head(&audio->write_wait);
+
+ /*
+ * Settings will be re-config at AUDIO_SET_CONFIG,
+ * but at least we need to have initial config
+ */
+ audio->str_cfg.buffer_size = FRAME_SIZE;
+ audio->str_cfg.buffer_count = FRAME_NUM;
+ audio->min_frame_size = 320;
+ audio->max_frames_per_buf = 10;
+ audio->pcm_cfg.buffer_size = PCM_BUF_SIZE;
+ audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+ enc_cfg->sample_rate = 8000;
+ audio->pcm_cfg.channel_count = 1;
+ audio->pcm_cfg.sample_rate = 8000;
+ audio->buf_cfg.meta_info_enable = 0x01;
+ audio->buf_cfg.frames_per_buf = 0x01;
+ audio->event_abort = 0;
+
+ audio->ac = q6asm_audio_client_alloc((app_cb)q6asm_in_cb,
+ (void *)audio);
+
+ if (!audio->ac) {
+ kfree(audio->enc_cfg);
+ kfree(audio);
+ return -ENOMEM;
+ }
+
+ /* open g711 encoder in T/NT mode */
+ if ((file->f_mode & FMODE_WRITE) &&
+ (file->f_mode & FMODE_READ)) {
+ audio->feedback = NON_TUNNEL_MODE;
+ rc = q6asm_open_read_write(audio->ac, FORMAT_G711_ALAW_FS,
+ FORMAT_LINEAR_PCM);
+ if (rc < 0) {
+ pr_err("%s:session id %d: NT mode Open failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ rc = -ENODEV;
+ goto fail;
+ }
+ } else if (!(file->f_mode & FMODE_WRITE) &&
+ (file->f_mode & FMODE_READ)) {
+ audio->feedback = TUNNEL_MODE;
+ rc = q6asm_open_read(audio->ac, FORMAT_G711_ALAW_FS);
+ if (rc < 0) {
+ pr_err("%s:session id %d: T mode Open failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ rc = -ENODEV;
+ goto fail;
+ }
+ /* register for tx overflow (valid for tunnel mode only) */
+ rc = q6asm_reg_tx_overflow(audio->ac, 0x01);
+ if (rc < 0) {
+ pr_err("%s:session id %d: TX Overflow registration failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ rc = -ENODEV;
+ goto fail;
+ }
+ } else {
+ pr_err("%s:session id %d: Unexpected mode\n", __func__,
+ audio->ac->session);
+ rc = -EACCES;
+ goto fail;
+ }
+
+ audio->opened = 1;
+ audio->reset_event = false;
+ atomic_set(&audio->in_count, PCM_BUF_COUNT);
+ atomic_set(&audio->out_count, 0x00);
+ audio->enc_compat_ioctl = g711_in_compat_ioctl;
+ audio->enc_ioctl = g711_in_ioctl;
+ file->private_data = audio;
+
+ pr_info("%s:session id %d: success\n", __func__, audio->ac->session);
+ return 0;
+fail:
+ q6asm_audio_client_free(audio->ac);
+ kfree(audio->enc_cfg);
+ kfree(audio);
+ return rc;
+}
+
+static const struct file_operations audio_in_fops = {
+ .owner = THIS_MODULE,
+ .open = g711_in_open,
+ .release = audio_in_release,
+ .read = audio_in_read,
+ .write = audio_in_write,
+ .unlocked_ioctl = audio_in_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = audio_in_compat_ioctl,
+#endif
+};
+
+struct miscdevice audio_g711alaw_in_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "msm_g711alaw_in",
+ .fops = &audio_in_fops,
+};
+
+static int __init g711alaw_in_init(void)
+{
+ return misc_register(&audio_g711alaw_in_misc);
+}
+
+device_initcall(g711alaw_in_init);
diff --git a/drivers/misc/qcom/qdsp6v2/g711mlaw_in.c b/drivers/misc/qcom/qdsp6v2/g711mlaw_in.c
new file mode 100644
index 000000000000..6660f83683f8
--- /dev/null
+++ b/drivers/misc/qcom/qdsp6v2/g711mlaw_in.c
@@ -0,0 +1,385 @@
+/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/msm_audio_g711.h>
+#include <linux/atomic.h>
+#include <linux/compat.h>
+#include <asm/ioctls.h>
+#include "audio_utils.h"
+
+#ifdef CONFIG_COMPAT
+#undef PROC_ADD
+#endif
+/* Buffer with meta*/
+#define PCM_BUF_SIZE (4096 + sizeof(struct meta_in))
+
+/* Maximum 10 frames in buffer with meta */
+#define FRAME_SIZE (1 + ((320+sizeof(struct meta_out_dsp)) * 10))
+static long g711_in_ioctl_shared(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct q6audio_in *audio = file->private_data;
+ int rc = 0;
+ int cnt = 0;
+
+ switch (cmd) {
+ case AUDIO_START: {
+ struct msm_audio_g711_enc_config *enc_cfg;
+
+ enc_cfg = (struct msm_audio_g711_enc_config *)audio->enc_cfg;
+ pr_debug("%s:session id %d: default buf alloc[%d]\n", __func__,
+ audio->ac->session, audio->buf_alloc);
+ if (audio->enabled == 1) {
+ rc = 0;
+ break;
+ }
+ rc = audio_in_buf_alloc(audio);
+ if (rc < 0) {
+ pr_err("%s:session id %d: buffer allocation failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ break;
+ }
+ pr_debug("%s: sample rate %d", __func__, enc_cfg->sample_rate);
+ rc = q6asm_enc_cfg_blk_g711(audio->ac,
+ audio->buf_cfg.frames_per_buf,
+ enc_cfg->sample_rate);
+
+ if (rc < 0) {
+ pr_err("%s:session id %d: cmd g711 media format block failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ break;
+ }
+ if (audio->feedback == NON_TUNNEL_MODE) {
+ rc = q6asm_media_format_block_pcm(audio->ac,
+ audio->pcm_cfg.sample_rate,
+ audio->pcm_cfg.channel_count);
+
+ if (rc < 0) {
+ pr_err("%s:session id %d: media format block failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ break;
+ }
+ }
+ pr_debug("%s:session id %d: AUDIO_START enable[%d]\n", __func__,
+ audio->ac->session, audio->enabled);
+ rc = audio_in_enable(audio);
+ if (!rc) {
+ audio->enabled = 1;
+ } else {
+ audio->enabled = 0;
+ pr_err("%s:session id %d: Audio Start procedure failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ break;
+ }
+ while (cnt++ < audio->str_cfg.buffer_count)
+ q6asm_read(audio->ac); /* Push buffer to DSP */
+ rc = 0;
+ pr_debug("%s:session id %d: AUDIO_START success enable[%d]\n",
+ __func__, audio->ac->session, audio->enabled);
+ break;
+ }
+ case AUDIO_STOP: {
+ pr_debug("%s:session id %d: AUDIO_STOP\n", __func__,
+ audio->ac->session);
+ rc = audio_in_disable(audio);
+ if (rc < 0) {
+ pr_err("%s:session id %d: Audio Stop procedure failed rc=%d\n",
+ __func__, audio->ac->session,
+ rc);
+ break;
+ }
+ break;
+ }
+ case AUDIO_SET_G711_ENC_CONFIG: {
+ struct msm_audio_g711_enc_config *cfg;
+ struct msm_audio_g711_enc_config *enc_cfg;
+
+ enc_cfg = (struct msm_audio_g711_enc_config *)audio->enc_cfg;
+
+ cfg = (struct msm_audio_g711_enc_config *)arg;
+ if (cfg == NULL) {
+ pr_err("%s: NULL config pointer\n", __func__);
+ rc = -EINVAL;
+ break;
+ }
+ if (cfg->sample_rate != 8000 &&
+ cfg->sample_rate != 16000) {
+ pr_err("%s:session id %d: invalid sample rate\n",
+ __func__, audio->ac->session);
+ rc = -EINVAL;
+ break;
+ }
+ enc_cfg->sample_rate = cfg->sample_rate;
+ pr_debug("%s:session id %d: sample_rate= 0x%x",
+ __func__,
+ audio->ac->session, enc_cfg->sample_rate);
+ break;
+ }
+ default:
+ pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+ rc = -ENOIOCTLCMD;
+ }
+ return rc;
+}
+
+static long g711_in_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct q6audio_in *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START:
+ case AUDIO_STOP: {
+ rc = g711_in_ioctl_shared(file, cmd, arg);
+ break;
+ }
+ case AUDIO_GET_G711_ENC_CONFIG: {
+ if (copy_to_user((void *)arg, audio->enc_cfg,
+ sizeof(struct msm_audio_g711_enc_config))) {
+ pr_err(
+ "%s: copy_to_user for AUDIO_GET_g711_ENC_CONFIG failed",
+ __func__);
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case AUDIO_SET_G711_ENC_CONFIG: {
+ struct msm_audio_g711_enc_config cfg;
+
+ if (copy_from_user(&cfg, (void *) arg,
+ sizeof(cfg))) {
+ pr_err(
+ "%s: copy_from_user for AUDIO_GET_G711_ENC_CONFIG failed",
+ __func__);
+ rc = -EFAULT;
+ break;
+ }
+ rc = g711_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+ if (rc)
+ pr_err("%s:AUDIO_GET_G711_ENC_CONFIG failed. Rc= %d\n",
+ __func__, rc);
+ break;
+ }
+ default:
+ pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+ rc = -ENOIOCTLCMD;
+ }
+ return rc;
+}
+
+#ifdef CONFIG_COMPAT
+struct msm_audio_g711_enc_config32 {
+ uint32_t sample_rate;
+};
+
+enum {
+ AUDIO_SET_G711_ENC_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC,
+ (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_g711_enc_config32),
+ AUDIO_GET_G711_ENC_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC,
+ (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_g711_enc_config32)
+};
+
+static long g711_in_compat_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct q6audio_in *audio = file->private_data;
+ int rc = 0;
+
+ switch (cmd) {
+ case AUDIO_START:
+ case AUDIO_STOP: {
+ rc = g711_in_ioctl_shared(file, cmd, arg);
+ break;
+ }
+ case AUDIO_GET_G711_ENC_CONFIG_32: {
+ struct msm_audio_g711_enc_config32 cfg_32;
+ struct msm_audio_g711_enc_config32 *enc_cfg;
+
+ enc_cfg = (struct msm_audio_g711_enc_config32 *)audio->enc_cfg;
+ cfg_32.sample_rate = enc_cfg->sample_rate;
+ if (copy_to_user((void *)arg, &cfg_32,
+ sizeof(cfg_32))) {
+ pr_err("%s: copy_to_user for AUDIO_GET_G711_ENC_CONFIG_32 failed\n",
+ __func__);
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case AUDIO_SET_G711_ENC_CONFIG_32: {
+ struct msm_audio_g711_enc_config32 cfg_32;
+ struct msm_audio_g711_enc_config32 cfg;
+
+ if (copy_from_user(&cfg_32, (void *) arg,
+ sizeof(cfg_32))) {
+ pr_err("%s: copy_from_user for AUDIO_SET_G711_ENC_CONFIG_32 failed\n",
+ __func__);
+ rc = -EFAULT;
+ break;
+ }
+ cfg.sample_rate = cfg_32.sample_rate;
+ cmd = AUDIO_SET_G711_ENC_CONFIG;
+ rc = g711_in_ioctl_shared(file, cmd, (unsigned long)&cfg);
+ if (rc)
+ pr_err("%s:AUDIO_SET_G711_ENC_CONFIG failed. rc= %d\n",
+ __func__, rc);
+ break;
+ }
+ default:
+ pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
+ rc = -ENOIOCTLCMD;
+ }
+ return rc;
+}
+#else
+#define g711_in_compat_ioctl NULL
+#endif
+
+static int g711_in_open(struct inode *inode, struct file *file)
+{
+ struct q6audio_in *audio = NULL;
+ struct msm_audio_g711_enc_config *enc_cfg;
+ int rc = 0;
+
+ audio = kzalloc(sizeof(struct q6audio_in), GFP_KERNEL);
+
+ if (audio == NULL)
+ return -ENOMEM;
+ /* Allocate memory for encoder config param */
+ audio->enc_cfg = kzalloc(sizeof(struct msm_audio_g711_enc_config),
+ GFP_KERNEL);
+ if (audio->enc_cfg == NULL) {
+ kfree(audio);
+ return -ENOMEM;
+ }
+ enc_cfg = audio->enc_cfg;
+
+ mutex_init(&audio->lock);
+ mutex_init(&audio->read_lock);
+ mutex_init(&audio->write_lock);
+ spin_lock_init(&audio->dsp_lock);
+ init_waitqueue_head(&audio->read_wait);
+ init_waitqueue_head(&audio->write_wait);
+
+ /*
+ * Settings will be re-config at AUDIO_SET_CONFIG,
+ * but at least we need to have initial config
+ */
+ audio->str_cfg.buffer_size = FRAME_SIZE;
+ audio->str_cfg.buffer_count = FRAME_NUM;
+ audio->min_frame_size = 320;
+ audio->max_frames_per_buf = 10;
+ audio->pcm_cfg.buffer_size = PCM_BUF_SIZE;
+ audio->pcm_cfg.buffer_count = PCM_BUF_COUNT;
+ enc_cfg->sample_rate = 8000;
+ audio->pcm_cfg.channel_count = 1;
+ audio->pcm_cfg.sample_rate = 8000;
+ audio->buf_cfg.meta_info_enable = 0x01;
+ audio->buf_cfg.frames_per_buf = 0x01;
+ audio->event_abort = 0;
+
+ audio->ac = q6asm_audio_client_alloc((app_cb)q6asm_in_cb,
+ (void *)audio);
+
+ if (!audio->ac) {
+ kfree(audio->enc_cfg);
+ kfree(audio);
+ return -ENOMEM;
+ }
+
+ /* open g711 encoder in T/NT mode */
+ if ((file->f_mode & FMODE_WRITE) &&
+ (file->f_mode & FMODE_READ)) {
+ audio->feedback = NON_TUNNEL_MODE;
+ rc = q6asm_open_read_write(audio->ac, FORMAT_G711_MLAW_FS,
+ FORMAT_LINEAR_PCM);
+ if (rc < 0) {
+ pr_err("%s:session id %d: NT mode Open failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ rc = -ENODEV;
+ goto fail;
+ }
+ } else if (!(file->f_mode & FMODE_WRITE) &&
+ (file->f_mode & FMODE_READ)) {
+ audio->feedback = TUNNEL_MODE;
+ rc = q6asm_open_read(audio->ac, FORMAT_G711_MLAW_FS);
+ if (rc < 0) {
+ pr_err("%s:session id %d: T mode Open failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ rc = -ENODEV;
+ goto fail;
+ }
+ /* register for tx overflow (valid for tunnel mode only) */
+ rc = q6asm_reg_tx_overflow(audio->ac, 0x01);
+ if (rc < 0) {
+ pr_err("%s:session id %d: TX Overflow registration failed rc=%d\n",
+ __func__, audio->ac->session, rc);
+ rc = -ENODEV;
+ goto fail;
+ }
+ } else {
+ pr_err("%s:session id %d: Unexpected mode\n", __func__,
+ audio->ac->session);
+ rc = -EACCES;
+ goto fail;
+ }
+
+ audio->opened = 1;
+ audio->reset_event = false;
+ atomic_set(&audio->in_count, PCM_BUF_COUNT);
+ atomic_set(&audio->out_count, 0x00);
+ audio->enc_compat_ioctl = g711_in_compat_ioctl;
+ audio->enc_ioctl = g711_in_ioctl;
+ file->private_data = audio;
+
+ pr_info("%s:session id %d: success\n", __func__, audio->ac->session);
+ return 0;
+fail:
+ q6asm_audio_client_free(audio->ac);
+ kfree(audio->enc_cfg);
+ kfree(audio);
+ return rc;
+}
+
+static const struct file_operations audio_in_fops = {
+ .owner = THIS_MODULE,
+ .open = g711_in_open,
+ .release = audio_in_release,
+ .read = audio_in_read,
+ .write = audio_in_write,
+ .unlocked_ioctl = audio_in_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = audio_in_compat_ioctl,
+#endif
+};
+
+struct miscdevice audio_g711mlaw_in_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "msm_g711mlaw_in",
+ .fops = &audio_in_fops,
+};
+
+static int __init g711mlaw_in_init(void)
+{
+ return misc_register(&audio_g711mlaw_in_misc);
+}
+
+device_initcall(g711mlaw_in_init);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 6eee4aa0e574..39cb46a5ce11 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -3456,7 +3456,8 @@ static void mmc_blk_cmdq_err(struct mmc_queue *mq)
struct mmc_request *mrq = host->err_mrq;
struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx;
struct request_queue *q;
- int err;
+ int err, ret;
+ u32 status = 0;
mmc_host_clk_hold(host);
host->cmdq_ops->dumpstate(host);
@@ -3475,8 +3476,14 @@ static void mmc_blk_cmdq_err(struct mmc_queue *mq)
/* RED error - Fatal: requires reset */
if (mrq->cmdq_req->resp_err) {
err = mrq->cmdq_req->resp_err;
- pr_crit("%s: Response error detected: Device in bad state\n",
- mmc_hostname(host));
+ if (mmc_host_halt(host) || mmc_host_cq_disable(host)) {
+ ret = get_card_status(host->card, &status, 0);
+ if (ret)
+ pr_err("%s: CMD13 failed with err %d\n",
+ mmc_hostname(host), ret);
+ }
+ pr_err("%s: Response error detected with device status 0x%08x\n",
+ mmc_hostname(host), status);
goto reset;
}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 828d2b85f6e4..6ad91042409e 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1552,6 +1552,12 @@ int mmc_cmdq_halt(struct mmc_host *host, bool halt)
{
int err = 0;
+ if (mmc_host_cq_disable(host)) {
+ pr_debug("%s: %s: CQE is already disabled\n",
+ mmc_hostname(host), __func__);
+ return 0;
+ }
+
if ((halt && mmc_host_halt(host)) ||
(!halt && !mmc_host_halt(host))) {
pr_debug("%s: %s: CQE is already %s\n", mmc_hostname(host),
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 0e0a018f39be..52427815722b 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -863,8 +863,16 @@ skip_cqterri:
* If CQE halt fails then, disable CQE
* from processing any further requests
*/
- if (ret)
+ if (ret) {
cmdq_disable_nosync(mmc, true);
+ /*
+ * Enable legacy interrupts as CQE halt has failed.
+ * This is needed to send legacy commands like status
+ * cmd as part of error handling work.
+ */
+ if (cq_host->ops->clear_set_irqs)
+ cq_host->ops->clear_set_irqs(mmc, false);
+ }
/*
* CQE detected a reponse error from device
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0542ba51445f..886229317fea 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3157,7 +3157,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
do {
if (host->mmc->card && mmc_card_cmdq(host->mmc->card) &&
- !mmc_host_halt(host->mmc)) {
+ !mmc_host_halt(host->mmc) && !mmc_host_cq_disable(host->mmc)) {
pr_debug("*** %s: cmdq intr: 0x%08x\n",
mmc_hostname(host->mmc),
intmask);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 8676b35914e2..2101147e7d24 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -624,16 +624,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
IPADBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd));
- if (!ipa3_is_ready()) {
- IPAERR("IPA not ready, waiting for init completion\n");
- wait_for_completion(&ipa3_ctx->init_completion_obj);
- }
-
if (_IOC_TYPE(cmd) != IPA_IOC_MAGIC)
return -ENOTTY;
if (_IOC_NR(cmd) >= IPA_IOCTL_MAX)
return -ENOTTY;
+ if (!ipa3_is_ready()) {
+ IPAERR("IPA not ready, waiting for init completion\n");
+ wait_for_completion(&ipa3_ctx->init_completion_obj);
+ }
+
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
switch (cmd) {
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 9ef57e5d7d64..9d9eed2d5d68 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -178,6 +178,9 @@ config USB_F_RNDIS
config USB_F_QCRNDIS
tristate
+config USB_F_RMNET_BAM
+ tristate
+
config USB_F_MASS_STORAGE
tristate
@@ -345,6 +348,12 @@ config USB_CONFIGFS_RNDIS
XP, you'll need to download drivers from Microsoft's website; a URL
is given in comments found in that info file.
+config USB_CONFIGFS_RMNET_BAM
+ bool "RMNET"
+ depends on USB_CONFIGFS
+ depends on IPA
+ select USB_F_RMNET_BAM
+
config USB_CONFIGFS_EEM
bool "Ethernet Emulation Model (EEM)"
depends on USB_CONFIGFS
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
index a213cd4c8377..511909fb78f6 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -62,3 +62,5 @@ usb_f_qdss-y := f_qdss.o u_qdss.o
obj-$(CONFIG_USB_F_QDSS) += usb_f_qdss.o
usb_f_qcrndis-y := f_qc_rndis.o u_data_ipa.o
obj-$(CONFIG_USB_F_QCRNDIS) += usb_f_qcrndis.o
+usb_f_rmnet_bam-y := f_rmnet.o u_ctrl_qti.o
+obj-$(CONFIG_USB_F_RMNET_BAM) += usb_f_rmnet_bam.o
diff --git a/drivers/usb/gadget/function/f_qdss.h b/drivers/usb/gadget/function/f_qdss.h
index c4af5ac839cd..e3fe8ae03775 100644
--- a/drivers/usb/gadget/function/f_qdss.h
+++ b/drivers/usb/gadget/function/f_qdss.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,8 @@
#include <linux/usb/composite.h>
#include <linux/usb/usb_qdss.h>
+#include "u_rmnet.h"
+
struct usb_qdss_bam_connect_info {
u32 usb_bam_pipe_idx;
u32 peer_pipe_idx;
@@ -33,8 +35,8 @@ struct gqdss {
struct usb_ep *ctrl_out;
struct usb_ep *ctrl_in;
struct usb_ep *data;
- int (*send_encap_cmd)(u8 port_num, void *buf, size_t len);
- void (*notify_modem)(void *g, u8 port_num, int cbits);
+ int (*send_encap_cmd)(enum qti_port_type qport, void *buf, size_t len);
+ void (*notify_modem)(void *g, enum qti_port_type qport, int cbits);
};
/* struct f_qdss - USB qdss function driver private structure */
diff --git a/drivers/usb/gadget/function/f_rmnet.c b/drivers/usb/gadget/function/f_rmnet.c
index d84b55cef666..0fd7e213ef99 100644
--- a/drivers/usb/gadget/function/f_rmnet.c
+++ b/drivers/usb/gadget/function/f_rmnet.c
@@ -17,16 +17,11 @@
#include <linux/netdevice.h>
#include <linux/spinlock.h>
#include <linux/usb_bam.h>
+#include <linux/module.h>
-#include "usb_gadget_xport.h"
-#include "u_ether.h"
#include "u_rmnet.h"
-#include "gadget_chips.h"
-
-static unsigned int rmnet_dl_max_pkt_per_xfer = 7;
-module_param(rmnet_dl_max_pkt_per_xfer, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rmnet_dl_max_pkt_per_xfer,
- "Maximum packets per transfer for DL aggregation");
+#include "u_data_ipa.h"
+#include "configfs.h"
#define RMNET_NOTIFY_INTERVAL 5
#define RMNET_MAX_NOTIFY_SIZE sizeof(struct usb_cdc_notification)
@@ -38,10 +33,9 @@ MODULE_PARM_DESC(rmnet_dl_max_pkt_per_xfer,
* control paths
*/
struct f_rmnet {
- struct gether gether_port;
+ struct usb_function func;
struct grmnet port;
int ifc_id;
- u8 port_num;
atomic_t online;
atomic_t ctrl_online;
struct usb_composite_dev *cdev;
@@ -53,30 +47,11 @@ struct f_rmnet {
struct usb_request *notify_req;
/* control info */
+ struct gadget_ipa_port ipa_port;
struct list_head cpkt_resp_q;
unsigned long notify_count;
unsigned long cpkts_len;
- const struct usb_endpoint_descriptor *in_ep_desc_backup;
- const struct usb_endpoint_descriptor *out_ep_desc_backup;
-};
-
-static unsigned int nr_rmnet_ports;
-static unsigned int no_ctrl_smd_ports;
-static unsigned int no_ctrl_qti_ports;
-static unsigned int no_ctrl_hsic_ports;
-static unsigned int no_ctrl_hsuart_ports;
-static unsigned int no_data_bam_ports;
-static unsigned int no_data_bam2bam_ports;
-static unsigned int no_data_hsic_ports;
-static unsigned int no_data_hsuart_ports;
-static struct rmnet_ports {
- enum transport_type data_xport;
- enum transport_type ctrl_xport;
- unsigned data_xport_num;
- unsigned ctrl_xport_num;
- unsigned port_num;
- struct f_rmnet *port;
-} rmnet_ports[NR_RMNET_PORTS];
+} *rmnet_port;
static struct usb_interface_descriptor rmnet_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
@@ -244,7 +219,7 @@ static void frmnet_ctrl_response_available(struct f_rmnet *dev);
static inline struct f_rmnet *func_to_rmnet(struct usb_function *f)
{
- return container_of(f, struct f_rmnet, gether_port.func);
+ return container_of(f, struct f_rmnet, func);
}
static inline struct f_rmnet *port_to_rmnet(struct grmnet *r)
@@ -253,8 +228,7 @@ static inline struct f_rmnet *port_to_rmnet(struct grmnet *r)
}
static struct usb_request *
-frmnet_alloc_req(struct usb_ep *ep, unsigned len, size_t extra_buf_alloc,
- gfp_t flags)
+frmnet_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags)
{
struct usb_request *req;
@@ -262,7 +236,7 @@ frmnet_alloc_req(struct usb_ep *ep, unsigned len, size_t extra_buf_alloc,
if (!req)
return ERR_PTR(-ENOMEM);
- req->buf = kmalloc(len + extra_buf_alloc, flags);
+ req->buf = kmalloc(len, flags);
if (!req->buf) {
usb_ep_free_request(ep, req);
return ERR_PTR(-ENOMEM);
@@ -305,198 +279,42 @@ static void rmnet_free_ctrl_pkt(struct rmnet_ctrl_pkt *pkt)
/* -------------------------------------------*/
-static int rmnet_gport_setup(void)
-{
- int ret;
- int port_idx;
- int i;
- u8 base;
-
- pr_debug("%s: bam ports:%u bam2bam ports:%u data hsic ports:%u\n",
- __func__, no_data_bam_ports, no_data_bam2bam_ports,
- no_data_hsic_ports);
-
- pr_debug("%s: data hsuart ports:%u smd ports:%u ctrl hsic ports:%u\n",
- __func__, no_data_hsuart_ports, no_ctrl_smd_ports,
- no_ctrl_hsic_ports);
-
- pr_debug("%s: ctrl hsuart ports:%u nr_rmnet_ports:%u\n",
- __func__, no_ctrl_hsuart_ports, nr_rmnet_ports);
-
- if (no_data_bam_ports) {
- ret = gbam_setup(no_data_bam_ports);
- if (ret < 0)
- return ret;
- }
-
- if (no_data_bam2bam_ports) {
- ret = gbam2bam_setup(no_data_bam2bam_ports);
- if (ret < 0)
- return ret;
- }
-
- if (no_ctrl_smd_ports) {
- ret = gsmd_ctrl_setup(FRMNET_CTRL_CLIENT,
- no_ctrl_smd_ports, &base);
- if (ret)
- return ret;
- for (i = 0; i < nr_rmnet_ports; i++)
- if (rmnet_ports[i].port)
- rmnet_ports[i].port->port_num += base;
- }
-
- if (no_data_hsic_ports) {
- port_idx = ghsic_data_setup(no_data_hsic_ports,
- USB_GADGET_RMNET);
- if (port_idx < 0)
- return port_idx;
- for (i = 0; i < nr_rmnet_ports; i++) {
- if (rmnet_ports[i].data_xport ==
- USB_GADGET_XPORT_HSIC) {
- rmnet_ports[i].data_xport_num = port_idx;
- port_idx++;
- }
- }
- }
-
- if (no_ctrl_hsic_ports) {
- port_idx = ghsic_ctrl_setup(no_ctrl_hsic_ports,
- USB_GADGET_RMNET);
- if (port_idx < 0)
- return port_idx;
- for (i = 0; i < nr_rmnet_ports; i++) {
- if (rmnet_ports[i].ctrl_xport ==
- USB_GADGET_XPORT_HSIC) {
- rmnet_ports[i].ctrl_xport_num = port_idx;
- port_idx++;
- }
- }
- }
-
- return 0;
-}
-
static int gport_rmnet_connect(struct f_rmnet *dev, unsigned intf)
{
int ret;
- unsigned port_num;
- enum transport_type cxport = rmnet_ports[dev->port_num].ctrl_xport;
- enum transport_type dxport = rmnet_ports[dev->port_num].data_xport;
int src_connection_idx = 0, dst_connection_idx = 0;
struct usb_gadget *gadget = dev->cdev->gadget;
enum usb_ctrl usb_bam_type;
- void *net;
-
- pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n",
- __func__, xport_to_str(cxport), xport_to_str(dxport),
- dev, dev->port_num);
- port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
- switch (cxport) {
- case USB_GADGET_XPORT_SMD:
- ret = gsmd_ctrl_connect(&dev->port, port_num);
- if (ret) {
- pr_err("%s: gsmd_ctrl_connect failed: err:%d\n",
- __func__, ret);
- return ret;
- }
- break;
- case USB_GADGET_XPORT_QTI:
- ret = gqti_ctrl_connect(&dev->port, port_num, dev->ifc_id,
- dxport, USB_GADGET_RMNET);
- if (ret) {
- pr_err("%s: gqti_ctrl_connect failed: err:%d\n",
- __func__, ret);
- return ret;
- }
- break;
- case USB_GADGET_XPORT_HSIC:
- ret = ghsic_ctrl_connect(&dev->port, port_num);
- if (ret) {
- pr_err("%s: ghsic_ctrl_connect failed: err:%d\n",
- __func__, ret);
- return ret;
- }
- break;
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %s\n", __func__,
- xport_to_str(cxport));
- return -ENODEV;
+ ret = gqti_ctrl_connect(&dev->port, QTI_PORT_RMNET, dev->ifc_id);
+ if (ret) {
+ pr_err("%s: gqti_ctrl_connect failed: err:%d\n",
+ __func__, ret);
+ return ret;
}
- port_num = rmnet_ports[dev->port_num].data_xport_num;
-
- switch (dxport) {
- case USB_GADGET_XPORT_BAM_DMUX:
- ret = gbam_connect(&dev->port, port_num,
- dxport, src_connection_idx, dst_connection_idx);
- if (ret) {
- pr_err("%s: gbam_connect failed: err:%d\n",
- __func__, ret);
- gsmd_ctrl_disconnect(&dev->port, port_num);
- return ret;
- }
- break;
- case USB_GADGET_XPORT_BAM2BAM_IPA:
- usb_bam_type = usb_bam_get_bam_type(gadget->name);
- src_connection_idx = usb_bam_get_connection_idx(usb_bam_type,
- IPA_P_BAM, USB_TO_PEER_PERIPHERAL, USB_BAM_DEVICE,
- port_num);
- dst_connection_idx = usb_bam_get_connection_idx(usb_bam_type,
- IPA_P_BAM, PEER_PERIPHERAL_TO_USB, USB_BAM_DEVICE,
- port_num);
- if (dst_connection_idx < 0 || src_connection_idx < 0) {
- pr_err("%s: usb_bam_get_connection_idx failed\n",
- __func__);
- gsmd_ctrl_disconnect(&dev->port, port_num);
- return -EINVAL;
- }
- ret = gbam_connect(&dev->port, port_num,
- dxport, src_connection_idx, dst_connection_idx);
- if (ret) {
- pr_err("%s: gbam_connect failed: err:%d\n",
- __func__, ret);
- if (cxport == USB_GADGET_XPORT_QTI)
- gqti_ctrl_disconnect(&dev->port, port_num);
- else
- gsmd_ctrl_disconnect(&dev->port, port_num);
- return ret;
- }
- break;
- case USB_GADGET_XPORT_HSIC:
- ret = ghsic_data_connect(&dev->port, port_num);
- if (ret) {
- pr_err("%s: ghsic_data_connect failed: err:%d\n",
- __func__, ret);
- ghsic_ctrl_disconnect(&dev->port, port_num);
- return ret;
- }
- break;
- case USB_GADGET_XPORT_ETHER:
- gether_enable_sg(&dev->gether_port, true);
- net = gether_connect(&dev->gether_port);
- if (IS_ERR(net)) {
- pr_err("%s: gether_connect failed: err:%ld\n",
- __func__, PTR_ERR(net));
- if (cxport == USB_GADGET_XPORT_QTI)
- gqti_ctrl_disconnect(&dev->port, port_num);
- else
- gsmd_ctrl_disconnect(&dev->port, port_num);
-
- return PTR_ERR(net);
- }
- gether_update_dl_max_pkts_per_xfer(&dev->gether_port,
- rmnet_dl_max_pkt_per_xfer);
- gether_update_dl_max_xfer_size(&dev->gether_port, 16384);
- break;
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %s\n", __func__,
- xport_to_str(dxport));
- return -ENODEV;
+ dev->ipa_port.cdev = dev->cdev;
+ ipa_data_port_select(USB_IPA_FUNC_RMNET);
+ usb_bam_type = usb_bam_get_bam_type(gadget->name);
+ src_connection_idx = usb_bam_get_connection_idx(usb_bam_type,
+ IPA_P_BAM, USB_TO_PEER_PERIPHERAL, USB_BAM_DEVICE,
+ QTI_PORT_RMNET);
+ dst_connection_idx = usb_bam_get_connection_idx(usb_bam_type,
+ IPA_P_BAM, PEER_PERIPHERAL_TO_USB, USB_BAM_DEVICE,
+ QTI_PORT_RMNET);
+ if (dst_connection_idx < 0 || src_connection_idx < 0) {
+ pr_err("%s: usb_bam_get_connection_idx failed\n",
+ __func__);
+ gqti_ctrl_disconnect(&dev->port, QTI_PORT_RMNET);
+ return -EINVAL;
+ }
+ ret = ipa_data_connect(&dev->ipa_port, USB_IPA_FUNC_RMNET,
+ src_connection_idx, dst_connection_idx);
+ if (ret) {
+ pr_err("%s: ipa_data_connect failed: err:%d\n",
+ __func__, ret);
+ gqti_ctrl_disconnect(&dev->port, QTI_PORT_RMNET);
+ return ret;
}
return 0;
@@ -504,61 +322,26 @@ static int gport_rmnet_connect(struct f_rmnet *dev, unsigned intf)
static int gport_rmnet_disconnect(struct f_rmnet *dev)
{
- unsigned port_num;
- enum transport_type cxport = rmnet_ports[dev->port_num].ctrl_xport;
- enum transport_type dxport = rmnet_ports[dev->port_num].data_xport;
-
- pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n",
- __func__, xport_to_str(cxport), xport_to_str(dxport),
- dev, dev->port_num);
-
- port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
- switch (cxport) {
- case USB_GADGET_XPORT_SMD:
- gsmd_ctrl_disconnect(&dev->port, port_num);
- break;
- case USB_GADGET_XPORT_QTI:
- gqti_ctrl_disconnect(&dev->port, port_num);
- break;
- case USB_GADGET_XPORT_HSIC:
- ghsic_ctrl_disconnect(&dev->port, port_num);
- break;
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %s\n", __func__,
- xport_to_str(cxport));
- return -ENODEV;
- }
+ gqti_ctrl_disconnect(&dev->port, QTI_PORT_RMNET);
+ ipa_data_disconnect(&dev->ipa_port, USB_IPA_FUNC_RMNET);
+ return 0;
+}
- port_num = rmnet_ports[dev->port_num].data_xport_num;
- switch (dxport) {
- case USB_GADGET_XPORT_BAM_DMUX:
- case USB_GADGET_XPORT_BAM2BAM_IPA:
- gbam_disconnect(&dev->port, port_num, dxport);
- break;
- case USB_GADGET_XPORT_HSIC:
- ghsic_data_disconnect(&dev->port, port_num);
- break;
- case USB_GADGET_XPORT_ETHER:
- gether_disconnect(&dev->gether_port);
- break;
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %s\n", __func__,
- xport_to_str(dxport));
- return -ENODEV;
- }
+static void frmnet_free(struct usb_function *f)
+{
+ struct f_rmnet_opts *opts;
- return 0;
+ opts = container_of(f->fi, struct f_rmnet_opts, func_inst);
+ opts->refcnt--;
+ kfree(rmnet_port);
+ rmnet_port = NULL;
}
static void frmnet_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_rmnet *dev = func_to_rmnet(f);
- pr_debug("%s: portno:%d\n", __func__, dev->port_num);
+ pr_debug("%s: start unbinding\n", __func__);
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
@@ -575,8 +358,7 @@ static void frmnet_purge_responses(struct f_rmnet *dev)
unsigned long flags;
struct rmnet_ctrl_pkt *cpkt;
- pr_debug("%s: port#%d\n", __func__, dev->port_num);
-
+ pr_debug("%s: Purging responses\n", __func__);
spin_lock_irqsave(&dev->lock, flags);
while (!list_empty(&dev->cpkt_resp_q)) {
cpkt = list_first_entry(&dev->cpkt_resp_q,
@@ -591,117 +373,46 @@ static void frmnet_purge_responses(struct f_rmnet *dev)
static void frmnet_suspend(struct usb_function *f)
{
- struct f_rmnet *dev = func_to_rmnet(f);
- unsigned port_num;
- enum transport_type dxport = rmnet_ports[dev->port_num].data_xport;
- bool remote_wakeup_allowed;
+ struct f_rmnet *dev = func_to_rmnet(f);
+ bool remote_wakeup_allowed;
if (f->config->cdev->gadget->speed == USB_SPEED_SUPER)
remote_wakeup_allowed = f->func_wakeup_allowed;
else
remote_wakeup_allowed = f->config->cdev->gadget->remote_wakeup;
- pr_debug("%s: data xport: %s dev: %p portno: %d remote_wakeup: %d\n",
- __func__, xport_to_str(dxport),
- dev, dev->port_num, remote_wakeup_allowed);
+ pr_debug("%s: dev: %p remote_wakeup: %d\n",
+ __func__, dev, remote_wakeup_allowed);
usb_ep_fifo_flush(dev->notify);
frmnet_purge_responses(dev);
- port_num = rmnet_ports[dev->port_num].data_xport_num;
- switch (dxport) {
- case USB_GADGET_XPORT_BAM_DMUX:
- break;
- case USB_GADGET_XPORT_BAM2BAM_IPA:
- if (remote_wakeup_allowed) {
- gbam_suspend(&dev->port, port_num, dxport);
- } else {
- /*
- * When remote wakeup is disabled, IPA is disconnected
- * because it cannot send new data until the USB bus is
- * resumed. Endpoint descriptors info is saved before it
- * gets reset by the BAM disconnect API. This lets us
- * restore this info when the USB bus is resumed.
- */
- dev->in_ep_desc_backup = dev->port.in->desc;
- dev->out_ep_desc_backup = dev->port.out->desc;
- pr_debug("in_ep_desc_bkup = %p, out_ep_desc_bkup = %p",
- dev->in_ep_desc_backup, dev->out_ep_desc_backup);
- pr_debug("%s(): Disconnecting\n", __func__);
- gport_rmnet_disconnect(dev);
- }
- break;
- case USB_GADGET_XPORT_HSIC:
- break;
- case USB_GADGET_XPORT_HSUART:
- break;
- case USB_GADGET_XPORT_ETHER:
- break;
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %s\n", __func__,
- xport_to_str(dxport));
- }
+ ipa_data_suspend(&dev->ipa_port, USB_IPA_FUNC_RMNET,
+ remote_wakeup_allowed);
}
static void frmnet_resume(struct usb_function *f)
{
- struct f_rmnet *dev = func_to_rmnet(f);
- unsigned port_num;
- enum transport_type dxport = rmnet_ports[dev->port_num].data_xport;
- int ret;
- bool remote_wakeup_allowed;
+ struct f_rmnet *dev = func_to_rmnet(f);
+ bool remote_wakeup_allowed;
if (f->config->cdev->gadget->speed == USB_SPEED_SUPER)
remote_wakeup_allowed = f->func_wakeup_allowed;
else
remote_wakeup_allowed = f->config->cdev->gadget->remote_wakeup;
- pr_debug("%s: data xport: %s dev: %p portno: %d remote_wakeup: %d\n",
- __func__, xport_to_str(dxport),
- dev, dev->port_num, remote_wakeup_allowed);
+ pr_debug("%s: dev: %p remote_wakeup: %d\n",
+ __func__, dev, remote_wakeup_allowed);
- port_num = rmnet_ports[dev->port_num].data_xport_num;
- switch (dxport) {
- case USB_GADGET_XPORT_BAM_DMUX:
- break;
- case USB_GADGET_XPORT_BAM2BAM_IPA:
- if (remote_wakeup_allowed) {
- gbam_resume(&dev->port, port_num, dxport);
- } else {
- dev->port.in->desc = dev->in_ep_desc_backup;
- dev->port.out->desc = dev->out_ep_desc_backup;
- pr_debug("%s(): Connecting\n", __func__);
- ret = gport_rmnet_connect(dev, dev->ifc_id);
- if (ret) {
- pr_err("%s: gport_rmnet_connect failed: err:%d\n",
- __func__, ret);
- }
- }
- break;
- case USB_GADGET_XPORT_HSIC:
- break;
- case USB_GADGET_XPORT_HSUART:
- break;
- case USB_GADGET_XPORT_ETHER:
- break;
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %s\n", __func__,
- xport_to_str(dxport));
- }
+ ipa_data_resume(&dev->ipa_port, USB_IPA_FUNC_RMNET,
+ remote_wakeup_allowed);
}
static void frmnet_disable(struct usb_function *f)
{
- struct f_rmnet *dev = func_to_rmnet(f);
- enum transport_type dxport = rmnet_ports[dev->port_num].data_xport;
- struct usb_composite_dev *cdev = dev->cdev;
-
- pr_debug("%s: port#%d\n", __func__, dev->port_num);
+ struct f_rmnet *dev = func_to_rmnet(f);
+ pr_debug("%s: Disabling\n", __func__);
usb_ep_disable(dev->notify);
dev->notify->driver_data = NULL;
@@ -709,11 +420,8 @@ static void frmnet_disable(struct usb_function *f)
frmnet_purge_responses(dev);
- if (dxport == USB_GADGET_XPORT_BAM2BAM_IPA &&
- gadget_is_dwc3(cdev->gadget)) {
- msm_ep_unconfig(dev->port.out);
- msm_ep_unconfig(dev->port.in);
- }
+ msm_ep_unconfig(dev->ipa_port.out);
+ msm_ep_unconfig(dev->ipa_port.in);
gport_rmnet_disconnect(dev);
}
@@ -721,14 +429,14 @@ static int
frmnet_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct f_rmnet *dev = func_to_rmnet(f);
- struct usb_composite_dev *cdev = dev->cdev;
+ struct usb_composite_dev *cdev = f->config->cdev;
int ret;
- struct list_head *cpkt;
-
- pr_debug("%s:dev:%p port#%d\n", __func__, dev, dev->port_num);
+ struct list_head *cpkt;
+ pr_debug("%s: dev: %p\n", __func__, dev);
+ dev->cdev = cdev;
if (dev->notify->driver_data) {
- pr_debug("%s: reset port:%d\n", __func__, dev->port_num);
+ pr_debug("%s: reset port\n", __func__);
usb_ep_disable(dev->notify);
}
@@ -749,14 +457,14 @@ frmnet_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
}
dev->notify->driver_data = dev;
- if (!dev->port.in->desc || !dev->port.out->desc) {
- if (config_ep_by_speed(cdev->gadget, f, dev->port.in) ||
- config_ep_by_speed(cdev->gadget, f, dev->port.out)) {
+ if (!dev->ipa_port.in->desc || !dev->ipa_port.out->desc) {
+ if (config_ep_by_speed(cdev->gadget, f, dev->ipa_port.in) ||
+ config_ep_by_speed(cdev->gadget, f, dev->ipa_port.out)) {
pr_err("%s(): config_ep_by_speed failed.\n", __func__);
ret = -EINVAL;
goto err_disable_ep;
}
- dev->port.gadget = dev->cdev->gadget;
+ dev->ipa_port.cdev = dev->cdev;
}
ret = gport_rmnet_connect(dev, intf);
@@ -777,8 +485,8 @@ frmnet_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
return ret;
err_disable_ep:
- dev->port.in->desc = NULL;
- dev->port.out->desc = NULL;
+ dev->ipa_port.in->desc = NULL;
+ dev->ipa_port.out->desc = NULL;
usb_ep_disable(dev->notify);
return ret;
@@ -790,10 +498,9 @@ static void frmnet_ctrl_response_available(struct f_rmnet *dev)
struct usb_cdc_notification *event;
unsigned long flags;
int ret;
- struct rmnet_ctrl_pkt *cpkt;
-
- pr_debug("%s:dev:%p portno#%d\n", __func__, dev, dev->port_num);
+ struct rmnet_ctrl_pkt *cpkt;
+ pr_debug("%s: dev: %p\n", __func__, dev);
spin_lock_irqsave(&dev->lock, flags);
if (!atomic_read(&dev->online) || !req || !req->buf) {
spin_unlock_irqrestore(&dev->lock, flags);
@@ -913,8 +620,7 @@ frmnet_send_cpkt_response(void *gr, void *buf, size_t len)
dev = port_to_rmnet(gr);
- pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
-
+ pr_debug("%s: dev: %p\n", __func__, dev);
if (!atomic_read(&dev->online) || !atomic_read(&dev->ctrl_online)) {
rmnet_free_ctrl_pkt(cpkt);
return 0;
@@ -934,32 +640,27 @@ frmnet_cmd_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_rmnet *dev = req->context;
struct usb_composite_dev *cdev;
- unsigned port_num;
if (!dev) {
pr_err("%s: rmnet dev is null\n", __func__);
return;
}
-
- pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
-
+ pr_debug("%s: dev: %p\n", __func__, dev);
cdev = dev->cdev;
if (dev->port.send_encap_cmd) {
- port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
- dev->port.send_encap_cmd(port_num, req->buf, req->actual);
+ dev->port.send_encap_cmd(QTI_PORT_RMNET, req->buf, req->actual);
}
}
static void frmnet_notify_complete(struct usb_ep *ep, struct usb_request *req)
{
- struct f_rmnet *dev = req->context;
- int status = req->status;
+ struct f_rmnet *dev = req->context;
+ int status = req->status;
unsigned long flags;
struct rmnet_ctrl_pkt *cpkt;
- pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
-
+ pr_debug("%s: dev: %p\n", __func__, dev);
switch (status) {
case -ECONNRESET:
case -ESHUTDOWN:
@@ -1021,14 +722,12 @@ frmnet_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
struct f_rmnet *dev = func_to_rmnet(f);
struct usb_composite_dev *cdev = dev->cdev;
struct usb_request *req = cdev->req;
- unsigned port_num;
u16 w_index = le16_to_cpu(ctrl->wIndex);
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength);
int ret = -EOPNOTSUPP;
- pr_debug("%s:dev:%p port#%d\n", __func__, dev, dev->port_num);
-
+ pr_debug("%s: dev: %p\n", __func__, dev);
if (!atomic_read(&dev->online)) {
pr_warn("%s: usb cable is not connected\n", __func__);
return -ENOTCONN;
@@ -1085,8 +784,8 @@ frmnet_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
pr_debug("%s: USB_CDC_REQ_SET_CONTROL_LINE_STATE: DTR:%d\n",
__func__, w_value & ACM_CTRL_DTR ? 1 : 0);
if (dev->port.notify_modem) {
- port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
- dev->port.notify_modem(&dev->port, port_num, w_value);
+ dev->port.notify_modem(&dev->port,
+ QTI_PORT_RMNET, w_value);
}
ret = 0;
@@ -1121,6 +820,16 @@ static int frmnet_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
int ret = -ENODEV;
+ if (rmnet_string_defs[0].id == 0) {
+ ret = usb_string_id(c->cdev);
+ if (ret < 0) {
+ pr_err("%s: failed to get string id, err:%d\n",
+ __func__, ret);
+ return ret;
+ }
+ rmnet_string_defs[0].id = ret;
+ }
+
pr_debug("%s: start binding\n", __func__);
dev->ifc_id = usb_interface_id(c, f);
if (dev->ifc_id < 0) {
@@ -1135,9 +844,7 @@ static int frmnet_bind(struct usb_configuration *c, struct usb_function *f)
pr_err("%s: usb epin autoconfig failed\n", __func__);
return -ENODEV;
}
- dev->port.in = ep;
- /* Update same for u_ether which uses gether port struct */
- dev->gether_port.in_ep = ep;
+ dev->ipa_port.in = ep;
ep->driver_data = cdev;
ep = usb_ep_autoconfig(cdev->gadget, &rmnet_fs_out_desc);
@@ -1146,9 +853,7 @@ static int frmnet_bind(struct usb_configuration *c, struct usb_function *f)
ret = -ENODEV;
goto ep_auto_out_fail;
}
- dev->port.out = ep;
- /* Update same for u_ether which uses gether port struct */
- dev->gether_port.out_ep = ep;
+ dev->ipa_port.out = ep;
ep->driver_data = cdev;
ep = usb_ep_autoconfig(cdev->gadget, &rmnet_fs_notify_desc);
@@ -1162,7 +867,6 @@ static int frmnet_bind(struct usb_configuration *c, struct usb_function *f)
dev->notify_req = frmnet_alloc_req(ep,
sizeof(struct usb_cdc_notification),
- cdev->gadget->extra_buf_alloc,
GFP_KERNEL);
if (IS_ERR(dev->notify_req)) {
pr_err("%s: unable to allocate memory for notify req\n",
@@ -1218,10 +922,9 @@ static int frmnet_bind(struct usb_configuration *c, struct usb_function *f)
}
}
- pr_debug("%s: RmNet(%d) %s Speed, IN:%s OUT:%s\n",
- __func__, dev->port_num,
- gadget_is_dualspeed(cdev->gadget) ? "dual" : "full",
- dev->port.in->name, dev->port.out->name);
+ pr_debug("%s: RmNet %s Speed, IN:%s OUT:%s\n",
+ __func__, gadget_is_dualspeed(cdev->gadget) ? "dual" : "full",
+ dev->ipa_port.in->name, dev->ipa_port.out->name);
return 0;
@@ -1238,67 +941,35 @@ ep_notify_alloc_fail:
dev->notify->driver_data = NULL;
dev->notify = NULL;
ep_auto_notify_fail:
- dev->port.out->driver_data = NULL;
- dev->port.out = NULL;
+ dev->ipa_port.out->driver_data = NULL;
+ dev->ipa_port.out = NULL;
ep_auto_out_fail:
- dev->port.in->driver_data = NULL;
- dev->port.in = NULL;
+ dev->ipa_port.in->driver_data = NULL;
+ dev->ipa_port.in = NULL;
return ret;
}
-static int frmnet_bind_config(struct usb_configuration *c, unsigned portno)
+static struct usb_function *frmnet_bind_config(struct usb_function_instance *fi)
{
+ struct f_rmnet_opts *opts;
int status;
struct f_rmnet *dev;
struct usb_function *f;
unsigned long flags;
- pr_debug("%s: usb config:%p\n", __func__, c);
-
- if (portno >= nr_rmnet_ports) {
- pr_err("%s: supporting ports#%u port_id:%u\n", __func__,
- nr_rmnet_ports, portno);
- return -ENODEV;
- }
-
- dev = rmnet_ports[portno].port;
-
- if (rmnet_ports[portno].data_xport == USB_GADGET_XPORT_ETHER) {
- struct net_device *net = gether_setup_name_default("usb_rmnet");
-
- if (IS_ERR(net)) {
- pr_err("%s: gether_setup failed\n", __func__);
- return PTR_ERR(net);
- }
- dev->gether_port.ioport = netdev_priv(net);
- gether_set_gadget(net, c->cdev->gadget);
- status = gether_register_netdev(net);
- if (status < 0) {
- pr_err("%s: gether_register_netdev failed\n", __func__);
- free_netdev(net);
- return status;
- }
- }
-
- if (rmnet_string_defs[0].id == 0) {
- status = usb_string_id(c->cdev);
- if (status < 0) {
- pr_err("%s: failed to get string id, err:%d\n",
- __func__, status);
- return status;
- }
- rmnet_string_defs[0].id = status;
- }
-
+ /* allocate and initialize one new instance */
+ status = -ENOMEM;
+ opts = container_of(fi, struct f_rmnet_opts, func_inst);
+ opts->refcnt++;
+ dev = opts->dev;
spin_lock_irqsave(&dev->lock, flags);
- dev->cdev = c->cdev;
- f = &dev->gether_port.func;
- f->name = kasprintf(GFP_ATOMIC, "rmnet%d", portno);
+ f = &dev->func;
+ f->name = kasprintf(GFP_ATOMIC, "rmnet%d", 0);
spin_unlock_irqrestore(&dev->lock, flags);
if (!f->name) {
pr_err("%s: cannot allocate memory for name\n", __func__);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
f->strings = rmnet_strings;
@@ -1309,166 +980,123 @@ static int frmnet_bind_config(struct usb_configuration *c, unsigned portno)
f->setup = frmnet_setup;
f->suspend = frmnet_suspend;
f->resume = frmnet_resume;
+ f->free_func = frmnet_free;
dev->port.send_cpkt_response = frmnet_send_cpkt_response;
dev->port.disconnect = frmnet_disconnect;
dev->port.connect = frmnet_connect;
- dev->gether_port.cdc_filter = 0;
-
- status = usb_add_function(c, f);
- if (status) {
- pr_err("%s: usb add function failed: %d\n",
- __func__, status);
- kfree(f->name);
- return status;
- }
pr_debug("%s: complete\n", __func__);
- return status;
+ return f;
}
-static void frmnet_unbind_config(void)
+static int rmnet_init(void)
{
- int i;
+ return gqti_ctrl_init();
+}
- for (i = 0; i < nr_rmnet_ports; i++)
- if (rmnet_ports[i].data_xport == USB_GADGET_XPORT_ETHER) {
- gether_cleanup(rmnet_ports[i].port->gether_port.ioport);
- rmnet_ports[i].port->gether_port.ioport = NULL;
- }
+static void frmnet_cleanup(void)
+{
+ gqti_ctrl_cleanup();
}
-static int rmnet_init(void)
+static void rmnet_free_inst(struct usb_function_instance *f)
{
- return gqti_ctrl_init();
+ struct f_rmnet_opts *opts = container_of(f, struct f_rmnet_opts,
+ func_inst);
+ ipa_data_free(USB_IPA_FUNC_RMNET);
+ kfree(opts);
}
-static void frmnet_cleanup(void)
+static int rmnet_set_inst_name(struct usb_function_instance *fi,
+ const char *name)
{
- int i;
+ int name_len;
+ int ret;
- gqti_ctrl_cleanup();
+ name_len = strlen(name) + 1;
+ if (name_len > MAX_INST_NAME_LEN)
+ return -ENAMETOOLONG;
- for (i = 0; i < nr_rmnet_ports; i++)
- kfree(rmnet_ports[i].port);
-
- gbam_cleanup();
- nr_rmnet_ports = 0;
- no_ctrl_smd_ports = 0;
- no_ctrl_qti_ports = 0;
- no_data_bam_ports = 0;
- no_data_bam2bam_ports = 0;
- no_ctrl_hsic_ports = 0;
- no_data_hsic_ports = 0;
- no_ctrl_hsuart_ports = 0;
- no_data_hsuart_ports = 0;
+ ret = ipa_data_setup(USB_IPA_FUNC_RMNET);
+ return ret;
}
-static int frmnet_init_port(const char *ctrl_name, const char *data_name,
- const char *port_name)
+static inline struct f_rmnet_opts *to_f_rmnet_opts(struct config_item *item)
{
- struct f_rmnet *dev;
- struct rmnet_ports *rmnet_port;
- int ret;
- int i;
+ return container_of(to_config_group(item), struct f_rmnet_opts,
+ func_inst.group);
+}
- if (nr_rmnet_ports >= NR_RMNET_PORTS) {
- pr_err("%s: Max-%d instances supported\n",
- __func__, NR_RMNET_PORTS);
- return -EINVAL;
- }
+static void rmnet_opts_release(struct config_item *item)
+{
+ struct f_rmnet_opts *opts = to_f_rmnet_opts(item);
- pr_debug("%s: port#:%d, ctrl port: %s data port: %s\n",
- __func__, nr_rmnet_ports, ctrl_name, data_name);
+ usb_put_function_instance(&opts->func_inst);
+};
- dev = kzalloc(sizeof(struct f_rmnet), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
+static struct configfs_item_operations rmnet_item_ops = {
+ .release = rmnet_opts_release,
+};
- dev->port_num = nr_rmnet_ports;
- spin_lock_init(&dev->lock);
- INIT_LIST_HEAD(&dev->cpkt_resp_q);
+static struct config_item_type rmnet_func_type = {
+ .ct_item_ops = &rmnet_item_ops,
+ .ct_owner = THIS_MODULE,
+};
- rmnet_port = &rmnet_ports[nr_rmnet_ports];
- rmnet_port->port = dev;
- rmnet_port->port_num = nr_rmnet_ports;
- rmnet_port->ctrl_xport = str_to_xport(ctrl_name);
- rmnet_port->data_xport = str_to_xport(data_name);
+static struct usb_function_instance *rmnet_alloc_inst(void)
+{
+ struct f_rmnet_opts *opts;
- switch (rmnet_port->ctrl_xport) {
- case USB_GADGET_XPORT_SMD:
- rmnet_port->ctrl_xport_num = no_ctrl_smd_ports;
- no_ctrl_smd_ports++;
- break;
- case USB_GADGET_XPORT_QTI:
- rmnet_port->ctrl_xport_num = no_ctrl_qti_ports;
- no_ctrl_qti_ports++;
- break;
- case USB_GADGET_XPORT_HSIC:
- ghsic_ctrl_set_port_name(port_name, ctrl_name);
- rmnet_port->ctrl_xport_num = no_ctrl_hsic_ports;
- no_ctrl_hsic_ports++;
- break;
- case USB_GADGET_XPORT_HSUART:
- rmnet_port->ctrl_xport_num = no_ctrl_hsuart_ports;
- no_ctrl_hsuart_ports++;
- break;
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %u\n", __func__,
- rmnet_port->ctrl_xport);
- ret = -ENODEV;
- goto fail_probe;
- }
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return ERR_PTR(-ENOMEM);
- switch (rmnet_port->data_xport) {
- case USB_GADGET_XPORT_BAM2BAM:
- /* Override BAM2BAM to BAM_DMUX for old ABI compatibility */
- rmnet_port->data_xport = USB_GADGET_XPORT_BAM_DMUX;
- /* fall-through */
- case USB_GADGET_XPORT_BAM_DMUX:
- rmnet_port->data_xport_num = no_data_bam_ports;
- no_data_bam_ports++;
- break;
- case USB_GADGET_XPORT_BAM2BAM_IPA:
- rmnet_port->data_xport_num = no_data_bam2bam_ports;
- no_data_bam2bam_ports++;
- break;
- case USB_GADGET_XPORT_HSIC:
- ghsic_data_set_port_name(port_name, data_name);
- rmnet_port->data_xport_num = no_data_hsic_ports;
- no_data_hsic_ports++;
- break;
- case USB_GADGET_XPORT_HSUART:
- rmnet_port->data_xport_num = no_data_hsuart_ports;
- no_data_hsuart_ports++;
- break;
- case USB_GADGET_XPORT_ETHER:
- case USB_GADGET_XPORT_NONE:
- break;
- default:
- pr_err("%s: Un-supported transport: %u\n", __func__,
- rmnet_port->data_xport);
- ret = -ENODEV;
- goto fail_probe;
- }
- nr_rmnet_ports++;
+ opts->func_inst.set_inst_name = rmnet_set_inst_name;
+ opts->func_inst.free_func_inst = rmnet_free_inst;
- return 0;
+ config_group_init_type_name(&opts->func_inst.group, "",
+ &rmnet_func_type);
+ return &opts->func_inst;
+}
+
+static struct usb_function *rmnet_alloc(struct usb_function_instance *fi)
+{
+ struct f_rmnet_opts *opts = container_of(fi,
+ struct f_rmnet_opts, func_inst);
+ rmnet_port = kzalloc(sizeof(struct f_rmnet), GFP_KERNEL);
+ if (!rmnet_port)
+ return ERR_PTR(-ENOMEM);
+ opts->dev = rmnet_port;
+ spin_lock_init(&rmnet_port->lock);
+ INIT_LIST_HEAD(&rmnet_port->cpkt_resp_q);
+ return frmnet_bind_config(fi);
+}
-fail_probe:
- for (i = 0; i < nr_rmnet_ports; i++)
- kfree(rmnet_ports[i].port);
+DECLARE_USB_FUNCTION(rmnet_bam, rmnet_alloc_inst, rmnet_alloc);
- nr_rmnet_ports = 0;
- no_ctrl_smd_ports = 0;
- no_ctrl_qti_ports = 0;
- no_data_bam_ports = 0;
- no_ctrl_hsic_ports = 0;
- no_data_hsic_ports = 0;
- no_ctrl_hsuart_ports = 0;
- no_data_hsuart_ports = 0;
+static int __init usb_rmnet_init(void)
+{
+ int ret;
+ ret = rmnet_init();
+ if (!ret) {
+ ret = usb_function_register(&rmnet_bamusb_func);
+ if (ret) {
+ pr_err("%s: failed to register rmnet %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
return ret;
}
+
+static void __exit usb_rmnet_exit(void)
+{
+ usb_function_unregister(&rmnet_bamusb_func);
+ frmnet_cleanup();
+}
+
+module_init(usb_rmnet_init);
+module_exit(usb_rmnet_exit);
+MODULE_DESCRIPTION("USB RMNET Function Driver");
diff --git a/drivers/usb/gadget/function/u_ctrl_qti.c b/drivers/usb/gadget/function/u_ctrl_qti.c
index 7ef56eca20b8..c0650b0abf8c 100644
--- a/drivers/usb/gadget/function/u_ctrl_qti.c
+++ b/drivers/usb/gadget/function/u_ctrl_qti.c
@@ -14,11 +14,11 @@
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/usb/usb_ctrl_qti.h>
-
-#include <soc/qcom/bam_dmux.h>
+#include <linux/miscdevice.h>
+#include <linux/debugfs.h>
#include "u_rmnet.h"
-#include "usb_gadget_xport.h"
+#include "f_qdss.h"
#define RMNET_CTRL_QTI_NAME "rmnet_ctrl"
#define DPL_CTRL_QTI_NAME "dpl_ctrl"
@@ -54,18 +54,18 @@ struct qti_ctrl_port {
struct list_head cpkt_req_q;
spinlock_t lock;
- enum gadget_type gtype;
+ enum qti_port_type port_type;
unsigned host_to_modem;
unsigned copied_to_modem;
unsigned copied_from_modem;
unsigned modem_to_host;
unsigned drp_cpkt_cnt;
};
-static struct qti_ctrl_port *ctrl_port[NR_QTI_PORTS];
+static struct qti_ctrl_port *ctrl_port[QTI_NUM_PORTS];
static inline int qti_ctrl_lock(atomic_t *excl)
{
- if (atomic_inc_return(excl) == 1) {
+ if (atomic_inc_return(excl) == 1)
return 0;
atomic_dec(excl);
return -EBUSY;
@@ -76,6 +76,32 @@ static inline void qti_ctrl_unlock(atomic_t *excl)
atomic_dec(excl);
}
+static struct rmnet_ctrl_pkt *alloc_rmnet_ctrl_pkt(unsigned len, gfp_t flags)
+{
+ struct rmnet_ctrl_pkt *pkt;
+
+ pkt = kzalloc(sizeof(struct rmnet_ctrl_pkt), flags);
+ if (!pkt)
+ return ERR_PTR(-ENOMEM);
+
+ pkt->buf = kmalloc(len, flags);
+ if (!pkt->buf) {
+ kfree(pkt);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ pkt->len = len;
+
+ return pkt;
+}
+
+static void free_rmnet_ctrl_pkt(struct rmnet_ctrl_pkt *pkt)
+{
+ kfree(pkt->buf);
+ kfree(pkt);
+}
+
+
static void qti_ctrl_queue_notify(struct qti_ctrl_port *port)
{
unsigned long flags;
@@ -106,7 +132,8 @@ static void qti_ctrl_queue_notify(struct qti_ctrl_port *port)
wake_up(&port->read_wq);
}
-static int gqti_ctrl_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
+static int gqti_ctrl_send_cpkt_tomodem(enum qti_port_type qport,
+ void *buf, size_t len)
{
unsigned long flags;
struct qti_ctrl_port *port;
@@ -118,12 +145,11 @@ static int gqti_ctrl_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
return -EINVAL;
}
- if (portno >= NR_QTI_PORTS) {
- pr_err("%s: Invalid QTI port %d\n", __func__, portno);
+ if (qport >= QTI_NUM_PORTS) {
+ pr_err("%s: Invalid QTI port %d\n", __func__, qport);
return -ENODEV;
}
- port = ctrl_port[portno];
-
+ port = ctrl_port[qport];
cpkt = alloc_rmnet_ctrl_pkt(len, GFP_ATOMIC);
if (IS_ERR(cpkt)) {
pr_err("%s: Unable to allocate ctrl pkt\n", __func__);
@@ -133,8 +159,8 @@ static int gqti_ctrl_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
memcpy(cpkt->buf, buf, len);
cpkt->len = len;
- pr_debug("%s: gtype:%d: Add to cpkt_req_q packet with len = %zu\n",
- __func__, port->gtype, len);
+ pr_debug("%s: port type:%d: Add to cpkt_req_q packet with len = %zu\n",
+ __func__, port->port_type, len);
spin_lock_irqsave(&port->lock, flags);
/* drop cpkt if port is not open */
@@ -159,71 +185,51 @@ static int gqti_ctrl_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
}
static void
-gqti_ctrl_notify_modem(void *gptr, u8 portno, int val)
+gqti_ctrl_notify_modem(void *gptr, enum qti_port_type qport, int val)
{
struct qti_ctrl_port *port;
- if (portno >= NR_QTI_PORTS) {
- pr_err("%s: Invalid QTI port %d\n", __func__, portno);
+ if (qport >= QTI_NUM_PORTS) {
+ pr_err("%s: Invalid QTI port %d\n", __func__, qport);
return;
}
- port = ctrl_port[portno];
-
+ port = ctrl_port[qport];
atomic_set(&port->line_state, val);
/* send 0 len pkt to qti to notify state change */
qti_ctrl_queue_notify(port);
}
-int gqti_ctrl_connect(void *gr, u8 port_num, unsigned intf,
- enum transport_type dxport, enum gadget_type gtype)
+int gqti_ctrl_connect(void *gr, enum qti_port_type qport, unsigned intf)
{
struct qti_ctrl_port *port;
struct grmnet *g_rmnet = NULL;
struct gqdss *g_dpl = NULL;
unsigned long flags;
- pr_debug("%s: gtype:%d gadget:%p\n", __func__, gtype, gr);
- if (port_num >= NR_QTI_PORTS) {
- pr_err("%s: Invalid QTI port %d\n", __func__, port_num);
+ pr_debug("%s: port type:%d gadget:%p\n", __func__, qport, gr);
+ if (qport >= QTI_NUM_PORTS) {
+ pr_err("%s: Invalid QTI port %d\n", __func__, qport);
return -ENODEV;
}
- port = ctrl_port[port_num];
+ port = ctrl_port[qport];
if (!port) {
pr_err("%s: gadget port is null\n", __func__);
return -ENODEV;
}
spin_lock_irqsave(&port->lock, flags);
- port->gtype = gtype;
- if (dxport == USB_GADGET_XPORT_BAM_DMUX) {
- /*
- * BAM-DMUX data transport is used for RMNET and DPL
- * on some targets where IPA is not available.
- * Set endpoint type as BAM-DMUX and interface
- * id as channel number. This information is
- * sent to user space via EP_LOOKUP ioctl.
- *
- */
-
- port->ep_type = DATA_EP_TYPE_BAM_DMUX;
- port->intf = (gtype == USB_GADGET_RMNET) ?
- BAM_DMUX_USB_RMNET_0 :
- BAM_DMUX_USB_DPL;
- port->ipa_prod_idx = 0;
- port->ipa_cons_idx = 0;
- } else {
- port->ep_type = DATA_EP_TYPE_HSUSB;
- port->intf = intf;
- }
+ port->port_type = qport;
+ port->ep_type = DATA_EP_TYPE_HSUSB;
+ port->intf = intf;
- if (gr && port->gtype == USB_GADGET_RMNET) {
+ if (gr && port->port_type == QTI_PORT_RMNET) {
port->port_usb = gr;
g_rmnet = (struct grmnet *)gr;
g_rmnet->send_encap_cmd = gqti_ctrl_send_cpkt_tomodem;
g_rmnet->notify_modem = gqti_ctrl_notify_modem;
- } else if (gr && port->gtype == USB_GADGET_DPL) {
+ } else if (gr && port->port_type == QTI_PORT_DPL) {
port->port_usb = gr;
g_dpl = (struct gqdss *)gr;
g_dpl->send_encap_cmd = gqti_ctrl_send_cpkt_tomodem;
@@ -231,7 +237,7 @@ int gqti_ctrl_connect(void *gr, u8 port_num, unsigned intf,
atomic_set(&port->line_state, 1);
} else {
spin_unlock_irqrestore(&port->lock, flags);
- pr_err("%s(): Port is used without gtype.\n", __func__);
+ pr_err("%s(): Port is used without port type.\n", __func__);
return -ENODEV;
}
@@ -251,7 +257,7 @@ int gqti_ctrl_connect(void *gr, u8 port_num, unsigned intf,
return 0;
}
-void gqti_ctrl_disconnect(void *gr, u8 port_num)
+void gqti_ctrl_disconnect(void *gr, enum qti_port_type qport)
{
struct qti_ctrl_port *port;
unsigned long flags;
@@ -261,13 +267,12 @@ void gqti_ctrl_disconnect(void *gr, u8 port_num)
pr_debug("%s: gadget:%p\n", __func__, gr);
- if (port_num >= NR_QTI_PORTS) {
- pr_err("%s: Invalid QTI port %d\n", __func__, port_num);
+ if (qport >= QTI_NUM_PORTS) {
+ pr_err("%s: Invalid QTI port %d\n", __func__, qport);
return;
}
- port = ctrl_port[port_num];
-
+ port = ctrl_port[qport];
if (!port) {
pr_err("%s: gadget port is null\n", __func__);
return;
@@ -282,17 +287,17 @@ void gqti_ctrl_disconnect(void *gr, u8 port_num)
port->ipa_cons_idx = -1;
port->port_usb = NULL;
- if (gr && port->gtype == USB_GADGET_RMNET) {
+ if (gr && port->port_type == QTI_PORT_RMNET) {
g_rmnet = (struct grmnet *)gr;
g_rmnet->send_encap_cmd = NULL;
g_rmnet->notify_modem = NULL;
- } else if (gr && port->gtype == USB_GADGET_DPL) {
+ } else if (gr && port->port_type == QTI_PORT_DPL) {
g_dpl = (struct gqdss *)gr;
g_dpl->send_encap_cmd = NULL;
g_dpl->notify_modem = NULL;
} else {
pr_err("%s(): unrecognized gadget type(%d).\n",
- __func__, port->gtype);
+ __func__, port->port_type);
}
while (!list_empty(&port->cpkt_req_q)) {
@@ -309,18 +314,17 @@ void gqti_ctrl_disconnect(void *gr, u8 port_num)
qti_ctrl_queue_notify(port);
}
-void gqti_ctrl_update_ipa_pipes(void *gr, u8 port_num, u32 ipa_prod,
- u32 ipa_cons)
+void gqti_ctrl_update_ipa_pipes(void *gr, enum qti_port_type qport,
+ u32 ipa_prod, u32 ipa_cons)
{
struct qti_ctrl_port *port;
- if (port_num >= NR_QTI_PORTS) {
- pr_err("%s: Invalid QTI port %d\n", __func__, port_num);
+ if (qport >= QTI_NUM_PORTS) {
+ pr_err("%s: Invalid QTI port %d\n", __func__, qport);
return;
}
- port = ctrl_port[port_num];
-
+ port = ctrl_port[qport];
port->ipa_prod_idx = ipa_prod;
port->ipa_cons_idx = ipa_cons;
@@ -492,12 +496,12 @@ qti_ctrl_write(struct file *fp, const char __user *buf, size_t count,
spin_lock_irqsave(&port->lock, flags);
if (port && port->port_usb) {
- if (port->gtype == USB_GADGET_RMNET) {
+ if (port->port_type == QTI_PORT_RMNET) {
g_rmnet = (struct grmnet *)port->port_usb;
} else {
spin_unlock_irqrestore(&port->lock, flags);
pr_err("%s(): unrecognized gadget type(%d).\n",
- __func__, port->gtype);
+ __func__, port->port_type);
return -EINVAL;
}
@@ -530,15 +534,15 @@ static long qti_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
struct ep_info info;
int val, ret = 0;
- pr_debug("%s: Received command %d for gtype:%d\n",
- __func__, cmd, port->gtype);
+ pr_debug("%s: Received command %d for port type:%d\n",
+ __func__, cmd, port->port_type);
if (qti_ctrl_lock(&port->ioctl_excl))
return -EBUSY;
switch (cmd) {
case QTI_CTRL_MODEM_OFFLINE:
- if (port && (port->gtype == USB_GADGET_DPL)) {
+ if (port && (port->port_type == QTI_PORT_DPL)) {
pr_err("%s(): Modem Offline not handled\n", __func__);
goto exit_ioctl;
}
@@ -550,7 +554,7 @@ static long qti_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
gr->disconnect(gr);
break;
case QTI_CTRL_MODEM_ONLINE:
- if (port && (port->gtype == USB_GADGET_DPL)) {
+ if (port && (port->port_type == QTI_PORT_DPL)) {
pr_err("%s(): Modem Online not handled\n", __func__);
goto exit_ioctl;
}
@@ -568,13 +572,13 @@ static long qti_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
pr_err("copying to user space failed");
ret = -EFAULT;
}
- pr_debug("%s: Sent line_state: %d for gtype:%d\n", __func__,
- atomic_read(&port->line_state), port->gtype);
+ pr_debug("%s: Sent line_state: %d for port type:%d\n", __func__,
+ atomic_read(&port->line_state), port->port_type);
break;
case QTI_CTRL_EP_LOOKUP:
- pr_debug("%s(): EP_LOOKUP for gtype:%d\n", __func__,
- port->gtype);
+ pr_debug("%s(): EP_LOOKUP for port type:%d\n", __func__,
+ port->port_type);
val = atomic_read(&port->connected);
if (!val) {
pr_err_ratelimited("EP_LOOKUP failed: not connected\n");
@@ -593,9 +597,9 @@ static long qti_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
info.ipa_ep_pair.cons_pipe_num = port->ipa_cons_idx;
info.ipa_ep_pair.prod_pipe_num = port->ipa_prod_idx;
- pr_debug("%s(): gtype:%d ep_type:%d intf:%d\n",
- __func__, port->gtype, info.ph_ep_info.ep_type,
- info.ph_ep_info.peripheral_iface_id);
+ pr_debug("%s(): port type:%d ep_type:%d intf:%d\n",
+ __func__, port->port_type, info.ph_ep_info.ep_type,
+ info.ph_ep_info.peripheral_iface_id);
pr_debug("%s(): ipa_cons_idx:%d ipa_prod_idx:%d\n",
__func__, info.ipa_ep_pair.cons_pipe_num,
@@ -650,7 +654,7 @@ static int qti_ctrl_read_stats(struct seq_file *s, void *unused)
unsigned long flags;
int i;
- for (i = 0; i < NR_QTI_PORTS; i++) {
+ for (i = 0; i < QTI_NUM_PORTS; i++) {
port = ctrl_port[i];
if (!port)
continue;
@@ -687,7 +691,7 @@ static ssize_t qti_ctrl_reset_stats(struct file *file,
int i;
unsigned long flags;
- for (i = 0; i < NR_QTI_PORTS; i++) {
+ for (i = 0; i < QTI_NUM_PORTS; i++) {
port = ctrl_port[i];
if (!port)
continue;
@@ -762,10 +766,9 @@ int gqti_ctrl_init(void)
int ret, i, sz = QTI_CTRL_NAME_LEN;
struct qti_ctrl_port *port = NULL;
- for (i = 0; i < NR_QTI_PORTS; i++) {
+ for (i = 0; i < QTI_NUM_PORTS; i++) {
port = kzalloc(sizeof(struct qti_ctrl_port), GFP_KERNEL);
if (!port) {
- pr_err("Failed to allocate rmnet control device\n");
ret = -ENOMEM;
goto fail_init;
}
@@ -787,16 +790,16 @@ int gqti_ctrl_init(void)
port->ipa_prod_idx = -1;
port->ipa_cons_idx = -1;
- if (i == 0)
+ if (i == QTI_PORT_RMNET)
strlcat(port->name, RMNET_CTRL_QTI_NAME, sz);
- else if (i == DPL_QTI_CTRL_PORT_NO)
+ else if (i == QTI_PORT_DPL)
strlcat(port->name, DPL_CTRL_QTI_NAME, sz);
else
snprintf(port->name, sz, "%s%d",
- RMNET_CTRL_QTI_NAME, i);
+ RMNET_CTRL_QTI_NAME, i);
port->ctrl_device.name = port->name;
- if (i == DPL_QTI_CTRL_PORT_NO)
+ if (i == QTI_PORT_DPL)
port->ctrl_device.fops = &dpl_qti_ctrl_fops;
else
port->ctrl_device.fops = &qti_ctrl_fops;
@@ -809,7 +812,6 @@ int gqti_ctrl_init(void)
}
}
qti_ctrl_debugfs_init();
-
return ret;
fail_init:
@@ -825,7 +827,7 @@ void gqti_ctrl_cleanup(void)
{
int i;
- for (i = 0; i < NR_QTI_PORTS; i++) {
+ for (i = 0; i < QTI_NUM_PORTS; i++) {
misc_deregister(&ctrl_port[i]->ctrl_device);
kfree(ctrl_port[i]);
ctrl_port[i] = NULL;
diff --git a/drivers/usb/gadget/function/u_data_ipa.c b/drivers/usb/gadget/function/u_data_ipa.c
index 56e7dea427ec..2da0c59fdfc2 100644
--- a/drivers/usb/gadget/function/u_data_ipa.c
+++ b/drivers/usb/gadget/function/u_data_ipa.c
@@ -23,6 +23,7 @@
#include <linux/usb_bam.h>
#include "u_data_ipa.h"
+#include "u_rmnet.h"
struct ipa_data_ch_info {
struct usb_request *rx_req;
@@ -564,6 +565,11 @@ static void ipa_data_connect_work(struct work_struct *w)
atomic_set(&port->pipe_connect_notified, 1);
}
+ if (port->func_type == USB_IPA_FUNC_RMNET) {
+ gqti_ctrl_update_ipa_pipes(port->port_usb, QTI_PORT_RMNET,
+ gport->ipa_producer_ep, gport->ipa_consumer_ep);
+ }
+
pr_debug("ipa_producer_ep:%d ipa_consumer_ep:%d\n",
gport->ipa_producer_ep,
gport->ipa_consumer_ep);
@@ -1135,7 +1141,7 @@ int ipa_data_setup(enum ipa_func_type func)
}
if (ipa_data_wq) {
pr_debug("ipa_data_wq is already setup.");
- goto free_rndis_data;
+ return 0;
}
ipa_data_wq = alloc_workqueue("k_usb_ipa_data",
diff --git a/drivers/usb/gadget/function/u_data_ipa.h b/drivers/usb/gadget/function/u_data_ipa.h
index a1c1055bd8ef..14411575af22 100644
--- a/drivers/usb/gadget/function/u_data_ipa.h
+++ b/drivers/usb/gadget/function/u_data_ipa.h
@@ -20,6 +20,8 @@
#include <linux/ipa_usb.h>
#include <linux/usb_bam.h>
+#include "u_rmnet.h"
+
enum ipa_func_type {
USB_IPA_FUNC_ECM,
USB_IPA_FUNC_MBIM,
@@ -57,6 +59,12 @@ struct f_rndis_qc_opts {
int refcnt;
};
+struct f_rmnet_opts {
+ struct usb_function_instance func_inst;
+ struct f_rmnet *dev;
+ int refcnt;
+};
+
void ipa_data_port_select(enum ipa_func_type func);
void ipa_data_disconnect(struct gadget_ipa_port *gp, enum ipa_func_type func);
int ipa_data_connect(struct gadget_ipa_port *gp, enum ipa_func_type func,
@@ -87,4 +95,6 @@ void *rndis_qc_get_ipa_rx_cb(void);
bool rndis_qc_get_skip_ep_config(void);
void *rndis_qc_get_ipa_tx_cb(void);
void rndis_ipa_reset_trigger(void);
+void gqti_ctrl_update_ipa_pipes(void *gr, enum qti_port_type qport,
+ u32 ipa_prod, u32 ipa_cons);
#endif
diff --git a/drivers/usb/gadget/function/u_rmnet.h b/drivers/usb/gadget/function/u_rmnet.h
index 4336dbf26274..e0843794b594 100644
--- a/drivers/usb/gadget/function/u_rmnet.h
+++ b/drivers/usb/gadget/function/u_rmnet.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,18 +19,19 @@
#include <linux/workqueue.h>
struct rmnet_ctrl_pkt {
- void *buf;
- int len;
+ void *buf;
+ int len;
struct list_head list;
};
-struct grmnet {
- struct usb_function func;
+enum qti_port_type {
+ QTI_PORT_RMNET,
+ QTI_PORT_DPL,
+ QTI_NUM_PORTS
+};
- struct usb_gadget *gadget;
- struct usb_ep *in;
- struct usb_ep *out;
+struct grmnet {
/* to usb host, aka laptop, windows pc etc. Will
* be filled by usb driver of rmnet functionality
*/
@@ -39,18 +40,13 @@ struct grmnet {
/* to modem, and to be filled by driver implementing
* control function
*/
- int (*send_encap_cmd)(u8 port_num, void *buf, size_t len);
-
- void (*notify_modem)(void *g, u8 port_num, int cbits);
+ int (*send_encap_cmd)(enum qti_port_type qport, void *buf, size_t len);
+ void (*notify_modem)(void *g, enum qti_port_type qport, int cbits);
void (*disconnect)(struct grmnet *g);
void (*connect)(struct grmnet *g);
};
-#define NR_QTI_PORTS (NR_RMNET_PORTS + NR_DPL_PORTS)
-#define NR_RMNET_PORTS 4
-#define NR_DPL_PORTS 1
-
enum ctrl_client {
FRMNET_CTRL_CLIENT,
GPS_CTRL_CLIENT,
@@ -58,22 +54,8 @@ enum ctrl_client {
NR_CTRL_CLIENTS
};
-int gbam_setup(unsigned int no_bam_port);
-int gbam2bam_setup(unsigned int no_bam2bam_port);
-void gbam_cleanup(void);
-int gbam_connect(struct grmnet *gr, u8 port_num,
- enum transport_type trans, u8 src_connection_idx,
- u8 dst_connection_idx);
-void gbam_disconnect(struct grmnet *gr, u8 port_num,
- enum transport_type trans);
-void gbam_suspend(struct grmnet *gr, u8 port_num, enum transport_type trans);
-void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans);
-int gbam_mbim_setup(void);
-int gbam_mbim_connect(struct usb_gadget *g, struct usb_ep *in,
- struct usb_ep *out);
-void gbam_mbim_disconnect(void);
-int gsmd_ctrl_connect(struct grmnet *gr, int port_num);
-void gsmd_ctrl_disconnect(struct grmnet *gr, u8 port_num);
-int gsmd_ctrl_setup(enum ctrl_client client_num, unsigned int count,
- u8 *first_port_idx);
+int gqti_ctrl_connect(void *gr, enum qti_port_type qport, unsigned intf);
+void gqti_ctrl_disconnect(void *gr, enum qti_port_type qport);
+int gqti_ctrl_init(void);
+void gqti_ctrl_cleanup(void);
#endif /* __U_RMNET_H*/
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 5a24a1995af9..5a6d7bc3ff78 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -164,6 +164,7 @@ enum mdss_hw_quirk {
MDSS_QUIRK_NEED_SECURE_MAP,
MDSS_QUIRK_SRC_SPLIT_ALWAYS,
MDSS_QUIRK_MMSS_GDSC_COLLAPSE,
+ MDSS_QUIRK_MDP_CLK_SET_RATE,
MDSS_QUIRK_MAX,
};
@@ -289,6 +290,7 @@ struct mdss_data_type {
bool en_svs_high;
u32 max_mdp_clk_rate;
struct mdss_util_intf *mdss_util;
+ unsigned long mdp_clk_rate;
struct platform_device *pdev;
struct dss_io_data mdss_io;
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 840df3741b21..132dc0e028ae 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -45,6 +45,8 @@
#define VDDA_UA_ON_LOAD 100000 /* uA units */
#define VDDA_UA_OFF_LOAD 100 /* uA units */
+#define DP_CRYPTO_CLK_RATE_KHZ 337500
+
struct mdss_dp_attention_node {
u32 vdo;
struct list_head list;
@@ -208,9 +210,9 @@ static int mdss_dp_get_dt_clk_data(struct device *dev,
&ctrl_power_data->clk_config[ctrl_clk_index];
strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
ctrl_clk_index++;
- if (!strcmp(clk_name, "ctrl_link_clk"))
- clk->type = DSS_CLK_PCLK;
- else if (!strcmp(clk_name, "ctrl_pixel_clk"))
+ if (!strcmp(clk_name, "ctrl_link_clk") ||
+ !strcmp(clk_name, "ctrl_pixel_clk") ||
+ !strcmp(clk_name, "ctrl_crypto_clk"))
clk->type = DSS_CLK_PCLK;
else
clk->type = DSS_CLK_AHB;
@@ -1089,6 +1091,23 @@ exit:
return ret;
}
+static void mdss_dp_set_clock_rate(struct mdss_dp_drv_pdata *dp,
+ char *name, u32 rate)
+{
+ u32 num = dp->power_data[DP_CTRL_PM].num_clk;
+ struct dss_clk *cfg = dp->power_data[DP_CTRL_PM].clk_config;
+
+ while (num && strcmp(cfg->clk_name, name)) {
+ num--;
+ cfg++;
+ }
+
+ if (num)
+ cfg->rate = rate;
+ else
+ pr_err("%s clock could not be set with rate %d\n", name, rate);
+}
+
/**
* mdss_dp_enable_mainlink_clocks() - enables Display Port main link clocks
* @dp: Display Port Driver data
@@ -1099,12 +1118,14 @@ static int mdss_dp_enable_mainlink_clocks(struct mdss_dp_drv_pdata *dp)
{
int ret = 0;
- dp->power_data[DP_CTRL_PM].clk_config[0].rate =
- ((dp->link_rate * DP_LINK_RATE_MULTIPLIER) / 1000);/* KHz */
+ mdss_dp_set_clock_rate(dp, "ctrl_link_clk",
+ (dp->link_rate * DP_LINK_RATE_MULTIPLIER) / DP_KHZ_TO_HZ);
+
+ mdss_dp_set_clock_rate(dp, "ctrl_crypto_clk", DP_CRYPTO_CLK_RATE_KHZ);
dp->pixel_rate = dp->panel_data.panel_info.clk_rate;
- dp->power_data[DP_CTRL_PM].clk_config[3].rate =
- (dp->pixel_rate / 1000);/* KHz */
+ mdss_dp_set_clock_rate(dp, "ctrl_pixel_clk",
+ (dp->pixel_rate / DP_KHZ_TO_HZ));
ret = mdss_dp_clk_ctrl(dp, DP_CTRL_PM, true);
if (ret) {
@@ -1286,12 +1307,8 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv)
link_training:
dp_drv->power_on = true;
- if (-EAGAIN == mdss_dp_train_main_link(dp_drv)) {
- mutex_unlock(&dp_drv->train_mutex);
-
- mdss_dp_link_retraining(dp_drv);
- return 0;
- }
+ while (-EAGAIN == mdss_dp_train_main_link(dp_drv))
+ pr_debug("MAIN LINK TRAINING RETRY\n");
dp_drv->cont_splash = 0;
@@ -1622,13 +1639,27 @@ static void mdss_dp_hdcp_cb_work(struct work_struct *work)
struct mdss_dp_drv_pdata *dp;
struct delayed_work *dw = to_delayed_work(work);
struct hdcp_ops *ops;
+ unsigned char *base;
int rc = 0;
+ u32 hdcp_auth_state;
dp = container_of(dw, struct mdss_dp_drv_pdata, hdcp_cb_work);
+ base = dp->base;
+
+ hdcp_auth_state = (dp_read(base + DP_HDCP_STATUS) >> 20) & 0x3;
+
+ pr_debug("hdcp auth state %d\n", hdcp_auth_state);
ops = dp->hdcp.ops;
switch (dp->hdcp_status) {
+ case HDCP_STATE_AUTHENTICATING:
+ pr_debug("start authenticaton\n");
+
+ if (dp->hdcp.ops && dp->hdcp.ops->authenticate)
+ rc = dp->hdcp.ops->authenticate(dp->hdcp.data);
+
+ break;
case HDCP_STATE_AUTHENTICATED:
pr_debug("hdcp authenticated\n");
dp->hdcp.auth_state = true;
@@ -1636,7 +1667,7 @@ static void mdss_dp_hdcp_cb_work(struct work_struct *work)
case HDCP_STATE_AUTH_FAIL:
dp->hdcp.auth_state = false;
- if (dp->power_on) {
+ if (dp->alt_mode.dp_status.hpd_high && dp->power_on) {
pr_debug("Reauthenticating\n");
if (ops && ops->reauthenticate) {
rc = ops->reauthenticate(dp->hdcp.data);
@@ -1664,7 +1695,8 @@ static void mdss_dp_hdcp_cb(void *ptr, enum hdcp_states status)
dp->hdcp_status = status;
- queue_delayed_work(dp->workq, &dp->hdcp_cb_work, HZ/4);
+ if (dp->alt_mode.dp_status.hpd_high)
+ queue_delayed_work(dp->workq, &dp->hdcp_cb_work, HZ/4);
}
static int mdss_dp_hdcp_init(struct mdss_panel_data *pdata)
@@ -1927,20 +1959,28 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
rc = mdss_dp_on(pdata);
break;
case MDSS_EVENT_PANEL_ON:
+ mdss_dp_ack_state(dp, true);
+
mdss_dp_update_hdcp_info(dp);
- if (dp->hdcp.ops && dp->hdcp.ops->authenticate)
- rc = dp->hdcp.ops->authenticate(dp->hdcp.data);
+ if (dp_is_hdcp_enabled(dp)) {
+ cancel_delayed_work(&dp->hdcp_cb_work);
- mdss_dp_ack_state(dp, true);
+ dp->hdcp_status = HDCP_STATE_AUTHENTICATING;
+ queue_delayed_work(dp->workq,
+ &dp->hdcp_cb_work, HZ / 2);
+ }
break;
case MDSS_EVENT_PANEL_OFF:
rc = mdss_dp_off(pdata);
break;
case MDSS_EVENT_BLANK:
- if (dp_is_hdcp_enabled(dp) && dp->hdcp.ops->off) {
- flush_delayed_work(&dp->hdcp_cb_work);
- dp->hdcp.ops->off(dp->hdcp.data);
+ if (dp_is_hdcp_enabled(dp)) {
+ dp->hdcp_status = HDCP_STATE_INACTIVE;
+
+ cancel_delayed_work(&dp->hdcp_cb_work);
+ if (dp->hdcp.ops->off)
+ dp->hdcp.ops->off(dp->hdcp.data);
}
mdss_dp_mainlink_push_idle(pdata);
@@ -2189,9 +2229,6 @@ irqreturn_t dp_isr(int irq, void *ptr)
isr1 &= ~mask1; /* remove masks bit */
- pr_debug("isr=%x mask=%x isr2=%x\n",
- isr1, mask1, isr2);
-
ack = isr1 & EDP_INTR_STATUS1;
ack <<= 1; /* ack bits */
ack |= mask1;
@@ -2601,8 +2638,7 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv)
if (dp_drv->alt_mode.dp_status.hpd_irq) {
pr_debug("Attention: hpd_irq high\n");
- if (dp_drv->power_on && dp_drv->hdcp.ops &&
- dp_drv->hdcp.ops->cp_irq) {
+ if (dp_drv->hdcp.ops && dp_drv->hdcp.ops->cp_irq) {
if (!dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data))
return;
}
@@ -2616,6 +2652,12 @@ static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv)
if (!dp_drv->alt_mode.dp_status.hpd_high) {
pr_debug("Attention: HPD low\n");
+
+ if (dp_is_hdcp_enabled(dp_drv) && dp_drv->hdcp.ops->off) {
+ cancel_delayed_work(&dp_drv->hdcp_cb_work);
+ dp_drv->hdcp.ops->off(dp_drv->hdcp.data);
+ }
+
mdss_dp_update_cable_status(dp_drv, false);
mdss_dp_notify_clients(dp_drv, false);
pr_debug("Attention: Notified clients\n");
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index 04abe9221acc..dc84694f2238 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -228,6 +228,7 @@ struct dp_alt_mode {
#define DP_LINK_RATE_MAX DP_LINK_RATE_540
#define DP_LINK_RATE_MULTIPLIER 27000000
+#define DP_KHZ_TO_HZ 1000
#define DP_MAX_PIXEL_CLK_KHZ 675000
struct downstream_port_config {
/* Byte 02205h */
diff --git a/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c b/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c
index 695331babf55..73b9ad65482f 100644
--- a/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c
+++ b/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c
@@ -23,6 +23,8 @@
#include "mdss_hdcp.h"
#include "mdss_dp_util.h"
+struct dp_hdcp2p2_ctrl;
+
enum dp_hdcp2p2_sink_status {
SINK_DISCONNECTED,
SINK_CONNECTED
@@ -33,9 +35,21 @@ enum dp_auth_status {
DP_HDCP_AUTH_STATUS_SUCCESS
};
+struct dp_hdcp2p2_int_set {
+ u32 interrupt;
+ char *name;
+ void (*func)(struct dp_hdcp2p2_ctrl *ctrl);
+};
+
+struct dp_hdcp2p2_interrupts {
+ u32 reg;
+ struct dp_hdcp2p2_int_set *int_set;
+};
+
struct dp_hdcp2p2_ctrl {
atomic_t auth_state;
enum dp_hdcp2p2_sink_status sink_status; /* Is sink connected */
+ struct dp_hdcp2p2_interrupts *intr;
struct hdcp_init_data init_data;
struct mutex mutex; /* mutex to protect access to ctrl */
struct mutex msg_lock; /* mutex to protect access to msg buffer */
@@ -172,7 +186,10 @@ static int dp_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data)
queue_kthread_work(&ctrl->worker, &ctrl->status);
break;
case HDMI_HDCP_WKUP_CMD_LINK_POLL:
- ctrl->polling = true;
+ if (ctrl->cp_irq_done)
+ queue_kthread_work(&ctrl->worker, &ctrl->recv_msg);
+ else
+ ctrl->polling = true;
break;
case HDMI_HDCP_WKUP_CMD_AUTHENTICATE:
queue_kthread_work(&ctrl->worker, &ctrl->auth);
@@ -211,6 +228,31 @@ static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl)
atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE);
}
+static void dp_hdcp2p2_set_interrupts(struct dp_hdcp2p2_ctrl *ctrl, bool enable)
+{
+ unsigned char *base = ctrl->init_data.core_io->base;
+ struct dp_hdcp2p2_interrupts *intr = ctrl->intr;
+
+ while (intr && intr->reg) {
+ struct dp_hdcp2p2_int_set *int_set = intr->int_set;
+ u32 interrupts = 0;
+
+ while (int_set && int_set->interrupt) {
+ interrupts |= int_set->interrupt;
+ int_set++;
+ }
+
+ if (enable)
+ dp_write(base + intr->reg,
+ dp_read(base + intr->reg) | interrupts);
+ else
+ dp_write(base + intr->reg,
+ dp_read(base + intr->reg) & ~interrupts);
+
+ intr++;
+ }
+}
+
static void dp_hdcp2p2_off(void *input)
{
struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
@@ -221,6 +263,13 @@ static void dp_hdcp2p2_off(void *input)
return;
}
+ if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
+ pr_err("hdcp is off\n");
+ return;
+ }
+
+ dp_hdcp2p2_set_interrupts(ctrl, false);
+
dp_hdcp2p2_reset(ctrl);
flush_kthread_worker(&ctrl->worker);
@@ -237,6 +286,8 @@ static int dp_hdcp2p2_authenticate(void *input)
flush_kthread_worker(&ctrl->worker);
+ dp_hdcp2p2_set_interrupts(ctrl, true);
+
ctrl->sink_status = SINK_CONNECTED;
atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATING);
@@ -317,6 +368,8 @@ static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl)
return;
}
+ dp_hdcp2p2_set_interrupts(ctrl, false);
+
/* notify DP about HDCP failure */
ctrl->init_data.notify_status(ctrl->init_data.cb_data,
HDCP_STATE_AUTH_FAIL);
@@ -640,6 +693,8 @@ static int dp_hdcp2p2_cp_irq(void *input)
goto error;
}
+ pr_debug("sink_rx_status=0x%x\n", ctrl->sink_rx_status);
+
if (!ctrl->sink_rx_status) {
pr_debug("not a hdcp 2.2 irq\n");
rc = -EINVAL;
@@ -653,6 +708,46 @@ error:
return rc;
}
+static int dp_hdcp2p2_isr(void *input)
+{
+ struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
+ int rc = 0;
+ struct dss_io_data *io;
+ struct dp_hdcp2p2_interrupts *intr;
+ u32 hdcp_int_val;
+
+ if (!ctrl || !ctrl->init_data.core_io) {
+ pr_err("invalid input\n");
+ rc = -EINVAL;
+ goto end;
+ }
+
+ io = ctrl->init_data.core_io;
+ intr = ctrl->intr;
+
+ while (intr && intr->reg) {
+ struct dp_hdcp2p2_int_set *int_set = intr->int_set;
+
+ hdcp_int_val = dp_read(io->base + intr->reg);
+
+ while (int_set && int_set->interrupt) {
+ if (hdcp_int_val & (int_set->interrupt >> 2)) {
+ pr_debug("%s\n", int_set->name);
+
+ if (int_set->func)
+ int_set->func(ctrl);
+
+ dp_write(io->base + intr->reg, hdcp_int_val |
+ (int_set->interrupt >> 1));
+ }
+ int_set++;
+ }
+ intr++;
+ }
+end:
+ return rc;
+}
+
void dp_hdcp2p2_deinit(void *input)
{
struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
@@ -684,6 +779,7 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data)
int rc;
struct dp_hdcp2p2_ctrl *ctrl;
static struct hdcp_ops ops = {
+ .isr = dp_hdcp2p2_isr,
.reauthenticate = dp_hdcp2p2_reauthenticate,
.authenticate = dp_hdcp2p2_authenticate,
.feature_supported = dp_hdcp2p2_feature_supported,
@@ -694,7 +790,22 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data)
static struct hdcp_client_ops client_ops = {
.wakeup = dp_hdcp2p2_wakeup,
};
-
+ static struct dp_hdcp2p2_int_set int_set1[] = {
+ {BIT(17), "authentication successful", 0},
+ {BIT(20), "authentication failed", 0},
+ {BIT(24), "encryption enabled", 0},
+ {BIT(27), "encryption disabled", 0},
+ {0},
+ };
+ static struct dp_hdcp2p2_int_set int_set2[] = {
+ {BIT(2), "key fifo underflow", 0},
+ {0},
+ };
+ static struct dp_hdcp2p2_interrupts intr[] = {
+ {DP_INTR_STATUS2, int_set1},
+ {DP_INTR_STATUS3, int_set2},
+ {0}
+ };
static struct hdcp_txmtr_ops txmtr_ops;
struct hdcp_register_data register_data = {0};
@@ -719,6 +830,7 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data)
}
ctrl->sink_status = SINK_DISCONNECTED;
+ ctrl->intr = intr;
atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE);
diff --git a/drivers/video/fbdev/msm/mdss_hdcp_1x.c b/drivers/video/fbdev/msm/mdss_hdcp_1x.c
index cefe368ccc9a..44a3ad993909 100644
--- a/drivers/video/fbdev/msm/mdss_hdcp_1x.c
+++ b/drivers/video/fbdev/msm/mdss_hdcp_1x.c
@@ -10,13 +10,14 @@
* GNU General Public License for more details.
*/
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
#include <linux/io.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/iopoll.h>
-#include <soc/qcom/scm.h>
#include <linux/hdcp_qseecom.h>
#include "mdss_hdcp.h"
#include "mdss_fb.h"
@@ -51,10 +52,6 @@
#define HDCP_POLL_SLEEP_US (20 * 1000)
#define HDCP_POLL_TIMEOUT_US (HDCP_POLL_SLEEP_US * 100)
-#define reg_set_data(x) \
- (hdcp_ctrl->init_data.sec_access ? reg_set->sec_data##x : \
- reg_set->data##x)
-
struct hdcp_sink_addr {
char *name;
u32 addr;
@@ -125,25 +122,15 @@ struct hdcp_reg_set {
u32 aksv_msb;
u32 entropy_ctrl0;
u32 entropy_ctrl1;
- u32 sha_ctrl;
- u32 sha_data;
u32 sec_sha_ctrl;
u32 sec_sha_data;
u32 sha_status;
- u32 data0;
- u32 data1;
u32 data2_0;
u32 data3;
u32 data4;
u32 data5;
u32 data6;
- u32 data7;
- u32 data8;
- u32 data9;
- u32 data10;
- u32 data11;
- u32 data12;
u32 sec_data0;
u32 sec_data1;
@@ -164,16 +151,11 @@ struct hdcp_reg_set {
{HDMI_HDCP_LINK0_STATUS, 28, 24, 20, HDMI_HDCP_CTRL, \
HDMI_HDCP_SW_LOWER_AKSV, HDMI_HDCP_SW_UPPER_AKSV, \
HDMI_HDCP_ENTROPY_CTRL0, HDMI_HDCP_ENTROPY_CTRL1, \
- HDMI_HDCP_SHA_CTRL, HDMI_HDCP_SHA_DATA, \
HDCP_SEC_TZ_HV_HLOS_HDCP_SHA_CTRL, \
HDCP_SEC_TZ_HV_HLOS_HDCP_SHA_DATA, \
- HDMI_HDCP_SHA_STATUS, HDMI_HDCP_RCVPORT_DATA0, \
- HDMI_HDCP_RCVPORT_DATA1, HDMI_HDCP_RCVPORT_DATA2_0, \
+ HDMI_HDCP_SHA_STATUS, HDMI_HDCP_RCVPORT_DATA2_0, \
HDMI_HDCP_RCVPORT_DATA3, HDMI_HDCP_RCVPORT_DATA4, \
HDMI_HDCP_RCVPORT_DATA5, HDMI_HDCP_RCVPORT_DATA6, \
- HDMI_HDCP_RCVPORT_DATA7, HDMI_HDCP_RCVPORT_DATA8, \
- HDMI_HDCP_RCVPORT_DATA9, HDMI_HDCP_RCVPORT_DATA10, \
- HDMI_HDCP_RCVPORT_DATA11, HDMI_HDCP_RCVPORT_DATA12, \
HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA0, \
HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA1, \
HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA7, \
@@ -188,12 +170,11 @@ struct hdcp_reg_set {
{DP_HDCP_STATUS, 16, 14, 13, DP_HDCP_CTRL, \
DP_HDCP_SW_LOWER_AKSV, DP_HDCP_SW_UPPER_AKSV, \
DP_HDCP_ENTROPY_CTRL0, DP_HDCP_ENTROPY_CTRL1, \
- 0, 0, HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_CTRL, \
+ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_CTRL, \
HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_DATA, \
- DP_HDCP_SHA_STATUS, 0, 0, DP_HDCP_RCVPORT_DATA2_0, \
+ DP_HDCP_SHA_STATUS, DP_HDCP_RCVPORT_DATA2_0, \
DP_HDCP_RCVPORT_DATA3, DP_HDCP_RCVPORT_DATA4, \
DP_HDCP_RCVPORT_DATA5, DP_HDCP_RCVPORT_DATA6, \
- 0, 0, 0, 0, 0, 0, \
HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA0, \
HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA1, \
HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA7, \
@@ -233,8 +214,8 @@ struct hdcp_reg_set {
struct hdcp_1x_ctrl {
u32 auth_retries;
u32 tp_msgid;
- u32 tz_hdcp;
bool sink_r0_ready;
+ bool reauth;
enum hdcp_states hdcp_state;
struct HDCP_V2V1_MSG_TOPOLOGY cached_tp;
struct HDCP_V2V1_MSG_TOPOLOGY current_tp;
@@ -280,7 +261,7 @@ static void reset_hdcp_ddc_failures(struct hdcp_1x_ctrl *hdcp_ctrl)
struct dss_io_data *io;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return;
}
@@ -290,8 +271,8 @@ static void reset_hdcp_ddc_failures(struct hdcp_1x_ctrl *hdcp_ctrl)
hdcp_ddc_status = DSS_REG_R(io, HDMI_HDCP_DDC_STATUS);
failure = (hdcp_ddc_status >> 16) & 0x1;
nack0 = (hdcp_ddc_status >> 14) & 0x1;
- DEV_DBG("%s: %s: On Entry: HDCP_DDC_STATUS=0x%x, FAIL=%d, NACK0=%d\n",
- __func__, HDCP_STATE_NAME, hdcp_ddc_status, failure, nack0);
+ pr_debug("%s: On Entry: HDCP_DDC_STATUS=0x%x, FAIL=%d, NACK0=%d\n",
+ HDCP_STATE_NAME, hdcp_ddc_status, failure, nack0);
if (failure == 0x1) {
/*
@@ -301,8 +282,8 @@ static void reset_hdcp_ddc_failures(struct hdcp_1x_ctrl *hdcp_ctrl)
* matches HDCP_DDC_RETRY_CNT.
* Failure occured, let's clear it.
*/
- DEV_DBG("%s: %s: DDC failure detected.HDCP_DDC_STATUS=0x%08x\n",
- __func__, HDCP_STATE_NAME, hdcp_ddc_status);
+ pr_debug("%s: DDC failure detected.HDCP_DDC_STATUS=0x%08x\n",
+ HDCP_STATE_NAME, hdcp_ddc_status);
/* First, Disable DDC */
DSS_REG_W(io, HDMI_HDCP_DDC_CTRL_0, BIT(0));
@@ -316,18 +297,18 @@ static void reset_hdcp_ddc_failures(struct hdcp_1x_ctrl *hdcp_ctrl)
hdcp_ddc_status = DSS_REG_R(io, HDMI_HDCP_DDC_STATUS);
hdcp_ddc_status = (hdcp_ddc_status >> 16) & BIT(0);
if (hdcp_ddc_status == 0x0)
- DEV_DBG("%s: %s: HDCP DDC Failure cleared\n", __func__,
+ pr_debug("%s: HDCP DDC Failure cleared\n",
HDCP_STATE_NAME);
else
- DEV_WARN("%s: %s: Unable to clear HDCP DDC Failure",
- __func__, HDCP_STATE_NAME);
+ pr_debug("%s: Unable to clear HDCP DDC Failure",
+ HDCP_STATE_NAME);
/* Re-Enable HDCP DDC */
DSS_REG_W(io, HDMI_HDCP_DDC_CTRL_0, 0);
}
if (nack0 == 0x1) {
- DEV_DBG("%s: %s: Before: HDMI_DDC_SW_STATUS=0x%08x\n", __func__,
+ pr_debug("%s: Before: HDMI_DDC_SW_STATUS=0x%08x\n",
HDCP_STATE_NAME, DSS_REG_R(io, HDMI_DDC_SW_STATUS));
/* Reset HDMI DDC software status */
DSS_REG_W_ND(io, HDMI_DDC_CTRL,
@@ -342,7 +323,7 @@ static void reset_hdcp_ddc_failures(struct hdcp_1x_ctrl *hdcp_ctrl)
msleep(20);
DSS_REG_W_ND(io, HDMI_DDC_CTRL,
DSS_REG_R(io, HDMI_DDC_CTRL) & ~BIT(1));
- DEV_DBG("%s: %s: After: HDMI_DDC_SW_STATUS=0x%08x\n", __func__,
+ pr_debug("%s: After: HDMI_DDC_SW_STATUS=0x%08x\n",
HDCP_STATE_NAME, DSS_REG_R(io, HDMI_DDC_SW_STATUS));
}
@@ -350,8 +331,8 @@ static void reset_hdcp_ddc_failures(struct hdcp_1x_ctrl *hdcp_ctrl)
failure = (hdcp_ddc_status >> 16) & BIT(0);
nack0 = (hdcp_ddc_status >> 14) & BIT(0);
- DEV_DBG("%s: %s: On Exit: HDCP_DDC_STATUS=0x%x, FAIL=%d, NACK0=%d\n",
- __func__, HDCP_STATE_NAME, hdcp_ddc_status, failure, nack0);
+ pr_debug("%s: On Exit: HDCP_DDC_STATUS=0x%x, FAIL=%d, NACK0=%d\n",
+ HDCP_STATE_NAME, hdcp_ddc_status, failure, nack0);
} /* reset_hdcp_ddc_failures */
static void hdcp_1x_hw_ddc_clean(struct hdcp_1x_ctrl *hdcp_ctrl)
@@ -364,14 +345,14 @@ static void hdcp_1x_hw_ddc_clean(struct hdcp_1x_ctrl *hdcp_ctrl)
u32 timeout_count;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return;
}
io = hdcp_ctrl->init_data.core_io;
if (!io->base) {
- DEV_ERR("%s: core io not inititalized\n", __func__);
- return;
+ pr_err("core io not inititalized\n");
+ return;
}
/* Wait to be clean on DDC HW engine */
@@ -393,49 +374,16 @@ static void hdcp_1x_hw_ddc_clean(struct hdcp_1x_ctrl *hdcp_ctrl)
ddc_hw_not_ready = xfer_not_done || hw_not_done;
- DEV_DBG("%s: %s: timeout count(%d): ddc hw%sready\n",
- __func__, HDCP_STATE_NAME, timeout_count,
+ pr_debug("%s: timeout count(%d): ddc hw%sready\n",
+ HDCP_STATE_NAME, timeout_count,
ddc_hw_not_ready ? " not " : " ");
- DEV_DBG("hdcp_ddc_status[0x%x], ddc_hw_status[0x%x]\n",
+ pr_debug("hdcp_ddc_status[0x%x], ddc_hw_status[0x%x]\n",
hdcp_ddc_status, ddc_hw_status);
if (ddc_hw_not_ready)
msleep(20);
} while (ddc_hw_not_ready && --timeout_count);
} /* hdcp_1x_hw_ddc_clean */
-static int hdcp_scm_call(struct scm_hdcp_req *req, u32 *resp)
-{
- int ret = 0;
-
- if (!is_scm_armv8()) {
- ret = scm_call(SCM_SVC_HDCP, SCM_CMD_HDCP, (void *) req,
- SCM_HDCP_MAX_REG * sizeof(struct scm_hdcp_req),
- &resp, sizeof(*resp));
- } else {
- struct scm_desc desc;
-
- desc.args[0] = req[0].addr;
- desc.args[1] = req[0].val;
- desc.args[2] = req[1].addr;
- desc.args[3] = req[1].val;
- desc.args[4] = req[2].addr;
- desc.args[5] = req[2].val;
- desc.args[6] = req[3].addr;
- desc.args[7] = req[3].val;
- desc.args[8] = req[4].addr;
- desc.args[9] = req[4].val;
- desc.arginfo = SCM_ARGS(10);
-
- ret = scm_call2(SCM_SIP_FNID(SCM_SVC_HDCP, SCM_CMD_HDCP),
- &desc);
- *resp = desc.ret[0];
- if (ret)
- return ret;
- }
-
- return ret;
-}
-
static int hdcp_1x_load_keys(void *input)
{
int rc = 0;
@@ -451,14 +399,14 @@ static int hdcp_1x_load_keys(void *input)
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io ||
!hdcp_ctrl->init_data.qfprom_io) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
rc = -EINVAL;
goto end;
}
if ((HDCP_STATE_INACTIVE != hdcp_ctrl->hdcp_state) &&
(HDCP_STATE_AUTH_FAIL != hdcp_ctrl->hdcp_state)) {
- DEV_ERR("%s: %s: invalid state. returning\n", __func__,
+ pr_err("%s: invalid state. returning\n",
HDCP_STATE_NAME);
rc = -EINVAL;
goto end;
@@ -481,7 +429,7 @@ static int hdcp_1x_load_keys(void *input)
if (use_sw_keys) {
if (hdcp1_set_keys(&aksv_msb, &aksv_lsb)) {
- pr_err("%s: setting hdcp SW keys failed\n", __func__);
+ pr_err("setting hdcp SW keys failed\n");
rc = -EINVAL;
goto end;
}
@@ -499,7 +447,7 @@ static int hdcp_1x_load_keys(void *input)
aksv_msb = DSS_REG_R(qfprom_io, ksv_msb_addr);
}
- DEV_DBG("%s: %s: AKSV=%02x%08x\n", __func__, HDCP_STATE_NAME,
+ pr_debug("%s: AKSV=%02x%08x\n", HDCP_STATE_NAME,
aksv_msb, aksv_lsb);
aksv[0] = aksv_lsb & 0xFF;
@@ -510,7 +458,7 @@ static int hdcp_1x_load_keys(void *input)
/* check there are 20 ones in AKSV */
if (hdcp_1x_count_one(aksv, 5) != 20) {
- DEV_ERR("%s: AKSV bit count failed\n", __func__);
+ pr_err("AKSV bit count failed\n");
rc = -EINVAL;
goto end;
}
@@ -558,7 +506,7 @@ static int hdcp_1x_read(struct hdcp_1x_ctrl *hdcp_ctrl,
rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
if (rc)
- DEV_ERR("%s: %s: %s read failed\n", __func__,
+ pr_err("%s: %s read failed\n",
HDCP_STATE_NAME, sink->name);
} else if (IS_ENABLED(CONFIG_FB_MSM_MDSS_DP_PANEL) &&
hdcp_ctrl->init_data.client_id == HDCP_CLIENT_DP) {
@@ -609,7 +557,7 @@ static int hdcp_1x_write(struct hdcp_1x_ctrl *hdcp_ctrl,
rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl);
if (rc)
- DEV_ERR("%s: %s: %s write failed\n", __func__,
+ pr_err("%s: %s write failed\n",
HDCP_STATE_NAME, sink->name);
} else if (IS_ENABLED(CONFIG_FB_MSM_MDSS_DP_PANEL) &&
hdcp_ctrl->init_data.client_id == HDCP_CLIENT_DP) {
@@ -621,7 +569,7 @@ static int hdcp_1x_write(struct hdcp_1x_ctrl *hdcp_ctrl,
rc = dp_aux_write(hdcp_ctrl->init_data.cb_data, &cmd);
if (rc)
- DEV_ERR("%s: %s: %s read failed\n", __func__,
+ pr_err("%s: %s read failed\n",
HDCP_STATE_NAME, sink->name);
}
@@ -661,14 +609,11 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl)
u8 bcaps = 0;
u32 link0_status = 0;
u8 buf[0xFF];
- struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG];
u32 phy_addr;
- u32 ret = 0;
- u32 resp = 0;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io ||
!hdcp_ctrl->init_data.qfprom_io) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
rc = -EINVAL;
goto error;
}
@@ -680,7 +625,7 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl)
reg_set = &hdcp_ctrl->reg_set;
if (HDCP_STATE_AUTHENTICATING != hdcp_ctrl->hdcp_state) {
- DEV_ERR("%s: %s: invalid state. returning\n", __func__,
+ pr_err("%s: invalid state. returning\n",
HDCP_STATE_NAME);
rc = -EINVAL;
goto error;
@@ -689,7 +634,7 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl)
rc = hdcp_1x_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.bcaps,
&bcaps, false);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: error reading bcaps\n", __func__);
+ pr_err("error reading bcaps\n");
goto error;
}
@@ -699,24 +644,7 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl)
DS_REPEATER : DS_RECEIVER;
/* Write BCAPS to the hardware */
- if (hdcp_ctrl->tz_hdcp) {
- memset(scm_buf, 0x00, sizeof(scm_buf));
-
- scm_buf[0].addr = phy_addr + reg_set->data12;
- scm_buf[0].val = bcaps;
-
- ret = hdcp_scm_call(scm_buf, &resp);
- if (ret || resp) {
- DEV_ERR("%s: error: scm_call ret = %d, resp = %d\n",
- __func__, ret, resp);
- rc = -EINVAL;
- goto error;
- }
- } else if (hdcp_ctrl->init_data.sec_access) {
- DSS_REG_W(hdcp_io, reg_set->sec_data12, bcaps);
- } else {
- DSS_REG_W(io, reg_set->data12, bcaps);
- }
+ DSS_REG_W(hdcp_io, reg_set->sec_data12, bcaps);
/* Wait for HDCP keys to be checked and validated */
rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
@@ -724,7 +652,7 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl)
== HDCP_KEYS_STATE_VALID,
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: key not ready\n", __func__);
+ pr_err("key not ready\n");
goto error;
}
@@ -739,7 +667,7 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl)
(link0_status & (BIT(8) | BIT(9))),
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: An not ready\n", __func__);
+ pr_err("An not ready\n");
goto error;
}
@@ -784,16 +712,16 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl)
rc = hdcp_1x_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.bksv, bksv, false);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: error reading bksv from sink\n", __func__);
+ pr_err("error reading bksv from sink\n");
goto error;
}
/* check there are 20 ones in BKSV */
if (hdcp_1x_count_one(bksv, 5) != 20) {
- DEV_ERR("%s: %s: BKSV doesn't have 20 1's and 20 0's\n",
- __func__, HDCP_STATE_NAME);
- DEV_ERR("%s: %s: BKSV chk fail. BKSV=%02x%02x%02x%02x%02x\n",
- __func__, HDCP_STATE_NAME, bksv[4], bksv[3], bksv[2],
+ pr_err("%s: BKSV doesn't have 20 1's and 20 0's\n",
+ HDCP_STATE_NAME);
+ pr_err("%s: BKSV chk fail. BKSV=%02x%02x%02x%02x%02x\n",
+ HDCP_STATE_NAME, bksv[4], bksv[3], bksv[2],
bksv[1], bksv[0]);
rc = -EINVAL;
goto error;
@@ -804,51 +732,30 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl)
link0_bksv_0 = (link0_bksv_0 << 8) | bksv[1];
link0_bksv_0 = (link0_bksv_0 << 8) | bksv[0];
link0_bksv_1 = bksv[4];
- DEV_DBG("%s: %s: BKSV=%02x%08x\n", __func__, HDCP_STATE_NAME,
+ pr_debug("%s: BKSV=%02x%08x\n", HDCP_STATE_NAME,
link0_bksv_1, link0_bksv_0);
- if (hdcp_ctrl->tz_hdcp) {
- memset(scm_buf, 0x00, sizeof(scm_buf));
-
- scm_buf[0].addr = phy_addr + reg_set->data0;
- scm_buf[0].val = link0_bksv_0;
- scm_buf[1].addr = phy_addr + reg_set->data1;
- scm_buf[1].val = link0_bksv_1;
-
- ret = hdcp_scm_call(scm_buf, &resp);
-
- if (ret || resp) {
- DEV_ERR("%s: error: scm_call ret = %d, resp = %d\n",
- __func__, ret, resp);
- rc = -EINVAL;
- goto error;
- }
- } else if (hdcp_ctrl->init_data.sec_access) {
- DSS_REG_W(hdcp_io, reg_set->sec_data0, link0_bksv_0);
- DSS_REG_W(hdcp_io, reg_set->sec_data1, link0_bksv_1);
- } else {
- DSS_REG_W(io, reg_set->data0, link0_bksv_0);
- DSS_REG_W(io, reg_set->data1, link0_bksv_1);
- }
+ DSS_REG_W(hdcp_io, reg_set->sec_data0, link0_bksv_0);
+ DSS_REG_W(hdcp_io, reg_set->sec_data1, link0_bksv_1);
/* Wait for HDCP R0 computation to be completed */
rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
link0_status & BIT(reg_set->r0_offset),
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: R0 not ready\n", __func__);
+ pr_err("R0 not ready\n");
goto error;
}
rc = hdcp_1x_write(hdcp_ctrl, &hdcp_ctrl->sink_addr.an, an);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: error writing an to sink\n", __func__);
+ pr_err("error writing an to sink\n");
goto error;
}
rc = hdcp_1x_write(hdcp_ctrl, &hdcp_ctrl->sink_addr.aksv, aksv);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: error writing aksv to sink\n", __func__);
+ pr_err("error writing aksv to sink\n");
goto error;
}
@@ -864,8 +771,8 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl)
timeout_count = wait_for_completion_timeout(
&hdcp_ctrl->sink_r0_available, HZ / 2);
- if (!timeout_count) {
- DEV_ERR("sink R0 not ready\n");
+ if (!timeout_count || hdcp_ctrl->reauth) {
+ pr_err("sink R0 not ready\n");
rc = -EINVAL;
goto error;
}
@@ -875,11 +782,11 @@ r0_read_retry:
memset(buf, 0, sizeof(buf));
rc = hdcp_1x_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.r0, buf, false);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: error reading R0' from sink\n", __func__);
+ pr_err("error reading R0' from sink\n");
goto error;
}
- DEV_DBG("%s: %s: R0'=%02x%02x\n", __func__, HDCP_STATE_NAME,
+ pr_debug("%s: R0'=%02x%02x\n", HDCP_STATE_NAME,
buf[1], buf[0]);
/* Write R0' to HDCP registers and check to see if it is a match */
@@ -888,7 +795,7 @@ r0_read_retry:
link0_status & BIT(12),
r0_read_delay_us, r0_read_timeout_us);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: R0 mismatch\n", __func__);
+ pr_err("R0 mismatch\n");
if (--r0_retry)
goto r0_read_retry;
@@ -897,13 +804,13 @@ r0_read_retry:
hdcp1_set_enc(true);
- DEV_INFO("%s: %s: Authentication Part I successful\n", __func__,
+ pr_debug("%s: Authentication Part I successful\n",
hdcp_ctrl ? HDCP_STATE_NAME : "???");
return 0;
error:
- DEV_ERR("%s: %s: Authentication Part I failed\n", __func__,
+ pr_err("%s: Authentication Part I failed\n",
hdcp_ctrl ? HDCP_STATE_NAME : "???");
return rc;
@@ -915,20 +822,16 @@ static int hdcp_1x_set_v_h(struct hdcp_1x_ctrl *hdcp_ctrl,
int rc;
struct dss_io_data *io;
- if (!hdcp_ctrl->tz_hdcp && hdcp_ctrl->init_data.sec_access)
- io = hdcp_ctrl->init_data.hdcp_io;
- else
- io = hdcp_ctrl->init_data.core_io;
+ io = hdcp_ctrl->init_data.hdcp_io;
rc = hdcp_1x_read(hdcp_ctrl, rd->sink, buf, false);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: error reading %s\n", __func__, rd->sink->name);
+ pr_err("error reading %s\n", rd->sink->name);
goto end;
}
- if (!hdcp_ctrl->tz_hdcp)
- DSS_REG_W(io, rd->reg_id,
- (buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]));
+ DSS_REG_W(io, rd->reg_id,
+ (buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]));
end:
return rc;
}
@@ -937,46 +840,27 @@ static int hdcp_1x_transfer_v_h(struct hdcp_1x_ctrl *hdcp_ctrl)
{
int rc = 0;
u8 buf[4];
- struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG];
u32 phy_addr;
struct hdcp_reg_set *reg_set = &hdcp_ctrl->reg_set;
struct hdcp_1x_reg_data reg_data[] = {
- {reg_set_data(7), &hdcp_ctrl->sink_addr.v_h0},
- {reg_set_data(8), &hdcp_ctrl->sink_addr.v_h1},
- {reg_set_data(9), &hdcp_ctrl->sink_addr.v_h2},
- {reg_set_data(10), &hdcp_ctrl->sink_addr.v_h3},
- {reg_set_data(11), &hdcp_ctrl->sink_addr.v_h4},
+ {reg_set->sec_data7, &hdcp_ctrl->sink_addr.v_h0},
+ {reg_set->sec_data8, &hdcp_ctrl->sink_addr.v_h1},
+ {reg_set->sec_data9, &hdcp_ctrl->sink_addr.v_h2},
+ {reg_set->sec_data10, &hdcp_ctrl->sink_addr.v_h3},
+ {reg_set->sec_data11, &hdcp_ctrl->sink_addr.v_h4},
};
u32 size = ARRAY_SIZE(reg_data);
- u32 iter = 0, ret = 0, resp = 0;
+ u32 iter = 0;
phy_addr = hdcp_ctrl->init_data.phy_addr;
- memset(scm_buf, 0x00, sizeof(scm_buf));
-
for (iter = 0; iter < size; iter++) {
struct hdcp_1x_reg_data *rd = reg_data + iter;
memset(buf, 0, sizeof(buf));
hdcp_1x_set_v_h(hdcp_ctrl, rd, buf);
-
- if (hdcp_ctrl->tz_hdcp) {
- u32 reg_val = buf[3] << 24 | buf[2] << 16 |
- buf[1] << 8 | buf[0];
-
- scm_buf[iter].addr = phy_addr + reg_data[iter].reg_id;
- scm_buf[iter].val = reg_val;
-
- ret = hdcp_scm_call(scm_buf, &resp);
- if (ret || resp) {
- DEV_ERR("%s: scm err: ret=%d, resp=%d\n",
- __func__, ret, resp);
- rc = -EINVAL;
- goto error;
- }
- }
}
-error:
+
return rc;
}
@@ -993,15 +877,12 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x_ctrl *hdcp_ctrl)
u32 ksv_bytes;
struct dss_io_data *io;
struct hdcp_reg_set *reg_set;
- struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG];
u32 phy_addr;
- u32 ret = 0;
- u32 resp = 0;
u32 ksv_read_retry = 20;
int v_retry = 3;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
rc = -EINVAL;
goto error;
}
@@ -1010,7 +891,7 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x_ctrl *hdcp_ctrl)
reg_set = &hdcp_ctrl->reg_set;
if (HDCP_STATE_AUTHENTICATING != hdcp_ctrl->hdcp_state) {
- DEV_DBG("%s: %s: invalid state. returning\n", __func__,
+ pr_debug("%s: invalid state. returning\n",
HDCP_STATE_NAME);
rc = -EINVAL;
goto error;
@@ -1029,7 +910,7 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x_ctrl *hdcp_ctrl)
*/
rc = hdcp_1x_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.bcaps, &bcaps, true);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: error reading bcaps\n", __func__);
+ pr_err("error reading bcaps\n");
goto error;
}
@@ -1040,7 +921,7 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x_ctrl *hdcp_ctrl)
rc = hdcp_1x_read(hdcp_ctrl,
&hdcp_ctrl->sink_addr.bcaps, &bcaps, true);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: error reading bcaps\n", __func__);
+ pr_err("error reading bcaps\n");
goto error;
}
msleep(100);
@@ -1050,8 +931,8 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x_ctrl *hdcp_ctrl)
timeout_count = wait_for_completion_timeout(
&hdcp_ctrl->sink_rep_ready, HZ * 5);
- if (!timeout_count) {
- DEV_ERR("sink not ready with DS KSV list\n");
+ if (!timeout_count || hdcp_ctrl->reauth) {
+ pr_err("sink not ready with DS KSV list\n");
rc = -EINVAL;
goto error;
}
@@ -1060,42 +941,20 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x_ctrl *hdcp_ctrl)
rc = hdcp_1x_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.bstatus,
buf, true);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: error reading bstatus\n", __func__);
+ pr_err("error reading bstatus\n");
goto error;
}
bstatus = buf[1];
bstatus = (bstatus << 8) | buf[0];
- if (hdcp_ctrl->tz_hdcp) {
- memset(scm_buf, 0x00, sizeof(scm_buf));
-
- /* Write BSTATUS and BCAPS to HDCP registers */
- scm_buf[0].addr = phy_addr + reg_set->data12;
- scm_buf[0].val = bcaps | (bstatus << 8);
-
- ret = hdcp_scm_call(scm_buf, &resp);
- if (ret || resp) {
- DEV_ERR("%s: error: scm_call ret = %d, resp = %d\n",
- __func__, ret, resp);
- rc = -EINVAL;
- goto error;
- }
- } else if (hdcp_ctrl->init_data.sec_access) {
- DSS_REG_W(hdcp_ctrl->init_data.hdcp_io,
- reg_set->sec_data12,
- bcaps | (bstatus << 8));
- } else {
- DSS_REG_W(io, reg_set->data12, bcaps | (bstatus << 8));
- }
-
down_stream_devices = bstatus & 0x7F;
- DEV_DBG("%s: DEVICE_COUNT %d\n", __func__, down_stream_devices);
+ pr_debug("DEVICE_COUNT %d\n", down_stream_devices);
/* Cascaded repeater depth */
repeater_cascade_depth = (bstatus >> 8) & 0x7;
- DEV_DBG("%s: DEPTH %d\n", __func__, repeater_cascade_depth);
+ pr_debug("DEPTH %d\n", repeater_cascade_depth);
/*
* HDCP Compliance 1B-05:
@@ -1103,10 +962,10 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x_ctrl *hdcp_ctrl)
* exceed max_devices_connected from bit 7 of Bstatus.
*/
max_devs_exceeded = (bstatus & BIT(7)) >> 7;
- DEV_DBG("%s: MAX_DEVS_EXCEEDED %d\n", __func__, max_devs_exceeded);
+ pr_debug("MAX_DEVS_EXCEEDED %d\n", max_devs_exceeded);
if (max_devs_exceeded == 0x01) {
- DEV_ERR("%s: %s: no. of devs connected exceeds max allowed",
- __func__, HDCP_STATE_NAME);
+ pr_err("%s: no. of devs connected exceeds max allowed",
+ HDCP_STATE_NAME);
rc = -EINVAL;
goto error;
}
@@ -1117,11 +976,11 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x_ctrl *hdcp_ctrl)
* exceed max_cascade_connected from bit 11 of Bstatus.
*/
max_cascade_exceeded = (bstatus & BIT(11)) >> 11;
- DEV_DBG("%s: MAX CASCADE_EXCEEDED %d\n", __func__,
+ pr_debug("MAX CASCADE_EXCEEDED %d\n",
max_cascade_exceeded);
if (max_cascade_exceeded == 0x01) {
- DEV_ERR("%s: %s: no. of cascade conn exceeds max allowed",
- __func__, HDCP_STATE_NAME);
+ pr_err("%s: no. of cascade conn exceeds max allowed",
+ HDCP_STATE_NAME);
rc = -EINVAL;
goto error;
}
@@ -1142,8 +1001,8 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x_ctrl *hdcp_ctrl)
rc = hdcp_1x_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.ksv_fifo,
ksv_fifo, false);
if (IS_ERR_VALUE(rc)) {
- DEV_DBG("%s: could not read ksv fifo (%d)\n",
- __func__, ksv_read_retry);
+ pr_debug("could not read ksv fifo (%d)\n",
+ ksv_read_retry);
/*
* HDCP Compliace Test case 1B-01:
* Wait here until all the ksv bytes have been
@@ -1156,9 +1015,12 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x_ctrl *hdcp_ctrl)
}
if (rc) {
- DEV_ERR("%s: error reading ksv_fifo\n", __func__);
+ pr_err("error reading ksv_fifo\n");
goto error;
}
+
+ DSS_REG_W(hdcp_ctrl->init_data.hdcp_io,
+ reg_set->sec_data12, bcaps | (bstatus << 8));
v_read_retry:
rc = hdcp_1x_transfer_v_h(hdcp_ctrl);
if (rc)
@@ -1176,55 +1038,15 @@ v_read_retry:
/* First, reset SHA engine */
/* Next, enable SHA engine, SEL=DIGA_HDCP */
- if (hdcp_ctrl->tz_hdcp) {
- memset(scm_buf, 0x00, sizeof(scm_buf));
-
- scm_buf[0].addr = phy_addr + reg_set->sha_ctrl;
- scm_buf[0].val = HDCP_REG_ENABLE;
- scm_buf[1].addr = phy_addr + reg_set->sha_ctrl;
- scm_buf[1].val = HDCP_REG_DISABLE;
-
- ret = hdcp_scm_call(scm_buf, &resp);
- if (ret || resp) {
- DEV_ERR("%s: error: scm_call ret = %d, resp = %d\n",
- __func__, ret, resp);
- rc = -EINVAL;
- goto error;
- }
- } else if (hdcp_ctrl->init_data.sec_access) {
- DSS_REG_W(hdcp_ctrl->init_data.hdcp_io,
- reg_set->sec_sha_ctrl,
- HDCP_REG_ENABLE);
- DSS_REG_W(hdcp_ctrl->init_data.hdcp_io,
- reg_set->sec_sha_ctrl,
- HDCP_REG_DISABLE);
- } else {
- DSS_REG_W(io, reg_set->sha_ctrl, HDCP_REG_ENABLE);
- DSS_REG_W(io, reg_set->sha_ctrl, HDCP_REG_DISABLE);
- }
+ DSS_REG_W(hdcp_ctrl->init_data.hdcp_io,
+ reg_set->sec_sha_ctrl, HDCP_REG_ENABLE);
+ DSS_REG_W(hdcp_ctrl->init_data.hdcp_io,
+ reg_set->sec_sha_ctrl, HDCP_REG_DISABLE);
for (i = 0; i < ksv_bytes - 1; i++) {
/* Write KSV byte and do not set DONE bit[0] */
- if (hdcp_ctrl->tz_hdcp) {
- memset(scm_buf, 0x00, sizeof(scm_buf));
-
- scm_buf[0].addr = phy_addr + reg_set->sha_data;
- scm_buf[0].val = ksv_fifo[i] << 16;
-
- ret = hdcp_scm_call(scm_buf, &resp);
- if (ret || resp) {
- DEV_ERR("%s: scm_call ret = %d, resp = %d\n",
- __func__, ret, resp);
- rc = -EINVAL;
- goto error;
- }
- } else if (hdcp_ctrl->init_data.sec_access) {
- DSS_REG_W_ND(hdcp_ctrl->init_data.hdcp_io,
- reg_set->sec_sha_data,
- ksv_fifo[i] << 16);
- } else {
- DSS_REG_W_ND(io, reg_set->sha_data, ksv_fifo[i] << 16);
- }
+ DSS_REG_W_ND(hdcp_ctrl->init_data.hdcp_io,
+ reg_set->sec_sha_data, ksv_fifo[i] << 16);
/*
* Once 64 bytes have been written, we need to poll for
@@ -1236,41 +1058,22 @@ v_read_retry:
HDCP_POLL_SLEEP_US,
HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: block not done\n", __func__);
+ pr_err("block not done\n");
goto error;
}
}
}
/* Write l to DONE bit[0] */
- if (hdcp_ctrl->tz_hdcp) {
- memset(scm_buf, 0x00, sizeof(scm_buf));
-
- scm_buf[0].addr = phy_addr + reg_set->sha_data;
- scm_buf[0].val = (ksv_fifo[ksv_bytes - 1] << 16) | 0x1;
-
- ret = hdcp_scm_call(scm_buf, &resp);
- if (ret || resp) {
- DEV_ERR("%s: error: scm_call ret = %d, resp = %d\n",
- __func__, ret, resp);
- rc = -EINVAL;
- goto error;
- }
- } else if (hdcp_ctrl->init_data.sec_access) {
- DSS_REG_W_ND(hdcp_ctrl->init_data.hdcp_io,
- reg_set->sec_sha_data,
- (ksv_fifo[ksv_bytes - 1] << 16) | 0x1);
- } else {
- DSS_REG_W_ND(io, reg_set->sha_data,
- (ksv_fifo[ksv_bytes - 1] << 16) | 0x1);
- }
+ DSS_REG_W_ND(hdcp_ctrl->init_data.hdcp_io,
+ reg_set->sec_sha_data, (ksv_fifo[ksv_bytes - 1] << 16) | 0x1);
/* Now wait for HDCP_SHA_COMP_DONE */
rc = readl_poll_timeout(io->base + reg_set->sha_status, sha_status,
sha_status & BIT(4),
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: V computation not done\n", __func__);
+ pr_err("V computation not done\n");
goto error;
}
@@ -1279,21 +1082,20 @@ v_read_retry:
status & BIT(reg_set->v_offset),
HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
if (IS_ERR_VALUE(rc)) {
- DEV_ERR("%s: V mismatch\n", __func__);
+ pr_err("V mismatch\n");
if (--v_retry)
goto v_read_retry;
}
error:
if (rc)
- DEV_ERR("%s: %s: Authentication Part II failed\n", __func__,
+ pr_err("%s: Authentication Part II failed\n",
hdcp_ctrl ? HDCP_STATE_NAME : "???");
else
- DEV_INFO("%s: %s: Authentication Part II successful\n",
- __func__, HDCP_STATE_NAME);
+ pr_debug("%s: Authentication Part II successful\n",
+ HDCP_STATE_NAME);
if (!hdcp_ctrl) {
- DEV_ERR("%s: hdcp_ctrl null. Topology not updated\n",
- __func__);
+ pr_err("hdcp_ctrl null. Topology not updated\n");
return rc;
}
/* Update topology information */
@@ -1308,7 +1110,7 @@ error:
static void hdcp_1x_cache_topology(struct hdcp_1x_ctrl *hdcp_ctrl)
{
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return;
}
@@ -1331,7 +1133,7 @@ static void hdcp_1x_notify_topology(struct hdcp_1x_ctrl *hdcp_ctrl)
snprintf(envp[2], 16, "%d", (int)HDCP_V1_TX);
kobject_uevent_env(hdcp_ctrl->init_data.sysfs_kobj, KOBJ_CHANGE, envp);
- DEV_DBG("%s Event Sent: %s msgID = %s srcID = %s\n", __func__,
+ pr_debug("Event Sent: %s msgID = %s srcID = %s\n",
envp[0], envp[1], envp[2]);
}
@@ -1341,7 +1143,7 @@ static void hdcp_1x_int_work(struct work_struct *work)
struct hdcp_1x_ctrl, hdcp_int_work);
if (!hdcp_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return;
}
@@ -1368,17 +1170,18 @@ static void hdcp_1x_auth_work(struct work_struct *work)
struct dss_io_data *io;
if (!hdcp_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return;
}
if (HDCP_STATE_AUTHENTICATING != hdcp_ctrl->hdcp_state) {
- DEV_DBG("%s: %s: invalid state. returning\n", __func__,
+ pr_debug("%s: invalid state. returning\n",
HDCP_STATE_NAME);
return;
}
hdcp_ctrl->sink_r0_ready = false;
+ hdcp_ctrl->reauth = false;
io = hdcp_ctrl->init_data.core_io;
/* Enabling Software DDC for HDMI and REF timer for DP */
@@ -1390,7 +1193,7 @@ static void hdcp_1x_auth_work(struct work_struct *work)
rc = hdcp_1x_authentication_part1(hdcp_ctrl);
if (rc) {
- DEV_DBG("%s: %s: HDCP Auth Part I failed\n", __func__,
+ pr_debug("%s: HDCP Auth Part I failed\n",
HDCP_STATE_NAME);
goto error;
}
@@ -1398,12 +1201,12 @@ static void hdcp_1x_auth_work(struct work_struct *work)
if (hdcp_ctrl->current_tp.ds_type == DS_REPEATER) {
rc = hdcp_1x_authentication_part2(hdcp_ctrl);
if (rc) {
- DEV_DBG("%s: %s: HDCP Auth Part II failed\n", __func__,
+ pr_debug("%s: HDCP Auth Part II failed\n",
HDCP_STATE_NAME);
goto error;
}
} else {
- DEV_INFO("%s: Downstream device is not a repeater\n", __func__);
+ pr_debug("Downstream device is not a repeater\n");
}
/* Disabling software DDC before going into part3 to make sure
* there is no Arbitration between software and hardware for DDC */
@@ -1431,16 +1234,16 @@ error:
mutex_unlock(hdcp_ctrl->init_data.mutex);
/* Notify HDMI Tx controller of the result */
- DEV_DBG("%s: %s: Notifying HDMI Tx of auth result\n",
- __func__, HDCP_STATE_NAME);
+ pr_debug("%s: Notifying HDMI Tx of auth result\n",
+ HDCP_STATE_NAME);
if (hdcp_ctrl->init_data.notify_status) {
hdcp_ctrl->init_data.notify_status(
hdcp_ctrl->init_data.cb_data,
hdcp_ctrl->hdcp_state);
}
} else {
- DEV_DBG("%s: %s: HDCP state changed during authentication\n",
- __func__, HDCP_STATE_NAME);
+ pr_debug("%s: HDCP state changed during authentication\n",
+ HDCP_STATE_NAME);
mutex_unlock(hdcp_ctrl->init_data.mutex);
}
return;
@@ -1451,17 +1254,17 @@ int hdcp_1x_authenticate(void *input)
struct hdcp_1x_ctrl *hdcp_ctrl = (struct hdcp_1x_ctrl *)input;
if (!hdcp_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return -EINVAL;
}
if (HDCP_STATE_INACTIVE != hdcp_ctrl->hdcp_state) {
- DEV_DBG("%s: %s: already active or activating. returning\n",
- __func__, HDCP_STATE_NAME);
+ pr_debug("%s: already active or activating. returning\n",
+ HDCP_STATE_NAME);
return 0;
}
- DEV_DBG("%s: %s: Queuing work to start HDCP authentication", __func__,
+ pr_debug("%s: Queuing work to start HDCP authentication",
HDCP_STATE_NAME);
if (!hdcp_1x_load_keys(input)) {
@@ -1489,7 +1292,7 @@ int hdcp_1x_reauthenticate(void *input)
u32 ret = 0, reg;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return -EINVAL;
}
@@ -1498,7 +1301,7 @@ int hdcp_1x_reauthenticate(void *input)
isr = &hdcp_ctrl->int_set;
if (HDCP_STATE_AUTH_FAIL != hdcp_ctrl->hdcp_state) {
- DEV_DBG("%s: %s: invalid state. returning\n", __func__,
+ pr_debug("%s: invalid state. returning\n",
HDCP_STATE_NAME);
return 0;
}
@@ -1545,7 +1348,7 @@ void hdcp_1x_off(void *input)
u32 reg;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return;
}
@@ -1554,7 +1357,7 @@ void hdcp_1x_off(void *input)
isr = &hdcp_ctrl->int_set;
if (HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) {
- DEV_DBG("%s: %s: inactive. returning\n", __func__,
+ pr_debug("%s: inactive. returning\n",
HDCP_STATE_NAME);
return;
}
@@ -1581,11 +1384,11 @@ void hdcp_1x_off(void *input)
*/
rc = cancel_delayed_work(&hdcp_ctrl->hdcp_auth_work);
if (rc)
- DEV_DBG("%s: %s: Deleted hdcp auth work\n", __func__,
+ pr_debug("%s: Deleted hdcp auth work\n",
HDCP_STATE_NAME);
rc = cancel_work_sync(&hdcp_ctrl->hdcp_int_work);
if (rc)
- DEV_DBG("%s: %s: Deleted hdcp int work\n", __func__,
+ pr_debug("%s: Deleted hdcp int work\n",
HDCP_STATE_NAME);
@@ -1599,7 +1402,7 @@ void hdcp_1x_off(void *input)
hdcp_ctrl->sink_r0_ready = false;
- DEV_DBG("%s: %s: HDCP: Off\n", __func__, HDCP_STATE_NAME);
+ pr_debug("%s: HDCP: Off\n", HDCP_STATE_NAME);
} /* hdcp_1x_off */
int hdcp_1x_isr(void *input)
@@ -1612,7 +1415,7 @@ int hdcp_1x_isr(void *input)
struct hdcp_int_set *isr;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
rc = -EINVAL;
goto error;
}
@@ -1633,7 +1436,7 @@ int hdcp_1x_isr(void *input)
/* AUTH_SUCCESS_INT */
DSS_REG_W(io, isr->int_reg,
(hdcp_int_val | isr->auth_success_ack));
- DEV_INFO("%s: %s: AUTH_SUCCESS_INT received\n", __func__,
+ pr_debug("%s: AUTH_SUCCESS_INT received\n",
HDCP_STATE_NAME);
if (HDCP_STATE_AUTHENTICATING == hdcp_ctrl->hdcp_state)
complete_all(&hdcp_ctrl->r0_checked);
@@ -1645,8 +1448,8 @@ int hdcp_1x_isr(void *input)
DSS_REG_W(io, isr->int_reg,
(hdcp_int_val | isr->auth_fail_ack));
- DEV_INFO("%s: %s: AUTH_FAIL_INT rcvd, LINK0_STATUS=0x%08x\n",
- __func__, HDCP_STATE_NAME, link_status);
+ pr_debug("%s: AUTH_FAIL_INT rcvd, LINK0_STATUS=0x%08x\n",
+ HDCP_STATE_NAME, link_status);
if (HDCP_STATE_AUTHENTICATED == hdcp_ctrl->hdcp_state) {
/* Inform HDMI Tx of the failure */
queue_work(hdcp_ctrl->workq,
@@ -1665,7 +1468,7 @@ int hdcp_1x_isr(void *input)
/* DDC_XFER_REQ_INT */
DSS_REG_W(io, isr->int_reg,
(hdcp_int_val | isr->tx_req_ack));
- DEV_INFO("%s: %s: DDC_XFER_REQ_INT received\n", __func__,
+ pr_debug("%s: DDC_XFER_REQ_INT received\n",
HDCP_STATE_NAME);
}
@@ -1673,7 +1476,7 @@ int hdcp_1x_isr(void *input)
/* DDC_XFER_DONE_INT */
DSS_REG_W(io, isr->int_reg,
(hdcp_int_val | isr->tx_req_done_ack));
- DEV_INFO("%s: %s: DDC_XFER_DONE received\n", __func__,
+ pr_debug("%s: DDC_XFER_DONE received\n",
HDCP_STATE_NAME);
}
@@ -1681,7 +1484,7 @@ int hdcp_1x_isr(void *input)
/* Encryption enabled */
DSS_REG_W(io, isr->int_reg,
(hdcp_int_val | isr->encryption_ready_ack));
- DEV_INFO("%s: %s: encryption ready received\n", __func__,
+ pr_debug("%s: encryption ready received\n",
HDCP_STATE_NAME);
}
@@ -1689,7 +1492,7 @@ int hdcp_1x_isr(void *input)
/* Encryption enabled */
DSS_REG_W(io, isr->int_reg,
(hdcp_int_val | isr->encryption_not_ready_ack));
- DEV_INFO("%s: %s: encryption not ready received\n", __func__,
+ pr_debug("%s: encryption not ready received\n",
HDCP_STATE_NAME);
}
@@ -1738,13 +1541,13 @@ static ssize_t hdcp_1x_sysfs_rda_status(struct device *dev,
struct hdcp_1x_ctrl *hdcp_ctrl = hdcp_1x_get_ctrl(dev);
if (!hdcp_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return -EINVAL;
}
mutex_lock(hdcp_ctrl->init_data.mutex);
ret = snprintf(buf, PAGE_SIZE, "%d\n", hdcp_ctrl->hdcp_state);
- DEV_DBG("%s: '%d'\n", __func__, hdcp_ctrl->hdcp_state);
+ pr_debug("'%d'\n", hdcp_ctrl->hdcp_state);
mutex_unlock(hdcp_ctrl->init_data.mutex);
return ret;
@@ -1757,7 +1560,7 @@ static ssize_t hdcp_1x_sysfs_rda_tp(struct device *dev,
struct hdcp_1x_ctrl *hdcp_ctrl = hdcp_1x_get_ctrl(dev);
if (!hdcp_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return -EINVAL;
}
@@ -1791,7 +1594,7 @@ static ssize_t hdcp_1x_sysfs_wta_tp(struct device *dev,
struct hdcp_1x_ctrl *hdcp_ctrl = hdcp_1x_get_ctrl(dev);
if (!hdcp_ctrl || !buf) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return -EINVAL;
}
@@ -1831,7 +1634,7 @@ void hdcp_1x_deinit(void *input)
struct hdcp_1x_ctrl *hdcp_ctrl = (struct hdcp_1x_ctrl *)input;
if (!hdcp_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
return;
}
@@ -1872,39 +1675,46 @@ static int hdcp_1x_cp_irq(void *input)
int ret = -EINVAL;
if (!hdcp_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
goto end;
}
ret = hdcp_1x_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.cp_irq_status,
&buf, false);
if (IS_ERR_VALUE(ret)) {
- DEV_ERR("%s: error reading cp_irq_status\n", __func__);
+ pr_err("error reading cp_irq_status\n");
goto end;
}
if (!buf) {
- DEV_DBG("%s: not a hdcp 1.x irq\n", __func__);
+ pr_debug("not a hdcp 1.x irq\n");
ret = -EINVAL;
goto end;
}
if ((buf & BIT(2)) || (buf & BIT(3))) {
- DEV_ERR("%s: REAUTH REQUIRED\n", __func__);
+ pr_err("%s\n",
+ buf & BIT(2) ? "LINK_INTEGRITY_FAILURE" :
+ "REAUTHENTICATION_REQUEST");
+
+ hdcp_ctrl->reauth = true;
+
+ complete_all(&hdcp_ctrl->sink_rep_ready);
+ complete_all(&hdcp_ctrl->sink_r0_available);
queue_work(hdcp_ctrl->workq, &hdcp_ctrl->hdcp_int_work);
goto end;
}
if (buf & BIT(1)) {
- DEV_DBG("%s: R0' AVAILABLE\n", __func__);
+ pr_debug("R0' AVAILABLE\n");
hdcp_ctrl->sink_r0_ready = true;
complete_all(&hdcp_ctrl->sink_r0_available);
goto end;
}
if (buf & BIT(0)) {
- DEV_DBG("%s: KSVs READY\n", __func__);
+ pr_debug("KSVs READY\n");
complete_all(&hdcp_ctrl->sink_rep_ready);
goto end;
}
@@ -1916,7 +1726,6 @@ void *hdcp_1x_init(struct hdcp_init_data *init_data)
{
struct hdcp_1x_ctrl *hdcp_ctrl = NULL;
char name[20];
- int ret;
static struct hdcp_ops ops = {
.isr = hdcp_1x_isr,
.cp_irq = hdcp_1x_cp_irq,
@@ -1928,20 +1737,18 @@ void *hdcp_1x_init(struct hdcp_init_data *init_data)
if (!init_data || !init_data->core_io || !init_data->qfprom_io ||
!init_data->mutex || !init_data->notify_status ||
!init_data->workq || !init_data->cb_data) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("invalid input\n");
goto error;
}
if (init_data->sec_access && !init_data->hdcp_io) {
- DEV_ERR("%s: hdcp_io required\n", __func__);
+ pr_err("hdcp_io required\n");
goto error;
}
hdcp_ctrl = kzalloc(sizeof(*hdcp_ctrl), GFP_KERNEL);
- if (!hdcp_ctrl) {
- DEV_ERR("%s: Out of memory\n", __func__);
+ if (!hdcp_ctrl)
goto error;
- }
hdcp_ctrl->init_data = *init_data;
hdcp_ctrl->ops = &ops;
@@ -1951,7 +1758,7 @@ void *hdcp_1x_init(struct hdcp_init_data *init_data)
hdcp_ctrl->workq = create_workqueue(name);
if (!hdcp_ctrl->workq) {
- DEV_ERR("%s: Error creating workqueue\n", __func__);
+ pr_err("Error creating workqueue\n");
goto error;
}
@@ -1959,7 +1766,7 @@ void *hdcp_1x_init(struct hdcp_init_data *init_data)
if (sysfs_create_group(init_data->sysfs_kobj,
&hdcp_1x_fs_attr_group)) {
- DEV_ERR("%s: hdcp sysfs group creation failed\n", __func__);
+ pr_err("hdcp sysfs group creation failed\n");
goto error;
}
@@ -1971,18 +1778,7 @@ void *hdcp_1x_init(struct hdcp_init_data *init_data)
init_completion(&hdcp_ctrl->sink_r0_available);
init_completion(&hdcp_ctrl->sink_rep_ready);
- if (!hdcp_ctrl->init_data.sec_access) {
- ret = scm_is_call_available(SCM_SVC_HDCP, SCM_CMD_HDCP);
- if (ret <= 0) {
- DEV_ERR("%s: secure hdcp service unavailable, ret = %d",
- __func__, ret);
- } else {
- DEV_DBG("%s: tz_hdcp = 1\n", __func__);
- hdcp_ctrl->tz_hdcp = 1;
- }
- }
-
- DEV_DBG("%s: HDCP module initialized. HDCP_STATE=%s", __func__,
+ pr_debug("HDCP module initialized. HDCP_STATE=%s\n",
HDCP_STATE_NAME);
error:
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index e137a8b050b0..58e0d9676736 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -1139,12 +1139,31 @@ static int mdss_mdp_clk_update(u32 clk_idx, u32 enable)
{
int ret = -ENODEV;
struct clk *clk = mdss_mdp_get_clk(clk_idx);
+ struct mdss_data_type *mdata = mdss_res;
if (clk) {
pr_debug("clk=%d en=%d\n", clk_idx, enable);
if (enable) {
if (clk_idx == MDSS_CLK_MDP_VSYNC)
clk_set_rate(clk, 19200000);
+ if (mdss_has_quirk(mdata, MDSS_QUIRK_MDP_CLK_SET_RATE)
+ && (clk_idx == MDSS_CLK_MDP_CORE)) {
+
+ if (WARN_ON(!mdata->mdp_clk_rate)) {
+ /*
+ * rate should have been set in probe
+ * or during clk scaling; but if this
+ * is not the case, set max clk rate.
+ */
+ pr_warn("set max mdp clk rate:%u\n",
+ mdata->max_mdp_clk_rate);
+ mdss_mdp_set_clk_rate(
+ mdata->max_mdp_clk_rate, true);
+ } else {
+ clk_set_rate(clk, mdata->mdp_clk_rate);
+ }
+ }
+
ret = clk_prepare_enable(clk);
} else {
clk_disable_unprepare(clk);
@@ -1172,7 +1191,7 @@ int mdss_mdp_vsync_clk_enable(int enable, bool locked)
return ret;
}
-void mdss_mdp_set_clk_rate(unsigned long rate)
+void mdss_mdp_set_clk_rate(unsigned long rate, bool locked)
{
struct mdss_data_type *mdata = mdss_res;
unsigned long clk_rate;
@@ -1182,7 +1201,9 @@ void mdss_mdp_set_clk_rate(unsigned long rate)
min_clk_rate = max(rate, mdata->perf_tune.min_mdp_clk);
if (clk) {
- mutex_lock(&mdp_clk_lock);
+
+ if (!locked)
+ mutex_lock(&mdp_clk_lock);
if (min_clk_rate < mdata->max_mdp_clk_rate)
clk_rate = clk_round_rate(clk, min_clk_rate);
else
@@ -1190,12 +1211,15 @@ void mdss_mdp_set_clk_rate(unsigned long rate)
if (IS_ERR_VALUE(clk_rate)) {
pr_err("unable to round rate err=%ld\n", clk_rate);
} else if (clk_rate != clk_get_rate(clk)) {
+
+ mdata->mdp_clk_rate = clk_rate;
if (IS_ERR_VALUE(clk_set_rate(clk, clk_rate)))
pr_err("clk_set_rate failed\n");
else
pr_debug("mdp clk rate=%lu\n", clk_rate);
}
- mutex_unlock(&mdp_clk_lock);
+ if (!locked)
+ mutex_unlock(&mdp_clk_lock);
} else {
pr_err("mdp src clk not setup properly\n");
}
@@ -1779,7 +1803,7 @@ static int mdss_mdp_irq_clk_setup(struct mdss_data_type *mdata)
mdss_mdp_irq_clk_register(mdata, "mnoc_clk", MDSS_CLK_MNOC_AHB);
/* Setting the default clock rate to the max supported.*/
- mdss_mdp_set_clk_rate(mdata->max_mdp_clk_rate);
+ mdss_mdp_set_clk_rate(mdata->max_mdp_clk_rate, false);
pr_debug("mdp clk rate=%ld\n",
mdss_mdp_get_clk_rate(MDSS_CLK_MDP_CORE, false));
@@ -2022,6 +2046,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
mdss_set_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU);
mdss_set_quirk(mdata, MDSS_QUIRK_DSC_2SLICE_PU_THRPUT);
mdss_set_quirk(mdata, MDSS_QUIRK_MMSS_GDSC_COLLAPSE);
+ mdss_set_quirk(mdata, MDSS_QUIRK_MDP_CLK_SET_RATE);
mdata->has_wb_ubwc = true;
set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map);
set_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map);
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 623c588ae456..20aeabfdf9a4 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -22,6 +22,7 @@
#include <linux/notifier.h>
#include <linux/irqreturn.h>
#include <linux/kref.h>
+#include <linux/kthread.h>
#include "mdss.h"
#include "mdss_mdp_hwio.h"
@@ -550,6 +551,7 @@ struct mdss_mdp_ctl {
/* dynamic resolution switch during cont-splash handoff */
bool switch_with_handoff;
struct mdss_mdp_avr_info avr_info;
+ bool commit_in_progress;
};
struct mdss_mdp_mixer {
@@ -931,7 +933,6 @@ struct mdss_overlay_private {
struct sw_sync_timeline *vsync_timeline;
struct mdss_mdp_vsync_handler vsync_retire_handler;
- struct work_struct retire_work;
int retire_cnt;
bool kickoff_released;
u32 cursor_ndx[2];
@@ -943,6 +944,11 @@ struct mdss_overlay_private {
struct mdss_mdp_cwb cwb;
wait_queue_head_t wb_waitq;
atomic_t wb_busy;
+ bool allow_kickoff;
+
+ struct kthread_worker worker;
+ struct kthread_work vsync_work;
+ struct task_struct *thread;
};
struct mdss_mdp_set_ot_params {
@@ -1590,7 +1596,7 @@ u32 mdss_mdp_get_irq_mask(u32 intr_type, u32 intf_num);
void mdss_mdp_footswitch_ctrl_splash(int on);
void mdss_mdp_batfet_ctrl(struct mdss_data_type *mdata, int enable);
-void mdss_mdp_set_clk_rate(unsigned long min_clk_rate);
+void mdss_mdp_set_clk_rate(unsigned long min_clk_rate, bool locked);
unsigned long mdss_mdp_get_clk_rate(u32 clk_idx, bool locked);
int mdss_mdp_vsync_clk_enable(int enable, bool locked);
void mdss_mdp_clk_ctrl(int enable);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 9c5c5ea090c3..c80d8f47bbb7 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -2375,7 +2375,7 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl,
*/
if (update_clk) {
ATRACE_INT("mdp_clk", clk_rate);
- mdss_mdp_set_clk_rate(clk_rate);
+ mdss_mdp_set_clk_rate(clk_rate, false);
pr_debug("update clk rate = %d HZ\n", clk_rate);
}
@@ -5788,7 +5788,9 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
} else {
sctl_flush_bits = sctl->flush_bits;
}
+ sctl->commit_in_progress = true;
}
+ ctl->commit_in_progress = true;
ctl_flush_bits = ctl->flush_bits;
ATRACE_END("postproc_programming");
@@ -5916,11 +5918,16 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
ATRACE_BEGIN("flush_kickoff");
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl_flush_bits);
- if (sctl && sctl_flush_bits) {
- mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH,
- sctl_flush_bits);
- sctl->flush_bits = 0;
+ if (sctl) {
+ if (sctl_flush_bits) {
+ mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH,
+ sctl_flush_bits);
+ sctl->flush_bits = 0;
+ }
+ sctl->commit_in_progress = false;
}
+ ctl->commit_in_progress = false;
+
MDSS_XLOG(ctl->intf_num, ctl_flush_bits, sctl_flush_bits,
split_lm_valid);
wmb();
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index a71c7254de7c..4852fc73f040 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -1267,7 +1267,8 @@ static void mdss_mdp_cmd_pingpong_done(void *arg)
atomic_read(&ctx->koff_cnt));
if (sync_ppdone) {
atomic_inc(&ctx->pp_done_cnt);
- schedule_work(&ctx->pp_done_work);
+ if (!ctl->commit_in_progress)
+ schedule_work(&ctx->pp_done_work);
mdss_mdp_resource_control(ctl,
MDP_RSRC_CTL_EVENT_PP_DONE);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 154b9d86e67c..bf8130b35a57 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -1923,6 +1923,8 @@ static void __restore_pipe(struct mdss_mdp_pipe *pipe)
pipe->dst.y = pipe->layer.dst_rect.y;
pipe->dst.w = pipe->layer.dst_rect.w;
pipe->dst.h = pipe->layer.dst_rect.h;
+
+ pipe->restore_roi = false;
}
/**
@@ -1946,7 +1948,6 @@ static int __crop_adjust_pipe_rect(struct mdss_mdp_pipe *pipe,
u32 roi_y_pos;
int ret = 0;
- pipe->restore_roi = false;
if (mdss_rect_overlap_check(&pipe->dst, &dual_roi->first_roi)) {
mdss_mdp_crop_rect(&pipe->src, &pipe->dst,
&dual_roi->first_roi, false);
@@ -2092,6 +2093,13 @@ static void __validate_and_set_roi(struct msm_fb_data_type *mfd,
}
list_for_each_entry(pipe, &mdp5_data->pipes_used, list) {
+ /*
+ * Restore the pipe src/dst ROI if it was altered
+ * in the previous kickoff.
+ */
+ if (pipe->restore_roi)
+ __restore_pipe(pipe);
+
pr_debug("pipe:%d src:{%d,%d,%d,%d} dst:{%d,%d,%d,%d}\n",
pipe->num, pipe->src.x, pipe->src.y,
pipe->src.w, pipe->src.h, pipe->dst.x,
@@ -5580,7 +5588,7 @@ ctl_stop:
* retire_signal api checks for retire_cnt with sync_mutex lock.
*/
- flush_work(&mdp5_data->retire_work);
+ flush_kthread_work(&mdp5_data->vsync_work);
}
mutex_lock(&mdp5_data->ov_lock);
@@ -5783,13 +5791,13 @@ static void __vsync_retire_handle_vsync(struct mdss_mdp_ctl *ctl, ktime_t t)
}
mdp5_data = mfd_to_mdp5_data(mfd);
- schedule_work(&mdp5_data->retire_work);
+ queue_kthread_work(&mdp5_data->worker, &mdp5_data->vsync_work);
}
-static void __vsync_retire_work_handler(struct work_struct *work)
+static void __vsync_retire_work_handler(struct kthread_work *work)
{
struct mdss_overlay_private *mdp5_data =
- container_of(work, typeof(*mdp5_data), retire_work);
+ container_of(work, typeof(*mdp5_data), vsync_work);
if (!mdp5_data->ctl || !mdp5_data->ctl->mfd)
return;
@@ -5889,6 +5897,7 @@ static int __vsync_retire_setup(struct msm_fb_data_type *mfd)
{
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
char name[24];
+ struct sched_param param = { .sched_priority = 5 };
snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index);
mdp5_data->vsync_timeline = sw_sync_timeline_create(name);
@@ -5896,12 +5905,26 @@ static int __vsync_retire_setup(struct msm_fb_data_type *mfd)
pr_err("cannot vsync create time line");
return -ENOMEM;
}
+
+ init_kthread_worker(&mdp5_data->worker);
+ init_kthread_work(&mdp5_data->vsync_work, __vsync_retire_work_handler);
+
+ mdp5_data->thread = kthread_run(kthread_worker_fn,
+ &mdp5_data->worker, "vsync_retire_work");
+
+ if (IS_ERR(mdp5_data->thread)) {
+ pr_err("unable to start vsync thread\n");
+ mdp5_data->thread = NULL;
+ return -ENOMEM;
+ }
+
+ sched_setscheduler(mdp5_data->thread, SCHED_FIFO, &param);
+
mfd->mdp_sync_pt_data.get_retire_fence = __vsync_retire_get_fence;
mdp5_data->vsync_retire_handler.vsync_handler =
__vsync_retire_handle_vsync;
mdp5_data->vsync_retire_handler.cmd_post_flush = false;
- INIT_WORK(&mdp5_data->retire_work, __vsync_retire_work_handler);
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index 94e64dd396d5..4d42e42035c3 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -1114,6 +1114,7 @@ static void mdss_mdp_init_pipe_params(struct mdss_mdp_pipe *pipe)
pipe->is_right_blend = false;
pipe->src_split_req = false;
pipe->bwc_mode = 0;
+ pipe->restore_roi = false;
pipe->mfd = NULL;
pipe->mixer_left = pipe->mixer_right = NULL;
diff --git a/include/linux/clk/msm-clk-provider.h b/include/linux/clk/msm-clk-provider.h
index a09ce5c3b156..2fa8916ad356 100644
--- a/include/linux/clk/msm-clk-provider.h
+++ b/include/linux/clk/msm-clk-provider.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2007-2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -29,6 +29,7 @@
#include <linux/seq_file.h>
#include <linux/clk/msm-clk.h>
+#if defined(CONFIG_COMMON_CLK_MSM)
/*
* Bit manipulation macros
*/
@@ -265,4 +266,5 @@ static inline const char *clk_name(struct clk *c)
return "(null)";
return c->dbg_name;
};
+#endif /* CONFIG_COMMON_CLK_MSM */
#endif
diff --git a/include/linux/clk/msm-clk.h b/include/linux/clk/msm-clk.h
index 964909d25021..8455fd776246 100644
--- a/include/linux/clk/msm-clk.h
+++ b/include/linux/clk/msm-clk.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2012-2015 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009, 2012-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,6 +23,9 @@ enum branch_mem_flags {
CLKFLAG_PERIPH_OFF_SET,
CLKFLAG_PERIPH_OFF_CLEAR,
};
+
+#include <linux/clk.h>
+
#elif defined(CONFIG_COMMON_CLK_MSM)
#define CLKFLAG_INVERT 0x00000001
#define CLKFLAG_NOINVERT 0x00000002
@@ -42,7 +45,6 @@ enum branch_mem_flags {
#define CLKFLAG_EPROBE_DEFER 0x00010000
#define CLKFLAG_PERIPH_OFF_SET 0x00020000
#define CLKFLAG_PERIPH_OFF_CLEAR 0x00040000
-#endif
struct clk_lookup;
struct clk;
@@ -132,4 +134,5 @@ int msm_clk_notif_register(struct clk *clk, struct notifier_block *nb);
int msm_clk_notif_unregister(struct clk *clk, struct notifier_block *nb);
+#endif /* CONFIG_COMMON_CLK_MSM */
#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4f6711f31939..9c3be2d56ac5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2401,6 +2401,8 @@ struct cpu_cycle_counter_cb {
u64 (*get_cpu_cycle_counter)(int cpu);
};
+#define MAX_NUM_CGROUP_COLOC_ID 20
+
#ifdef CONFIG_SCHED_HMP
extern void free_task_load_ptrs(struct task_struct *p);
extern int sched_set_window(u64 window_start, unsigned int window_size);
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index e713641cc3ec..e01e16e5cebe 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -3609,6 +3609,10 @@ struct asm_alac_cfg {
u32 channel_layout_tag;
};
+struct asm_g711_dec_cfg {
+ u32 sample_rate;
+};
+
struct asm_vorbis_cfg {
u32 bit_stream_fmt;
};
@@ -4220,6 +4224,22 @@ struct asm_aac_enc_cfg_v2 {
} __packed;
+#define ASM_MEDIA_FMT_G711_ALAW_FS 0x00010BF7
+#define ASM_MEDIA_FMT_G711_MLAW_FS 0x00010C2E
+
+struct asm_g711_enc_cfg_v2 {
+ struct apr_hdr hdr;
+ struct asm_stream_cmd_set_encdec_param encdec;
+ struct asm_enc_cfg_blk_param_v2 encblk;
+
+ u32 sample_rate;
+/*
+ * Number of samples per second.
+ * Supported values: 8000, 16000 Hz
+ */
+
+} __packed;
+
struct asm_vorbis_fmt_blk_v2 {
struct apr_hdr hdr;
struct asm_data_cmd_media_fmt_update_v2 fmtblk;
@@ -4321,6 +4341,12 @@ struct asm_alac_fmt_blk_v2 {
} __packed;
+struct asm_g711_dec_fmt_blk_v2 {
+ struct apr_hdr hdr;
+ struct asm_data_cmd_media_fmt_update_v2 fmtblk;
+ u32 sample_rate;
+} __packed;
+
struct asm_ape_fmt_blk_v2 {
struct apr_hdr hdr;
struct asm_data_cmd_media_fmt_update_v2 fmtblk;
@@ -8811,6 +8837,7 @@ struct afe_param_id_clip_bank_sel {
/* Supported OSR clock values */
#define Q6AFE_LPASS_OSR_CLK_12_P288_MHZ 0xBB8000
+#define Q6AFE_LPASS_OSR_CLK_11_P2896_MHZ 0xAC4400
#define Q6AFE_LPASS_OSR_CLK_9_P600_MHZ 0x927C00
#define Q6AFE_LPASS_OSR_CLK_8_P192_MHZ 0x7D0000
#define Q6AFE_LPASS_OSR_CLK_6_P144_MHZ 0x5DC000
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index f08bd73edb59..efa5af8e661c 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -73,6 +73,11 @@
/* bit 4 represents META enable of encoded data buffer */
#define BUFFER_META_ENABLE 0x0010
+/* bit 5 represents timestamp */
+/* bit 5 - 0 -- ASM_DATA_EVENT_READ_DONE will have relative time-stamp*/
+/* bit 5 - 1 -- ASM_DATA_EVENT_READ_DONE will have absolute time-stamp*/
+#define ABSOLUTE_TIMESTAMP_ENABLE 0x0020
+
/* Enable Sample_Rate/Channel_Mode notification event from Decoder */
#define SR_CM_NOTIFY_ENABLE 0x0004
@@ -175,6 +180,7 @@ struct audio_aio_read_param {
phys_addr_t paddr;
uint32_t len;
uint32_t uid;
+ uint32_t flags;/*meta data flags*/
};
struct audio_port_data {
@@ -382,6 +388,10 @@ int q6asm_enc_cfg_blk_aac(struct audio_client *ac,
uint32_t bit_rate,
uint32_t mode, uint32_t format);
+int q6asm_enc_cfg_blk_g711(struct audio_client *ac,
+ uint32_t frames_per_buf,
+ uint32_t sample_rate);
+
int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
uint32_t rate, uint32_t channels);
@@ -530,6 +540,9 @@ int q6asm_stream_media_format_block_flac(struct audio_client *ac,
int q6asm_media_format_block_alac(struct audio_client *ac,
struct asm_alac_cfg *cfg, int stream_id);
+int q6asm_media_format_block_g711(struct audio_client *ac,
+ struct asm_g711_dec_cfg *cfg, int stream_id);
+
int q6asm_stream_media_format_block_vorbis(struct audio_client *ac,
struct asm_vorbis_cfg *cfg, int stream_id);
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 14bd1e806ad7..748b7c277a3c 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -302,6 +302,8 @@ header-y += msm_audio_wma.h
header-y += msm_audio_wmapro.h
header-y += msm_audio_alac.h
header-y += msm_audio_ape.h
+header-y += msm_audio_g711.h
+header-y += msm_audio_g711_dec.h
header-y += msm_ion.h
header-y += msm_kgsl.h
header-y += msm_pft.h
diff --git a/include/uapi/linux/msm_audio_g711.h b/include/uapi/linux/msm_audio_g711.h
new file mode 100644
index 000000000000..48ebd6a1131e
--- /dev/null
+++ b/include/uapi/linux/msm_audio_g711.h
@@ -0,0 +1,17 @@
+#ifndef _UAPI_MSM_AUDIO_G711_H
+#define _UAPI_MSM_AUDIO_G711_H
+
+#include <linux/msm_audio.h>
+
+struct msm_audio_g711_enc_config {
+ uint32_t sample_rate;
+};
+
+#define AUDIO_SET_G711_ENC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_g711_enc_config)
+
+#define AUDIO_GET_G711_ENC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_g711_enc_config)
+
+
+#endif /* _UAPI_MSM_AUDIO_G711_H */
diff --git a/include/uapi/linux/msm_audio_g711_dec.h b/include/uapi/linux/msm_audio_g711_dec.h
new file mode 100644
index 000000000000..ff7e4ce39fd5
--- /dev/null
+++ b/include/uapi/linux/msm_audio_g711_dec.h
@@ -0,0 +1,16 @@
+#ifndef _UAPI_MSM_AUDIO_G711_H
+#define _UAPI_MSM_AUDIO_G711_H
+
+#include <linux/msm_audio.h>
+
+struct msm_audio_g711_dec_config {
+ uint32_t sample_rate;
+};
+
+#define AUDIO_SET_G711_DEC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+0), struct msm_audio_g711_dec_config)
+
+#define AUDIO_GET_G711_DEC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+1), struct msm_audio_g711_dec_config)
+
+#endif /* _UAPI_MSM_AUDIO_G711_H */
diff --git a/include/uapi/media/msm_media_info.h b/include/uapi/media/msm_media_info.h
index e9b5501c697b..50b8fc32b129 100644
--- a/include/uapi/media/msm_media_info.h
+++ b/include/uapi/media/msm_media_info.h
@@ -2,7 +2,9 @@
#define __MEDIA_INFO_H__
#ifndef MSM_MEDIA_ALIGN
-#define MSM_MEDIA_ALIGN(__sz, __align) (((__sz) + (__align-1)) & (~(__align-1)))
+#define MSM_MEDIA_ALIGN(__sz, __align) (((__align) & ((__align) - 1)) ?\
+ ((((__sz) + (__align) - 1) / (__align)) * (__align)) :\
+ (((__sz) + (__align) - 1) & (~((__align) - 1))))
#endif
#ifndef MSM_MEDIA_ROUNDUP
@@ -399,8 +401,195 @@ enum color_fmts {
* Extradata, 4096)
*/
COLOR_FMT_RGBA8888_UBWC,
+ /* Venus RGBA1010102 UBWC format:
+ * Contains 2 planes in the following order -
+ * (A) Meta plane
+ * (B) RGBA plane
+ *
+ * <--- RGB_Meta_Stride ---->
+ * <-------- Width ------>
+ * M M M M M M M M M M M M . . ^ ^
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . Height |
+ * M M M M M M M M M M M M . . | Meta_RGB_Scanlines
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . V |
+ * . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k
+ * . . . . . . . . . . . . . . V
+ * <-------- RGB_Stride -------->
+ * <------- Width ------->
+ * R R R R R R R R R R R R . . . . ^ ^
+ * R R R R R R R R R R R R . . . . | |
+ * R R R R R R R R R R R R . . . . Height |
+ * R R R R R R R R R R R R . . . . | RGB_Scanlines
+ * R R R R R R R R R R R R . . . . | |
+ * R R R R R R R R R R R R . . . . | |
+ * R R R R R R R R R R R R . . . . | |
+ * R R R R R R R R R R R R . . . . V |
+ * . . . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k
+ * . . . . . . . . . . . . . . . . V
+ *
+ * RGB_Stride = align(Width * 4, 256)
+ * RGB_Scanlines = align(Height, 16)
+ * RGB_Plane_size = align(RGB_Stride * RGB_Scanlines, 4096)
+ * RGB_Meta_Stride = align(roundup(Width, RGB_TileWidth), 64)
+ * RGB_Meta_Scanline = align(roundup(Height, RGB_TileHeight), 16)
+ * RGB_Meta_Plane_size = align(RGB_Meta_Stride *
+ * RGB_Meta_Scanlines, 4096)
+ * Extradata = 8k
+ *
+ * Total size = align(RGB_Meta_Plane_size + RGB_Plane_size +
+ * Extradata, 4096)
+ */
+ COLOR_FMT_RGBA1010102_UBWC,
+ /* Venus RGB565 UBWC format:
+ * Contains 2 planes in the following order -
+ * (A) Meta plane
+ * (B) RGB plane
+ *
+ * <--- RGB_Meta_Stride ---->
+ * <-------- Width ------>
+ * M M M M M M M M M M M M . . ^ ^
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . Height |
+ * M M M M M M M M M M M M . . | Meta_RGB_Scanlines
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . V |
+ * . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k
+ * . . . . . . . . . . . . . . V
+ * <-------- RGB_Stride -------->
+ * <------- Width ------->
+ * R R R R R R R R R R R R . . . . ^ ^
+ * R R R R R R R R R R R R . . . . | |
+ * R R R R R R R R R R R R . . . . Height |
+ * R R R R R R R R R R R R . . . . | RGB_Scanlines
+ * R R R R R R R R R R R R . . . . | |
+ * R R R R R R R R R R R R . . . . | |
+ * R R R R R R R R R R R R . . . . | |
+ * R R R R R R R R R R R R . . . . V |
+ * . . . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k
+ * . . . . . . . . . . . . . . . . V
+ *
+ * RGB_Stride = align(Width * 2, 128)
+ * RGB_Scanlines = align(Height, 16)
+ * RGB_Plane_size = align(RGB_Stride * RGB_Scanlines, 4096)
+ * RGB_Meta_Stride = align(roundup(Width, RGB_TileWidth), 64)
+ * RGB_Meta_Scanline = align(roundup(Height, RGB_TileHeight), 16)
+ * RGB_Meta_Plane_size = align(RGB_Meta_Stride *
+ * RGB_Meta_Scanlines, 4096)
+ * Extradata = 8k
+ *
+ * Total size = align(RGB_Meta_Plane_size + RGB_Plane_size +
+ * Extradata, 4096)
+ */
+ COLOR_FMT_RGB565_UBWC,
+ /* P010 UBWC:
+ * Compressed Macro-tile format for NV12.
+ * Contains 4 planes in the following order -
+ * (A) Y_Meta_Plane
+ * (B) Y_UBWC_Plane
+ * (C) UV_Meta_Plane
+ * (D) UV_UBWC_Plane
+ *
+ * Y_Meta_Plane consists of meta information to decode compressed
+ * tile data in Y_UBWC_Plane.
+ * Y_UBWC_Plane consists of Y data in compressed macro-tile format.
+ * UBWC decoder block will use the Y_Meta_Plane data together with
+ * Y_UBWC_Plane data to produce loss-less uncompressed 10 bit Y samples.
+ *
+ * UV_Meta_Plane consists of meta information to decode compressed
+ * tile data in UV_UBWC_Plane.
+ * UV_UBWC_Plane consists of UV data in compressed macro-tile format.
+ * UBWC decoder block will use UV_Meta_Plane data together with
+ * UV_UBWC_Plane data to produce loss-less uncompressed 10 bit 2x2
+ * subsampled color difference samples.
+ *
+ * Each tile in Y_UBWC_Plane/UV_UBWC_Plane is independently decodable
+ * and randomly accessible. There is no dependency between tiles.
+ *
+ * <----- Y_Meta_Stride ----->
+ * <-------- Width ------>
+ * M M M M M M M M M M M M . . ^ ^
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . Height |
+ * M M M M M M M M M M M M . . | Meta_Y_Scanlines
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . | |
+ * M M M M M M M M M M M M . . V |
+ * . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k
+ * . . . . . . . . . . . . . . V
+ * <--Compressed tile Y Stride--->
+ * <------- Width ------->
+ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . ^ ^
+ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | |
+ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . Height |
+ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | Macro_tile_Y_Scanlines
+ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | |
+ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | |
+ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . | |
+ * Y* Y* Y* Y* Y* Y* Y* Y* . . . . V |
+ * . . . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k
+ * . . . . . . . . . . . . . . . . V
+ * <----- UV_Meta_Stride ---->
+ * M M M M M M M M M M M M . . ^
+ * M M M M M M M M M M M M . . |
+ * M M M M M M M M M M M M . . |
+ * M M M M M M M M M M M M . . M_UV_Scanlines
+ * . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . V
+ * . . . . . . . . . . . . . . -------> Buffer size aligned to 4k
+ * <--Compressed tile UV Stride--->
+ * U* V* U* V* U* V* U* V* . . . . ^
+ * U* V* U* V* U* V* U* V* . . . . |
+ * U* V* U* V* U* V* U* V* . . . . |
+ * U* V* U* V* U* V* U* V* . . . . UV_Scanlines
+ * . . . . . . . . . . . . . . . . |
+ * . . . . . . . . . . . . . . . . V
+ * . . . . . . . . . . . . . . . . -------> Buffer size aligned to 4k
+ *
+ *
+ * Y_Stride = align(Width * 2, 256)
+ * UV_Stride = align(Width * 2, 256)
+ * Y_Scanlines = align(Height, 16)
+ * UV_Scanlines = align(Height/2, 16)
+ * Y_UBWC_Plane_Size = align(Y_Stride * Y_Scanlines, 4096)
+ * UV_UBWC_Plane_Size = align(UV_Stride * UV_Scanlines, 4096)
+ * Y_Meta_Stride = align(roundup(Width, Y_TileWidth), 64)
+ * Y_Meta_Scanlines = align(roundup(Height, Y_TileHeight), 16)
+ * Y_Meta_Plane_size = align(Y_Meta_Stride * Y_Meta_Scanlines, 4096)
+ * UV_Meta_Stride = align(roundup(Width, UV_TileWidth), 64)
+ * UV_Meta_Scanlines = align(roundup(Height, UV_TileHeight), 16)
+ * UV_Meta_Plane_size = align(UV_Meta_Stride * UV_Meta_Scanlines, 4096)
+ * Extradata = 8k
+ *
+ * Total size = align(Y_UBWC_Plane_size + UV_UBWC_Plane_size +
+ * Y_Meta_Plane_size + UV_Meta_Plane_size
+ * + max(Extradata, Y_Stride * 48), 4096)
+ */
+ COLOR_FMT_P010_UBWC,
};
+#define COLOR_FMT_RGBA1010102_UBWC COLOR_FMT_RGBA1010102_UBWC
+#define COLOR_FMT_RGB565_UBWC COLOR_FMT_RGB565_UBWC
+#define COLOR_FMT_P010_UBWC COLOR_FMT_P010_UBWC
+
static inline unsigned int VENUS_EXTRADATA_SIZE(int width, int height)
{
(void)height;
@@ -433,6 +622,10 @@ static inline unsigned int VENUS_Y_STRIDE(int color_fmt, int width)
stride = MSM_MEDIA_ALIGN(width, 192);
stride = MSM_MEDIA_ALIGN(stride * 4/3, alignment);
break;
+ case COLOR_FMT_P010_UBWC:
+ alignment = 256;
+ stride = MSM_MEDIA_ALIGN(width * 2, alignment);
+ break;
default:
break;
}
@@ -460,6 +653,10 @@ static inline unsigned int VENUS_UV_STRIDE(int color_fmt, int width)
stride = MSM_MEDIA_ALIGN(width, 192);
stride = MSM_MEDIA_ALIGN(stride * 4/3, alignment);
break;
+ case COLOR_FMT_P010_UBWC:
+ alignment = 256;
+ stride = MSM_MEDIA_ALIGN(width * 2, alignment);
+ break;
default:
break;
}
@@ -482,6 +679,7 @@ static inline unsigned int VENUS_Y_SCANLINES(int color_fmt, int height)
alignment = 32;
break;
case COLOR_FMT_NV12_BPP10_UBWC:
+ case COLOR_FMT_P010_UBWC:
alignment = 16;
break;
default:
@@ -504,6 +702,7 @@ static inline unsigned int VENUS_UV_SCANLINES(int color_fmt, int height)
case COLOR_FMT_NV12:
case COLOR_FMT_NV12_MVTB:
case COLOR_FMT_NV12_BPP10_UBWC:
+ case COLOR_FMT_P010_UBWC:
alignment = 16;
break;
case COLOR_FMT_NV12_UBWC:
@@ -528,6 +727,7 @@ static inline unsigned int VENUS_Y_META_STRIDE(int color_fmt, int width)
switch (color_fmt) {
case COLOR_FMT_NV12_UBWC:
+ case COLOR_FMT_P010_UBWC:
y_tile_width = 32;
break;
case COLOR_FMT_NV12_BPP10_UBWC:
@@ -556,6 +756,7 @@ static inline unsigned int VENUS_Y_META_SCANLINES(int color_fmt, int height)
y_tile_height = 8;
break;
case COLOR_FMT_NV12_BPP10_UBWC:
+ case COLOR_FMT_P010_UBWC:
y_tile_height = 4;
break;
default:
@@ -578,6 +779,7 @@ static inline unsigned int VENUS_UV_META_STRIDE(int color_fmt, int width)
switch (color_fmt) {
case COLOR_FMT_NV12_UBWC:
+ case COLOR_FMT_P010_UBWC:
uv_tile_width = 16;
break;
case COLOR_FMT_NV12_BPP10_UBWC:
@@ -606,6 +808,7 @@ static inline unsigned int VENUS_UV_META_SCANLINES(int color_fmt, int height)
uv_tile_height = 8;
break;
case COLOR_FMT_NV12_BPP10_UBWC:
+ case COLOR_FMT_P010_UBWC:
uv_tile_height = 4;
break;
default:
@@ -621,7 +824,7 @@ invalid_input:
static inline unsigned int VENUS_RGB_STRIDE(int color_fmt, int width)
{
- unsigned int alignment = 0, stride = 0;
+ unsigned int alignment = 0, stride = 0, bpp = 4;
if (!width)
goto invalid_input;
@@ -630,14 +833,19 @@ static inline unsigned int VENUS_RGB_STRIDE(int color_fmt, int width)
case COLOR_FMT_RGBA8888:
alignment = 128;
break;
+ case COLOR_FMT_RGB565_UBWC:
+ alignment = 128;
+ bpp = 2;
+ break;
case COLOR_FMT_RGBA8888_UBWC:
+ case COLOR_FMT_RGBA1010102_UBWC:
alignment = 256;
break;
default:
goto invalid_input;
}
- stride = MSM_MEDIA_ALIGN(width * 4, alignment);
+ stride = MSM_MEDIA_ALIGN(width * bpp, alignment);
invalid_input:
return stride;
@@ -655,6 +863,8 @@ static inline unsigned int VENUS_RGB_SCANLINES(int color_fmt, int height)
alignment = 32;
break;
case COLOR_FMT_RGBA8888_UBWC:
+ case COLOR_FMT_RGBA1010102_UBWC:
+ case COLOR_FMT_RGB565_UBWC:
alignment = 16;
break;
default:
@@ -676,6 +886,8 @@ static inline unsigned int VENUS_RGB_META_STRIDE(int color_fmt, int width)
switch (color_fmt) {
case COLOR_FMT_RGBA8888_UBWC:
+ case COLOR_FMT_RGBA1010102_UBWC:
+ case COLOR_FMT_RGB565_UBWC:
rgb_tile_width = 16;
break;
default:
@@ -698,6 +910,8 @@ static inline unsigned int VENUS_RGB_META_SCANLINES(int color_fmt, int height)
switch (color_fmt) {
case COLOR_FMT_RGBA8888_UBWC:
+ case COLOR_FMT_RGBA1010102_UBWC:
+ case COLOR_FMT_RGB565_UBWC:
rgb_tile_height = 4;
break;
default:
diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h
index 47367c663011..ef96966b2bbe 100644
--- a/include/uapi/sound/compress_params.h
+++ b/include/uapi/sound/compress_params.h
@@ -70,6 +70,11 @@
#define Q6_DTS 0x00010D88
#define Q6_DTS_LBR 0x00010DBB
+/* Timestamp flsg */
+/* Bit-0 - 1 : Enable Timestamp mode */
+/* Bit-0 - 0 : Disable Timestamp mode */
+#define COMPRESSED_TIMESTAMP_FLAG 0x0001
+
/* Codecs are listed linearly to allow for extensibility */
#define SND_AUDIOCODEC_PCM ((__u32) 0x00000001)
#define SND_AUDIOCODEC_MP3 ((__u32) 0x00000002)
@@ -480,7 +485,24 @@ struct snd_codec {
__u32 align;
__u32 compr_passthr;
union snd_codec_options options;
- __u32 reserved[3];
+ __u32 flags;
+ __u32 reserved[2];
} __attribute__((packed, aligned(4)));
+
+/** struct snd_codec_metadata
+ * @length: Length of the encoded buffer.
+ * @offset: Offset from the buffer address to the first byte of the first
+ * encoded frame. All encoded frames are consecutive starting
+ * from this offset.
+ * @timestamp: Session time in microseconds of the first sample in the buffer.
+ * @reserved: Reserved for future use.
+ */
+struct snd_codec_metadata {
+ __u32 length;
+ __u32 offset;
+ __u64 timestamp;
+ __u32 reserved[4];
+};
+
#endif
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index f352d06d7673..d7846edd7a79 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8071,6 +8071,9 @@ void __init sched_init(void)
atomic_set(&rq->nr_iowait, 0);
}
+ i = alloc_related_thread_groups();
+ BUG_ON(i);
+
set_hmp_defaults();
set_load_weight(&init_task);
diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c
index 5ff7a11d043f..6304c5030137 100644
--- a/kernel/sched/hmp.c
+++ b/kernel/sched/hmp.c
@@ -788,11 +788,12 @@ __read_mostly unsigned int sched_major_task_runtime = 10000000;
static unsigned int sync_cpu;
-static LIST_HEAD(related_thread_groups);
+struct related_thread_group *related_thread_groups[MAX_NUM_CGROUP_COLOC_ID];
+static LIST_HEAD(active_related_thread_groups);
static DEFINE_RWLOCK(related_thread_group_lock);
#define for_each_related_thread_group(grp) \
- list_for_each_entry(grp, &related_thread_groups, list)
+ list_for_each_entry(grp, &active_related_thread_groups, list)
/*
* Task load is categorized into buckets for the purpose of top task tracking.
@@ -3056,7 +3057,7 @@ void reset_all_window_stats(u64 window_start, unsigned int window_size)
read_unlock(&tasklist_lock);
- list_for_each_entry(grp, &related_thread_groups, list) {
+ list_for_each_entry(grp, &active_related_thread_groups, list) {
int j;
for_each_possible_cpu(j) {
@@ -3972,47 +3973,54 @@ _group_cpu_time(struct related_thread_group *grp, int cpu)
return grp ? per_cpu_ptr(grp->cpu_time, cpu) : NULL;
}
-struct related_thread_group *alloc_related_thread_group(int group_id)
+static inline struct related_thread_group*
+lookup_related_thread_group(unsigned int group_id)
{
- struct related_thread_group *grp;
-
- grp = kzalloc(sizeof(*grp), GFP_ATOMIC);
- if (!grp)
- return ERR_PTR(-ENOMEM);
-
- if (alloc_group_cputime(grp)) {
- kfree(grp);
- return ERR_PTR(-ENOMEM);
- }
-
- grp->id = group_id;
- INIT_LIST_HEAD(&grp->tasks);
- INIT_LIST_HEAD(&grp->list);
- raw_spin_lock_init(&grp->lock);
-
- return grp;
+ return related_thread_groups[group_id];
}
-struct related_thread_group *lookup_related_thread_group(unsigned int group_id)
+int alloc_related_thread_groups(void)
{
+ int i, ret;
struct related_thread_group *grp;
- list_for_each_entry(grp, &related_thread_groups, list) {
- if (grp->id == group_id)
- return grp;
+ /* groupd_id = 0 is invalid as it's special id to remove group. */
+ for (i = 1; i < MAX_NUM_CGROUP_COLOC_ID; i++) {
+ grp = kzalloc(sizeof(*grp), GFP_NOWAIT);
+ if (!grp) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ if (alloc_group_cputime(grp)) {
+ kfree(grp);
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ grp->id = i;
+ INIT_LIST_HEAD(&grp->tasks);
+ INIT_LIST_HEAD(&grp->list);
+ raw_spin_lock_init(&grp->lock);
+
+ related_thread_groups[i] = grp;
}
- return NULL;
-}
+ return 0;
-/* See comments before preferred_cluster() */
-static void free_related_thread_group(struct rcu_head *rcu)
-{
- struct related_thread_group *grp = container_of(rcu, struct
- related_thread_group, rcu);
+err:
+ for (i = 1; i < MAX_NUM_CGROUP_COLOC_ID; i++) {
+ grp = lookup_related_thread_group(i);
+ if (grp) {
+ free_group_cputime(grp);
+ kfree(grp);
+ related_thread_groups[i] = NULL;
+ } else {
+ break;
+ }
+ }
- free_group_cputime(grp);
- kfree(grp);
+ return ret;
}
static void remove_task_from_group(struct task_struct *p)
@@ -4037,10 +4045,12 @@ static void remove_task_from_group(struct task_struct *p)
raw_spin_unlock(&grp->lock);
/* Reserved groups cannot be destroyed */
- if (empty_group && grp->id != DEFAULT_CGROUP_COLOC_ID) {
- list_del(&grp->list);
- call_rcu(&grp->rcu, free_related_thread_group);
- }
+ if (empty_group && grp->id != DEFAULT_CGROUP_COLOC_ID)
+ /*
+ * We test whether grp->list is attached with list_empty()
+ * hence re-init the list after deletion.
+ */
+ list_del_init(&grp->list);
}
static int
@@ -4112,53 +4122,15 @@ void add_new_task_to_grp(struct task_struct *new)
write_unlock_irqrestore(&related_thread_group_lock, flags);
}
-#if defined(CONFIG_SCHED_TUNE) && defined(CONFIG_CGROUP_SCHEDTUNE)
-/*
- * We create a default colocation group at boot. There is no need to
- * synchronize tasks between cgroups at creation time because the
- * correct cgroup hierarchy is not available at boot. Therefore cgroup
- * colocation is turned off by default even though the colocation group
- * itself has been allocated. Furthermore this colocation group cannot
- * be destroyted once it has been created. All of this has been as part
- * of runtime optimizations.
- *
- * The job of synchronizing tasks to the colocation group is done when
- * the colocation flag in the cgroup is turned on.
- */
-static int __init create_default_coloc_group(void)
-{
- struct related_thread_group *grp = NULL;
- unsigned long flags;
-
- grp = alloc_related_thread_group(DEFAULT_CGROUP_COLOC_ID);
- if (IS_ERR(grp)) {
- WARN_ON(1);
- return -ENOMEM;
- }
-
- write_lock_irqsave(&related_thread_group_lock, flags);
- list_add(&grp->list, &related_thread_groups);
- write_unlock_irqrestore(&related_thread_group_lock, flags);
-
- update_freq_aggregate_threshold(MAX_FREQ_AGGR_THRESH);
- return 0;
-}
-late_initcall(create_default_coloc_group);
-
-int sync_cgroup_colocation(struct task_struct *p, bool insert)
-{
- unsigned int grp_id = insert ? DEFAULT_CGROUP_COLOC_ID : 0;
-
- return sched_set_group_id(p, grp_id);
-}
-#endif
-
-int sched_set_group_id(struct task_struct *p, unsigned int group_id)
+static int __sched_set_group_id(struct task_struct *p, unsigned int group_id)
{
int rc = 0;
unsigned long flags;
struct related_thread_group *grp = NULL;
+ if (group_id >= MAX_NUM_CGROUP_COLOC_ID)
+ return -EINVAL;
+
raw_spin_lock_irqsave(&p->pi_lock, flags);
write_lock(&related_thread_group_lock);
@@ -4174,29 +4146,26 @@ int sched_set_group_id(struct task_struct *p, unsigned int group_id)
}
grp = lookup_related_thread_group(group_id);
- if (!grp) {
- /* This is a reserved id */
- if (group_id == DEFAULT_CGROUP_COLOC_ID) {
- rc = -EINVAL;
- goto done;
- }
-
- grp = alloc_related_thread_group(group_id);
- if (IS_ERR(grp)) {
- rc = -ENOMEM;
- goto done;
- }
-
- list_add(&grp->list, &related_thread_groups);
- }
+ if (list_empty(&grp->list))
+ list_add(&grp->list, &active_related_thread_groups);
rc = add_task_to_group(p, grp);
done:
write_unlock(&related_thread_group_lock);
raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+
return rc;
}
+int sched_set_group_id(struct task_struct *p, unsigned int group_id)
+{
+ /* DEFAULT_CGROUP_COLOC_ID is a reserved id */
+ if (group_id == DEFAULT_CGROUP_COLOC_ID)
+ return -EINVAL;
+
+ return __sched_set_group_id(p, group_id);
+}
+
unsigned int sched_get_group_id(struct task_struct *p)
{
unsigned int group_id;
@@ -4210,6 +4179,42 @@ unsigned int sched_get_group_id(struct task_struct *p)
return group_id;
}
+#if defined(CONFIG_SCHED_TUNE) && defined(CONFIG_CGROUP_SCHEDTUNE)
+/*
+ * We create a default colocation group at boot. There is no need to
+ * synchronize tasks between cgroups at creation time because the
+ * correct cgroup hierarchy is not available at boot. Therefore cgroup
+ * colocation is turned off by default even though the colocation group
+ * itself has been allocated. Furthermore this colocation group cannot
+ * be destroyted once it has been created. All of this has been as part
+ * of runtime optimizations.
+ *
+ * The job of synchronizing tasks to the colocation group is done when
+ * the colocation flag in the cgroup is turned on.
+ */
+static int __init create_default_coloc_group(void)
+{
+ struct related_thread_group *grp = NULL;
+ unsigned long flags;
+
+ grp = lookup_related_thread_group(DEFAULT_CGROUP_COLOC_ID);
+ write_lock_irqsave(&related_thread_group_lock, flags);
+ list_add(&grp->list, &active_related_thread_groups);
+ write_unlock_irqrestore(&related_thread_group_lock, flags);
+
+ update_freq_aggregate_threshold(MAX_FREQ_AGGR_THRESH);
+ return 0;
+}
+late_initcall(create_default_coloc_group);
+
+int sync_cgroup_colocation(struct task_struct *p, bool insert)
+{
+ unsigned int grp_id = insert ? DEFAULT_CGROUP_COLOC_ID : 0;
+
+ return __sched_set_group_id(p, grp_id);
+}
+#endif
+
static void update_cpu_cluster_capacity(const cpumask_t *cpus)
{
int i;
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 30838bb9b442..f569c6fe3cbb 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1448,6 +1448,8 @@ static inline void update_cgroup_boost_settings(void) { }
static inline void restore_cgroup_boost_settings(void) { }
#endif
+extern int alloc_related_thread_groups(void);
+
#else /* CONFIG_SCHED_HMP */
struct hmp_sched_stats;
@@ -1638,6 +1640,7 @@ static inline void set_hmp_defaults(void) { }
static inline void clear_reserved(int cpu) { }
static inline void sched_boost_parse_dt(void) {}
+static inline int alloc_related_thread_groups(void) { return 0; }
#define trace_sched_cpu_load(...)
#define trace_sched_cpu_load_lb(...)
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index 00c96462cc36..3ecd3807c2c2 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -7,6 +7,7 @@
#include <linux/pageblock-flags.h>
#include <linux/memory.h>
#include <linux/hugetlb.h>
+#include <linux/kasan.h>
#include "internal.h"
static int set_migratetype_isolate(struct page *page,
@@ -105,6 +106,8 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype)
if (pfn_valid_within(page_to_pfn(buddy)) &&
!is_migrate_isolate_page(buddy)) {
__isolate_free_page(page, order);
+ kasan_alloc_pages(page, order);
+ arch_alloc_page(page, order);
kernel_map_pages(page, (1 << order), 1);
set_page_refcounted(page);
isolated_page = page;
diff --git a/net/rmnet_data/rmnet_data_handlers.c b/net/rmnet_data/rmnet_data_handlers.c
index 185b609e637f..35b94e9da0d9 100644
--- a/net/rmnet_data/rmnet_data_handlers.c
+++ b/net/rmnet_data/rmnet_data_handlers.c
@@ -505,6 +505,7 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
if (pskb_expand_head(skb, required_headroom, 0, GFP_KERNEL)) {
LOGD("Failed to add headroom of %d bytes",
required_headroom);
+ kfree_skb(skb);
return 1;
}
}
@@ -528,6 +529,7 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
if (!map_header) {
LOGD("%s", "Failed to add MAP header to egress packet");
+ kfree_skb(skb);
return 1;
}
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index f580a1048d65..5f21eb37eae4 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -139,6 +139,10 @@ snd-soc-wcd9xxx-v2-objs := wcd9xxx-common-v2.o wcd9xxx-resmgr-v2.o
ifeq ($(CONFIG_COMMON_CLK_MSM), y)
audio-ext-clock-objs := audio-ext-clk.o
endif
+
+ifeq ($(CONFIG_COMMON_CLK_QCOM), y)
+ audio-ext-clock-up-objs := audio-ext-clk-up.o
+endif
snd-soc-wcd-cpe-objs := wcd_cpe_services.o wcd_cpe_core.o
snd-soc-wsa881x-objs := wsa881x.o wsa881x-tables.o wsa881x-regmap.o wsa881x-temp-sensor.o
snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o
@@ -349,6 +353,9 @@ obj-$(CONFIG_SND_SOC_WCD934X) += wcd934x/
ifeq ($(CONFIG_COMMON_CLK_MSM), y)
obj-$(CONFIG_AUDIO_EXT_CLK) += audio-ext-clock.o
endif
+ifeq ($(CONFIG_COMMON_CLK_QCOM), y)
+ obj-$(CONFIG_AUDIO_EXT_CLK) += audio-ext-clock-up.o
+endif
obj-$(CONFIG_SND_SOC_WCD9XXX) += snd-soc-wcd9xxx.o
obj-$(CONFIG_SND_SOC_WCD9XXX_V2) += snd-soc-wcd9xxx-v2.o
obj-$(CONFIG_SND_SOC_WCD_CPE) += snd-soc-wcd-cpe.o
diff --git a/sound/soc/codecs/audio-ext-clk-up.c b/sound/soc/codecs/audio-ext-clk-up.c
new file mode 100644
index 000000000000..f989498e9c32
--- /dev/null
+++ b/sound/soc/codecs/audio-ext-clk-up.c
@@ -0,0 +1,577 @@
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include "../../../drivers/clk/qcom/common.h"
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <dt-bindings/clock/audio-ext-clk.h>
+#include <sound/q6afe-v2.h>
+
+enum audio_clk_mux {
+ AP_CLK2,
+ LPASS_MCLK,
+ LPASS_MCLK2,
+};
+
+struct pinctrl_info {
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *sleep;
+ struct pinctrl_state *active;
+};
+
+struct audio_ext_ap_clk {
+ bool enabled;
+ int gpio;
+ struct clk_fixed_factor fact;
+};
+
+struct audio_ext_pmi_clk {
+ int gpio;
+ struct clk_fixed_factor fact;
+};
+
+struct audio_ext_ap_clk2 {
+ bool enabled;
+ struct pinctrl_info pnctrl_info;
+ struct clk_fixed_factor fact;
+};
+
+struct audio_ext_lpass_mclk {
+ struct pinctrl_info pnctrl_info;
+ struct clk_fixed_factor fact;
+};
+
+static struct afe_clk_set clk2_config = {
+ Q6AFE_LPASS_CLK_CONFIG_API_VERSION,
+ Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_OSR,
+ Q6AFE_LPASS_IBIT_CLK_11_P2896_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+};
+
+static struct afe_clk_set lpass_default = {
+ Q6AFE_LPASS_CLK_CONFIG_API_VERSION,
+ Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_OSR,
+ Q6AFE_LPASS_IBIT_CLK_11_P2896_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+};
+
+static struct afe_clk_set lpass_mclk = {
+ Q6AFE_LPASS_CLK_CONFIG_API_VERSION,
+ Q6AFE_LPASS_CLK_ID_MCLK_1,
+ Q6AFE_LPASS_OSR_CLK_11_P2896_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+};
+
+static inline struct audio_ext_ap_clk *to_audio_ap_clk(struct clk_hw *hw)
+{
+ return container_of(hw, struct audio_ext_ap_clk, fact.hw);
+}
+
+static int audio_ext_clk_prepare(struct clk_hw *hw)
+{
+ struct audio_ext_ap_clk *audio_clk = to_audio_ap_clk(hw);
+
+ pr_debug("%s: gpio: %d\n", __func__, audio_clk->gpio);
+ if (gpio_is_valid(audio_clk->gpio))
+ return gpio_direction_output(audio_clk->gpio, 1);
+ return 0;
+}
+
+static void audio_ext_clk_unprepare(struct clk_hw *hw)
+{
+ struct audio_ext_ap_clk *audio_clk = to_audio_ap_clk(hw);
+
+ pr_debug("%s: gpio: %d\n", __func__, audio_clk->gpio);
+ if (gpio_is_valid(audio_clk->gpio))
+ gpio_direction_output(audio_clk->gpio, 0);
+}
+
+static inline struct audio_ext_ap_clk2 *to_audio_ap_clk2(struct clk_hw *hw)
+{
+ return container_of(hw, struct audio_ext_ap_clk2, fact.hw);
+}
+
+static int audio_ext_clk2_prepare(struct clk_hw *hw)
+{
+ struct audio_ext_ap_clk2 *audio_clk2 = to_audio_ap_clk2(hw);
+ struct pinctrl_info *pnctrl_info = &audio_clk2->pnctrl_info;
+ int ret;
+
+
+ if (!pnctrl_info->pinctrl || !pnctrl_info->active)
+ return 0;
+
+ ret = pinctrl_select_state(pnctrl_info->pinctrl,
+ pnctrl_info->active);
+ if (ret) {
+ pr_err("%s: active state select failed with %d\n",
+ __func__, ret);
+ return -EIO;
+ }
+
+ clk2_config.enable = 1;
+ ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk2_config);
+ if (ret < 0) {
+ pr_err("%s: failed to set clock, ret = %d\n", __func__, ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void audio_ext_clk2_unprepare(struct clk_hw *hw)
+{
+ struct audio_ext_ap_clk2 *audio_clk2 = to_audio_ap_clk2(hw);
+ struct pinctrl_info *pnctrl_info = &audio_clk2->pnctrl_info;
+ int ret;
+
+ if (!pnctrl_info->pinctrl || !pnctrl_info->sleep)
+ return;
+
+ ret = pinctrl_select_state(pnctrl_info->pinctrl,
+ pnctrl_info->sleep);
+ if (ret)
+ pr_err("%s: sleep state select failed with %d\n",
+ __func__, ret);
+
+ clk2_config.enable = 0;
+ ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk2_config);
+ if (ret < 0)
+ pr_err("%s: failed to reset clock, ret = %d\n", __func__, ret);
+}
+
+static inline struct audio_ext_lpass_mclk *to_audio_lpass_mclk(
+ struct clk_hw *hw)
+{
+ return container_of(hw, struct audio_ext_lpass_mclk, fact.hw);
+}
+
+static int audio_ext_lpass_mclk_prepare(struct clk_hw *hw)
+{
+ struct audio_ext_lpass_mclk *audio_lpass_mclk = to_audio_lpass_mclk(hw);
+ struct pinctrl_info *pnctrl_info = &audio_lpass_mclk->pnctrl_info;
+ int ret;
+
+ if (pnctrl_info->pinctrl) {
+ ret = pinctrl_select_state(pnctrl_info->pinctrl,
+ pnctrl_info->active);
+ if (ret) {
+ pr_err("%s: active state select failed with %d\n",
+ __func__, ret);
+ return -EIO;
+ }
+ }
+
+ lpass_mclk.enable = 1;
+ ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &lpass_mclk);
+ if (ret < 0) {
+ pr_err("%s afe_set_digital_codec_core_clock failed\n",
+ __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void audio_ext_lpass_mclk_unprepare(struct clk_hw *hw)
+{
+ struct audio_ext_lpass_mclk *audio_lpass_mclk = to_audio_lpass_mclk(hw);
+ struct pinctrl_info *pnctrl_info = &audio_lpass_mclk->pnctrl_info;
+ int ret;
+
+ if (pnctrl_info->pinctrl) {
+ ret = pinctrl_select_state(pnctrl_info->pinctrl,
+ pnctrl_info->sleep);
+ if (ret) {
+ pr_err("%s: active state select failed with %d\n",
+ __func__, ret);
+ return;
+ }
+ }
+
+ lpass_mclk.enable = 0;
+ ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX,
+ &lpass_mclk);
+ if (ret < 0)
+ pr_err("%s: afe_set_digital_codec_core_clock failed, ret = %d\n",
+ __func__, ret);
+}
+
+static int audio_ext_lpass_mclk2_prepare(struct clk_hw *hw)
+{
+ struct audio_ext_lpass_mclk *audio_lpass_mclk2 =
+ to_audio_lpass_mclk(hw);
+ struct pinctrl_info *pnctrl_info = &audio_lpass_mclk2->pnctrl_info;
+ int ret;
+
+ if (pnctrl_info->pinctrl) {
+ ret = pinctrl_select_state(pnctrl_info->pinctrl,
+ pnctrl_info->active);
+ if (ret) {
+ pr_err("%s: active state select failed with %d\n",
+ __func__, ret);
+ return -EIO;
+ }
+ }
+
+ lpass_default.enable = 1;
+ ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &lpass_default);
+ if (ret < 0) {
+ pr_err("%s: failed to set clock, ret = %d\n", __func__, ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void audio_ext_lpass_mclk2_unprepare(struct clk_hw *hw)
+{
+ struct audio_ext_lpass_mclk *audio_lpass_mclk2 =
+ to_audio_lpass_mclk(hw);
+ struct pinctrl_info *pnctrl_info = &audio_lpass_mclk2->pnctrl_info;
+ int ret;
+
+ if (pnctrl_info->pinctrl) {
+ ret = pinctrl_select_state(pnctrl_info->pinctrl,
+ pnctrl_info->sleep);
+ if (ret)
+ pr_err("%s: sleep state select failed with %d\n",
+ __func__, ret);
+ }
+
+ lpass_default.enable = 0;
+ ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &lpass_default);
+ if (ret < 0)
+ pr_err("%s: failed to reset clock, ret = %d\n", __func__, ret);
+}
+
+static struct clk_ops audio_ext_ap_clk_ops = {
+ .prepare = audio_ext_clk_prepare,
+ .unprepare = audio_ext_clk_unprepare,
+};
+
+static struct clk_ops audio_ext_ap_clk2_ops = {
+ .prepare = audio_ext_clk2_prepare,
+ .unprepare = audio_ext_clk2_unprepare,
+};
+
+static struct clk_ops audio_ext_lpass_mclk_ops = {
+ .prepare = audio_ext_lpass_mclk_prepare,
+ .unprepare = audio_ext_lpass_mclk_unprepare,
+};
+
+static struct clk_ops audio_ext_lpass_mclk2_ops = {
+ .prepare = audio_ext_lpass_mclk2_prepare,
+ .unprepare = audio_ext_lpass_mclk2_unprepare,
+};
+
+static struct audio_ext_pmi_clk audio_pmi_clk = {
+ .gpio = -EINVAL,
+ .fact = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "audio_ext_pmi_clk",
+ .ops = &clk_dummy_ops,
+ },
+ },
+};
+
+static struct audio_ext_pmi_clk audio_pmi_lnbb_clk = {
+ .gpio = -EINVAL,
+ .fact = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "audio_ext_pmi_lnbb_clk",
+ .ops = &clk_dummy_ops,
+ },
+ },
+};
+
+static struct audio_ext_ap_clk audio_ap_clk = {
+ .gpio = -EINVAL,
+ .fact = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "audio_ap_clk",
+ .ops = &audio_ext_ap_clk_ops,
+ },
+ },
+};
+
+static struct audio_ext_ap_clk2 audio_ap_clk2 = {
+ .enabled = false,
+ .pnctrl_info = {NULL},
+ .fact = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "audio_ap_clk2",
+ .ops = &audio_ext_ap_clk2_ops,
+ },
+ },
+};
+
+static struct audio_ext_lpass_mclk audio_lpass_mclk = {
+ .pnctrl_info = {NULL},
+ .fact = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "audio_lpass_mclk",
+ .ops = &audio_ext_lpass_mclk_ops,
+ },
+ },
+};
+
+static struct audio_ext_lpass_mclk audio_lpass_mclk2 = {
+ .pnctrl_info = {NULL},
+ .fact = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "audio_lpass_mclk2",
+ .ops = &audio_ext_lpass_mclk2_ops,
+ },
+ },
+};
+
+static struct clk_hw *audio_msm_hws[] = {
+ &audio_pmi_clk.fact.hw,
+ &audio_pmi_lnbb_clk.fact.hw,
+ &audio_ap_clk.fact.hw,
+ &audio_ap_clk2.fact.hw,
+ &audio_lpass_mclk.fact.hw,
+ &audio_lpass_mclk2.fact.hw,
+};
+
+static int audio_get_pinctrl(struct platform_device *pdev,
+ enum audio_clk_mux mux)
+{
+ struct pinctrl_info *pnctrl_info;
+ struct pinctrl *pinctrl;
+ int ret;
+
+ switch (mux) {
+ case AP_CLK2:
+ pnctrl_info = &audio_ap_clk2.pnctrl_info;
+ break;
+ case LPASS_MCLK:
+ pnctrl_info = &audio_lpass_mclk.pnctrl_info;
+ break;
+ case LPASS_MCLK2:
+ pnctrl_info = &audio_lpass_mclk2.pnctrl_info;
+ break;
+ default:
+ dev_err(&pdev->dev, "%s Not a valid MUX ID: %d\n",
+ __func__, mux);
+ return -EINVAL;
+ }
+ pnctrl_info = &audio_ap_clk2.pnctrl_info;
+
+ if (pnctrl_info->pinctrl) {
+ dev_dbg(&pdev->dev, "%s: already requested before\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR_OR_NULL(pinctrl)) {
+ dev_dbg(&pdev->dev, "%s: Unable to get pinctrl handle\n",
+ __func__);
+ return -EINVAL;
+ }
+ pnctrl_info->pinctrl = pinctrl;
+ /* get all state handles from Device Tree */
+ pnctrl_info->sleep = pinctrl_lookup_state(pinctrl, "sleep");
+ if (IS_ERR(pnctrl_info->sleep)) {
+ dev_err(&pdev->dev, "%s: could not get sleep pinstate\n",
+ __func__);
+ goto err;
+ }
+ pnctrl_info->active = pinctrl_lookup_state(pinctrl, "active");
+ if (IS_ERR(pnctrl_info->active)) {
+ dev_err(&pdev->dev, "%s: could not get active pinstate\n",
+ __func__);
+ goto err;
+ }
+ /* Reset the TLMM pins to a default state */
+ ret = pinctrl_select_state(pnctrl_info->pinctrl,
+ pnctrl_info->sleep);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Disable TLMM pins failed with %d\n",
+ __func__, ret);
+ goto err;
+ }
+ return 0;
+
+err:
+ devm_pinctrl_put(pnctrl_info->pinctrl);
+ return -EINVAL;
+}
+
+static int audio_ref_clk_probe(struct platform_device *pdev)
+{
+ int clk_gpio;
+ int ret;
+ u32 mclk_freq;
+ struct clk *audio_clk;
+ struct device *dev = &pdev->dev;
+ int i;
+ struct clk_onecell_data *clk_data;
+
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "qcom,codec-mclk-clk-freq",
+ &mclk_freq);
+ if (!ret) {
+ lpass_mclk.clk_freq_in_hz = mclk_freq;
+
+ ret = audio_get_pinctrl(pdev, LPASS_MCLK);
+ if (ret)
+ dev_err(&pdev->dev, "%s: Parsing pinctrl %s failed\n",
+ __func__, "LPASS_MCLK");
+ ret = audio_get_pinctrl(pdev, LPASS_MCLK2);
+ if (ret)
+ dev_dbg(&pdev->dev, "%s: Parsing pinctrl %s failed\n",
+ __func__, "LPASS_MCLK2");
+ }
+
+ clk_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,audio-ref-clk-gpio", 0);
+ if (clk_gpio > 0) {
+ ret = gpio_request(clk_gpio, "EXT_CLK");
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Request ext clk gpio failed %d, err:%d\n",
+ clk_gpio, ret);
+ goto err;
+ }
+ if (of_property_read_bool(pdev->dev.of_node,
+ "qcom,node_has_rpm_clock")) {
+ audio_pmi_clk.gpio = clk_gpio;
+ } else
+ audio_ap_clk.gpio = clk_gpio;
+
+ }
+
+ ret = audio_get_pinctrl(pdev, AP_CLK2);
+ if (ret)
+ dev_dbg(&pdev->dev, "%s: Parsing pinctrl failed\n",
+ __func__);
+
+ clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
+ if (!clk_data)
+ goto err_gpio;
+
+ clk_data->clk_num = ARRAY_SIZE(audio_msm_hws);
+ clk_data->clks = devm_kzalloc(&pdev->dev,
+ clk_data->clk_num * sizeof(struct clk *),
+ GFP_KERNEL);
+ if (!clk_data->clks)
+ goto err_clk;
+
+ for (i = 0; i < ARRAY_SIZE(audio_msm_hws); i++) {
+ audio_clk = devm_clk_register(dev, audio_msm_hws[i]);
+ if (IS_ERR(audio_clk)) {
+ dev_err(&pdev->dev,
+ "%s: audio ref clock i = %d register failed\n",
+ __func__, i);
+ return PTR_ERR(audio_clk);
+ }
+ clk_data->clks[i] = audio_clk;
+ }
+
+ ret = of_clk_add_provider(pdev->dev.of_node,
+ of_clk_src_onecell_get, clk_data);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: audio ref clock register failed\n",
+ __func__);
+ goto err_gpio;
+ }
+
+ return 0;
+
+err_clk:
+ if (clk_data)
+ devm_kfree(&pdev->dev, clk_data->clks);
+ devm_kfree(&pdev->dev, clk_data);
+err_gpio:
+ gpio_free(clk_gpio);
+
+err:
+ return ret;
+}
+
+static int audio_ref_clk_remove(struct platform_device *pdev)
+{
+ struct pinctrl_info *pnctrl_info = &audio_ap_clk2.pnctrl_info;
+
+ if (audio_pmi_clk.gpio > 0)
+ gpio_free(audio_pmi_clk.gpio);
+ else if (audio_ap_clk.gpio > 0)
+ gpio_free(audio_ap_clk.gpio);
+
+ if (pnctrl_info->pinctrl) {
+ devm_pinctrl_put(pnctrl_info->pinctrl);
+ pnctrl_info->pinctrl = NULL;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id audio_ref_clk_match[] = {
+ {.compatible = "qcom,audio-ref-clk"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, audio_ref_clk_match);
+
+static struct platform_driver audio_ref_clk_driver = {
+ .driver = {
+ .name = "audio-ref-clk",
+ .owner = THIS_MODULE,
+ .of_match_table = audio_ref_clk_match,
+ },
+ .probe = audio_ref_clk_probe,
+ .remove = audio_ref_clk_remove,
+};
+
+static int __init audio_ref_clk_platform_init(void)
+{
+ return platform_driver_register(&audio_ref_clk_driver);
+}
+module_init(audio_ref_clk_platform_init);
+
+static void __exit audio_ref_clk_platform_exit(void)
+{
+ platform_driver_unregister(&audio_ref_clk_driver);
+}
+module_exit(audio_ref_clk_platform_exit);
+
+MODULE_DESCRIPTION("Audio Ref Up Clock module platform driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index b0bb89c8d9c2..1fdf81a3a45f 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -1879,6 +1879,7 @@ static void tavil_codec_override(struct snd_soc_codec *codec, int mode,
{
if (mode == CLS_AB || mode == CLS_AB_HIFI) {
switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
case SND_SOC_DAPM_POST_PMU:
if (!(snd_soc_read(codec,
WCD934X_CDC_RX2_RX_PATH_CTL) & 0x10) &&
@@ -2088,6 +2089,9 @@ static int tavil_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w,
}
switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ tavil_codec_override(codec, CLS_AB, event);
+ break;
case SND_SOC_DAPM_POST_PMU:
/*
* 5ms sleep is required after PA is enabled as per
@@ -2102,6 +2106,13 @@ static int tavil_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w,
lineout_mix_vol_reg,
0x10, 0x00);
break;
+ case SND_SOC_DAPM_POST_PMD:
+ /*
+ * 5ms sleep is required after PA is disabled as per
+ * HW requirement
+ */
+ usleep_range(5000, 5500);
+ tavil_codec_override(codec, CLS_AB, event);
default:
break;
};
@@ -7039,10 +7050,12 @@ static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = {
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("LINEOUT1 PA", WCD934X_ANA_LO_1_2, 7, 0, NULL, 0,
tavil_codec_enable_lineout_pa,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("LINEOUT2 PA", WCD934X_ANA_LO_1_2, 6, 0, NULL, 0,
tavil_codec_enable_lineout_pa,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("ANC EAR PA", WCD934X_ANA_EAR, 7, 0, NULL, 0,
tavil_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
@@ -8156,6 +8169,8 @@ static const struct tavil_reg_mask_val tavil_codec_reg_defaults[] = {
{WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
{WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
{WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
+ {WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
+ {WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
{WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
{WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
{WCD934X_CDC_COMPANDER8_CTL7, 0x1E, 0x18},
@@ -8189,6 +8204,8 @@ static const struct tavil_reg_mask_val tavil_codec_reg_init_1_1_val[] = {
{WCD934X_CDC_COMPANDER2_CTL7, 0x1E, 0x06},
{WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0xFF, 0x84},
{WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0xFF, 0x84},
+ {WCD934X_CDC_RX3_RX_PATH_SEC0, 0xFC, 0xF4},
+ {WCD934X_CDC_RX4_RX_PATH_SEC0, 0xFC, 0xF4},
};
static const struct tavil_cpr_reg_defaults cpr_defaults[] = {
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index 94a529acaff7..1df839333d09 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -398,7 +398,8 @@ static char const *ch_text[] = {"Two", "Three", "Four", "Five",
static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025",
"KHZ_16", "KHZ_22P05",
"KHZ_32", "KHZ_44P1", "KHZ_48",
- "KHZ_96", "KHZ_192", "KHZ_384"};
+ "KHZ_88P2", "KHZ_96", "KHZ_176P4",
+ "KHZ_192", "KHZ_352P8", "KHZ_384"};
static char const *ext_disp_sample_rate_text[] = {"KHZ_48", "KHZ_96",
"KHZ_192"};
static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four",
@@ -1031,12 +1032,21 @@ static int usb_audio_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
switch (usb_rx_cfg.sample_rate) {
case SAMPLING_RATE_384KHZ:
- sample_rate_val = 9;
+ sample_rate_val = 12;
+ break;
+ case SAMPLING_RATE_352P8KHZ:
+ sample_rate_val = 11;
break;
case SAMPLING_RATE_192KHZ:
- sample_rate_val = 8;
+ sample_rate_val = 10;
+ break;
+ case SAMPLING_RATE_176P4KHZ:
+ sample_rate_val = 9;
break;
case SAMPLING_RATE_96KHZ:
+ sample_rate_val = 8;
+ break;
+ case SAMPLING_RATE_88P2KHZ:
sample_rate_val = 7;
break;
case SAMPLING_RATE_48KHZ:
@@ -1073,15 +1083,24 @@ static int usb_audio_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
switch (ucontrol->value.integer.value[0]) {
- case 9:
+ case 12:
usb_rx_cfg.sample_rate = SAMPLING_RATE_384KHZ;
break;
- case 8:
+ case 11:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_352P8KHZ;
+ break;
+ case 10:
usb_rx_cfg.sample_rate = SAMPLING_RATE_192KHZ;
break;
- case 7:
+ case 9:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_176P4KHZ;
+ break;
+ case 8:
usb_rx_cfg.sample_rate = SAMPLING_RATE_96KHZ;
break;
+ case 7:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_88P2KHZ;
+ break;
case 6:
usb_rx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
break;
@@ -1191,12 +1210,21 @@ static int usb_audio_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
switch (usb_tx_cfg.sample_rate) {
case SAMPLING_RATE_384KHZ:
- sample_rate_val = 9;
+ sample_rate_val = 12;
+ break;
+ case SAMPLING_RATE_352P8KHZ:
+ sample_rate_val = 11;
break;
case SAMPLING_RATE_192KHZ:
- sample_rate_val = 8;
+ sample_rate_val = 10;
+ break;
+ case SAMPLING_RATE_176P4KHZ:
+ sample_rate_val = 9;
break;
case SAMPLING_RATE_96KHZ:
+ sample_rate_val = 8;
+ break;
+ case SAMPLING_RATE_88P2KHZ:
sample_rate_val = 7;
break;
case SAMPLING_RATE_48KHZ:
@@ -1235,15 +1263,24 @@ static int usb_audio_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
switch (ucontrol->value.integer.value[0]) {
- case 9:
+ case 12:
usb_tx_cfg.sample_rate = SAMPLING_RATE_384KHZ;
break;
- case 8:
+ case 11:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_352P8KHZ;
+ break;
+ case 10:
usb_tx_cfg.sample_rate = SAMPLING_RATE_192KHZ;
break;
- case 7:
+ case 9:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_176P4KHZ;
+ break;
+ case 8:
usb_tx_cfg.sample_rate = SAMPLING_RATE_96KHZ;
break;
+ case 7:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_88P2KHZ;
+ break;
case 6:
usb_tx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
break;
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 90371b8e27f4..d3c0850d8de2 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -55,6 +55,10 @@
#define DSP_NUM_OUTPUT_FRAME_BUFFERED 2
#define FLAC_BLK_SIZE_LIMIT 65535
+/* Timestamp mode payload offsets */
+#define TS_LSW_OFFSET 6
+#define TS_MSW_OFFSET 7
+
/* decoder parameter length */
#define DDP_DEC_MAX_NUM_PARAM 18
@@ -130,7 +134,9 @@ struct msm_compr_audio {
uint64_t received_total; /* bytes received from DSP */
uint64_t bytes_copied; /* to userspace */
uint64_t bytes_read; /* from DSP */
- uint32_t bytes_read_offset; /* bytes read offset*/
+ uint32_t bytes_read_offset; /* bytes read offset */
+
+ uint32_t ts_header_offset; /* holds the timestamp header offset */
int32_t first_buffer;
int32_t last_buffer;
@@ -380,19 +386,23 @@ static int msm_compr_read_buffer(struct msm_compr_audio *prtd)
return -EINVAL;
}
- buffer_length = prtd->codec_param.buffer.fragment_size;
+ buffer_length = prtd->codec_param.buffer.fragment_size -
+ prtd->ts_header_offset;
bytes_available = prtd->received_total - prtd->bytes_copied;
buffer_sent = prtd->bytes_read - prtd->bytes_copied;
- if (buffer_sent + buffer_length > prtd->buffer_size) {
+ if (buffer_sent + buffer_length + prtd->ts_header_offset
+ > prtd->buffer_size) {
pr_debug(" %s : Buffer is Full bytes_available: %llu\n",
__func__, bytes_available);
return 0;
}
memset(&param, 0x0, sizeof(struct audio_aio_read_param));
- param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset;
+ param.paddr = prtd->buffer_paddr + prtd->bytes_read_offset +
+ prtd->ts_header_offset;
param.len = buffer_length;
param.uid = buffer_length;
+ param.flags = prtd->codec_param.codec.flags;
pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n",
__func__, buffer_length, prtd->bytes_read);
@@ -423,6 +433,7 @@ static void compr_event_handler(uint32_t opcode,
uint32_t stream_index;
unsigned long flags;
uint64_t read_size;
+ uint32_t *buff_addr;
if (!prtd) {
pr_err("%s: prtd is NULL\n", __func__);
@@ -514,6 +525,23 @@ static void compr_event_handler(uint32_t opcode,
pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n",
prtd->byte_offset, payload[4]);
+
+ if (prtd->ts_header_offset) {
+ /* Update the header for received buffer */
+ buff_addr = prtd->buffer + prtd->byte_offset;
+ /* Write the length of the buffer */
+ *buff_addr = prtd->codec_param.buffer.fragment_size
+ - prtd->ts_header_offset;
+ buff_addr++;
+ /* Write the offset */
+ *buff_addr = prtd->ts_header_offset;
+ buff_addr++;
+ /* Write the TS LSW */
+ *buff_addr = payload[TS_LSW_OFFSET];
+ buff_addr++;
+ /* Write the TS MSW */
+ *buff_addr = payload[TS_MSW_OFFSET];
+ }
/* Always assume read_size is same as fragment_size */
read_size = prtd->codec_param.buffer.fragment_size;
prtd->byte_offset += read_size;
@@ -1214,7 +1242,7 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
pr_debug("%s: stream_id %d bits_per_sample %d\n",
__func__, ac->stream_id, bits_per_sample);
- ret = q6asm_open_read_v3(prtd->audio_client, FORMAT_LINEAR_PCM,
+ ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM,
bits_per_sample);
if (ret < 0) {
pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret);
@@ -1265,6 +1293,11 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
prtd->buffer_paddr = ac->port[dir].buf[0].phys;
prtd->buffer_size = runtime->fragments * runtime->fragment_size;
+ /* Bit-0 of flags represent timestamp mode */
+ if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG)
+ prtd->ts_header_offset = sizeof(struct snd_codec_metadata);
+ else
+ prtd->ts_header_offset = 0;
pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n",
__func__, prtd->sample_rate, prtd->num_channels,
@@ -3146,7 +3179,7 @@ static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int msm_compr_app_type_cfg_put(struct snd_kcontrol *kcontrol,
+static int msm_compr_playback_app_type_cfg_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
u64 fe_id = kcontrol->private_value;
@@ -3173,7 +3206,7 @@ static int msm_compr_app_type_cfg_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static int msm_compr_app_type_cfg_get(struct snd_kcontrol *kcontrol,
+static int msm_compr_playback_app_type_cfg_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
u64 fe_id = kcontrol->private_value;
@@ -3208,6 +3241,68 @@ done:
return ret;
}
+static int msm_compr_capture_app_type_cfg_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate = 48000;
+
+ pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bounds fe_id %llu\n",
+ __func__, fe_id);
+ return -EINVAL;
+ }
+
+ app_type = ucontrol->value.integer.value[0];
+ acdb_dev_id = ucontrol->value.integer.value[1];
+ if (ucontrol->value.integer.value[2] != 0)
+ sample_rate = ucontrol->value.integer.value[2];
+ pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n",
+ __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX);
+ msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type,
+ acdb_dev_id, sample_rate, SESSION_TYPE_TX);
+
+ return 0;
+}
+
+static int msm_compr_capture_app_type_cfg_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int ret = 0;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate;
+
+ pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bounds fe_id %llu\n",
+ __func__, fe_id);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_TX,
+ &app_type, &acdb_dev_id, &sample_rate);
+ if (ret < 0) {
+ pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ ucontrol->value.integer.value[0] = app_type;
+ ucontrol->value.integer.value[1] = acdb_dev_id;
+ ucontrol->value.integer.value[2] = sample_rate;
+ pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fe_id, SESSION_TYPE_TX,
+ app_type, acdb_dev_id, sample_rate);
+done:
+ return ret;
+}
+
static int msm_compr_channel_map_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -3595,7 +3690,8 @@ static int msm_compr_add_dec_runtime_params_control(
static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
{
- const char *mixer_ctl_name = "Audio Stream";
+ const char *playback_mixer_ctl_name = "Audio Stream";
+ const char *capture_mixer_ctl_name = "Audio Stream Capture";
const char *deviceNo = "NN";
const char *suffix = "App Type Cfg";
char *mixer_str = NULL;
@@ -3606,8 +3702,8 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
.name = "?",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = msm_compr_app_type_cfg_info,
- .put = msm_compr_app_type_cfg_put,
- .get = msm_compr_app_type_cfg_get,
+ .put = msm_compr_playback_app_type_cfg_put,
+ .get = msm_compr_playback_app_type_cfg_get,
.private_value = 0,
}
};
@@ -3618,11 +3714,15 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
}
pr_debug("%s: added new compr FE ctl with name %s, id %d, cpu dai %s, device no %d\n",
- __func__, rtd->dai_link->name, rtd->dai_link->be_id,
- rtd->dai_link->cpu_dai_name, rtd->pcm->device);
+ __func__, rtd->dai_link->name, rtd->dai_link->be_id,
+ rtd->dai_link->cpu_dai_name, rtd->pcm->device);
+ if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
+ ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo)
+ + 1 + strlen(suffix) + 1;
+ else
+ ctl_len = strlen(capture_mixer_ctl_name) + 1 + strlen(deviceNo)
+ + 1 + strlen(suffix) + 1;
- ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
- strlen(suffix) + 1;
mixer_str = kzalloc(ctl_len, GFP_KERNEL);
if (!mixer_str) {
@@ -3630,14 +3730,31 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd)
return 0;
}
- snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
- rtd->pcm->device, suffix);
+ if (rtd->compr->direction == SND_COMPRESS_PLAYBACK)
+ snprintf(mixer_str, ctl_len, "%s %d %s",
+ playback_mixer_ctl_name, rtd->pcm->device, suffix);
+ else
+ snprintf(mixer_str, ctl_len, "%s %d %s",
+ capture_mixer_ctl_name, rtd->pcm->device, suffix);
+
fe_app_type_cfg_control[0].name = mixer_str;
fe_app_type_cfg_control[0].private_value = rtd->dai_link->be_id;
+
+ if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
+ fe_app_type_cfg_control[0].put =
+ msm_compr_playback_app_type_cfg_put;
+ fe_app_type_cfg_control[0].get =
+ msm_compr_playback_app_type_cfg_get;
+ } else {
+ fe_app_type_cfg_control[0].put =
+ msm_compr_capture_app_type_cfg_put;
+ fe_app_type_cfg_control[0].get =
+ msm_compr_capture_app_type_cfg_get;
+ }
pr_debug("Registering new mixer ctl %s", mixer_str);
snd_soc_add_platform_controls(rtd->platform,
- fe_app_type_cfg_control,
- ARRAY_SIZE(fe_app_type_cfg_control));
+ fe_app_type_cfg_control,
+ ARRAY_SIZE(fe_app_type_cfg_control));
kfree(mixer_str);
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index c75f7214db1a..75dc7cf059e3 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -4595,7 +4595,7 @@ static ssize_t afe_debug_write(struct file *filp,
lbuf[cnt] = '\0';
- if (!strncmp(lb_str, "afe_loopback", 12)) {
+ if (!strcmp(lb_str, "afe_loopback")) {
rc = afe_get_parameters(lbuf, param, 3);
if (!rc) {
pr_info("%s: %lu %lu %lu\n", lb_str, param[0], param[1],
@@ -4624,7 +4624,7 @@ static ssize_t afe_debug_write(struct file *filp,
rc = -EINVAL;
}
- } else if (!strncmp(lb_str, "afe_loopback_gain", 17)) {
+ } else if (!strcmp(lb_str, "afe_loopback_gain")) {
rc = afe_get_parameters(lbuf, param, 2);
if (!rc) {
pr_info("%s: %s %lu %lu\n",
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index e3545405f61d..38c51eb32f4d 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1639,7 +1639,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
asm_token.token = data->token;
if (q6asm_get_flag_from_token(&asm_token, ASM_CMD_NO_WAIT_OFFSET)) {
pr_debug("%s: No wait command opcode[0x%x] cmd_opcode:%x\n",
- __func__, data->opcode, payload[0]);
+ __func__, data->opcode, payload ? payload[0] : 0);
wakeup_flag = 0;
}
@@ -1673,9 +1673,14 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
data->dest_port);
if ((data->opcode != ASM_DATA_EVENT_RENDERED_EOS) &&
(data->opcode != ASM_DATA_EVENT_EOS) &&
- (data->opcode != ASM_SESSION_EVENT_RX_UNDERFLOW))
+ (data->opcode != ASM_SESSION_EVENT_RX_UNDERFLOW)) {
+ if (payload == NULL) {
+ pr_err("%s: payload is null\n", __func__);
+ return -EINVAL;
+ }
dev_vdbg(ac->dev, "%s: Payload = [0x%x] status[0x%x] opcode 0x%x\n",
__func__, payload[0], payload[1], data->opcode);
+ }
if (data->opcode == APR_BASIC_RSP_RESULT) {
switch (payload[0]) {
case ASM_STREAM_CMD_SET_PP_PARAMS_V2:
@@ -2285,7 +2290,8 @@ static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr,
static int __q6asm_open_read(struct audio_client *ac,
uint32_t format, uint16_t bits_per_sample,
- uint32_t pcm_format_block_ver)
+ uint32_t pcm_format_block_ver,
+ bool ts_mode)
{
int rc = 0x00;
struct asm_stream_cmd_open_read_v3 open;
@@ -2329,11 +2335,21 @@ static int __q6asm_open_read(struct audio_client *ac,
case FORMAT_LINEAR_PCM:
open.mode_flags |= 0x00;
open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver);
+ if (ts_mode)
+ open.mode_flags |= ABSOLUTE_TIMESTAMP_ENABLE;
break;
case FORMAT_MPEG4_AAC:
open.mode_flags |= BUFFER_META_ENABLE;
open.enc_cfg_id = ASM_MEDIA_FMT_AAC_V2;
break;
+ case FORMAT_G711_ALAW_FS:
+ open.mode_flags |= BUFFER_META_ENABLE;
+ open.enc_cfg_id = ASM_MEDIA_FMT_G711_ALAW_FS;
+ break;
+ case FORMAT_G711_MLAW_FS:
+ open.mode_flags |= BUFFER_META_ENABLE;
+ open.enc_cfg_id = ASM_MEDIA_FMT_G711_MLAW_FS;
+ break;
case FORMAT_V13K:
open.mode_flags |= BUFFER_META_ENABLE;
open.enc_cfg_id = ASM_MEDIA_FMT_V13K_FS;
@@ -2391,14 +2407,16 @@ int q6asm_open_read(struct audio_client *ac,
uint32_t format)
{
return __q6asm_open_read(ac, format, 16,
- PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/);
+ PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/,
+ false/*ts_mode*/);
}
int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample)
{
return __q6asm_open_read(ac, format, bits_per_sample,
- PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/);
+ PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/,
+ false/*ts_mode*/);
}
/*
@@ -2412,7 +2430,8 @@ int q6asm_open_read_v3(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample)
{
return __q6asm_open_read(ac, format, bits_per_sample,
- PCM_MEDIA_FORMAT_V3/*media fmt block ver*/);
+ PCM_MEDIA_FORMAT_V3/*media fmt block ver*/,
+ false/*ts_mode*/);
}
EXPORT_SYMBOL(q6asm_open_read_v3);
@@ -2427,7 +2446,8 @@ int q6asm_open_read_v4(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample)
{
return __q6asm_open_read(ac, format, bits_per_sample,
- PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/);
+ PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/,
+ true/*ts_mode*/);
}
EXPORT_SYMBOL(q6asm_open_read_v4);
@@ -2857,6 +2877,11 @@ static int __q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format,
break;
case FORMAT_DSD:
open.dec_fmt_id = ASM_MEDIA_FMT_DSD;
+ case FORMAT_G711_ALAW_FS:
+ open.dec_fmt_id = ASM_MEDIA_FMT_G711_ALAW_FS;
+ break;
+ case FORMAT_G711_MLAW_FS:
+ open.dec_fmt_id = ASM_MEDIA_FMT_G711_MLAW_FS;
break;
default:
pr_err("%s: Invalid format 0x%x\n",
@@ -2873,6 +2898,12 @@ static int __q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format,
case FORMAT_MPEG4_AAC:
open.enc_cfg_id = ASM_MEDIA_FMT_AAC_V2;
break;
+ case FORMAT_G711_ALAW_FS:
+ open.enc_cfg_id = ASM_MEDIA_FMT_G711_ALAW_FS;
+ break;
+ case FORMAT_G711_MLAW_FS:
+ open.enc_cfg_id = ASM_MEDIA_FMT_G711_MLAW_FS;
+ break;
case FORMAT_V13K:
open.enc_cfg_id = ASM_MEDIA_FMT_V13K_FS;
break;
@@ -3540,6 +3571,57 @@ fail_cmd:
return rc;
}
+int q6asm_enc_cfg_blk_g711(struct audio_client *ac,
+ uint32_t frames_per_buf,
+ uint32_t sample_rate)
+{
+ struct asm_g711_enc_cfg_v2 enc_cfg;
+ int rc = 0;
+
+ pr_debug("%s: session[%d]frames[%d]SR[%d]\n",
+ __func__, ac->session, frames_per_buf,
+ sample_rate);
+
+ q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
+ atomic_set(&ac->cmd_state, -1);
+
+ enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+ enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
+ enc_cfg.encdec.param_size = sizeof(struct asm_g711_enc_cfg_v2) -
+ sizeof(struct asm_stream_cmd_set_encdec_param);
+ enc_cfg.encblk.frames_per_buf = frames_per_buf;
+ enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
+ sizeof(struct asm_enc_cfg_blk_param_v2);
+ enc_cfg.sample_rate = sample_rate;
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
+ if (rc < 0) {
+ pr_err("%s: Comamnd %d failed %d\n",
+ __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM, 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));
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return rc;
+}
+
int q6asm_set_encdec_chan_map(struct audio_client *ac,
uint32_t num_channels)
{
@@ -5424,6 +5506,75 @@ fail_cmd:
return rc;
}
+/*
+ * q6asm_media_format_block_g711 - sends g711 decoder configuration
+ * parameters
+ * @ac: Client session handle
+ * @cfg: Audio stream manager configuration parameters
+ * @stream_id: Stream id
+ */
+int q6asm_media_format_block_g711(struct audio_client *ac,
+ struct asm_g711_dec_cfg *cfg, int stream_id)
+{
+ struct asm_g711_dec_fmt_blk_v2 fmt;
+ int rc = 0;
+
+ if (!ac) {
+ pr_err("%s: audio client is null\n", __func__);
+ return -EINVAL;
+ }
+ if (!cfg) {
+ pr_err("%s: Invalid ASM config\n", __func__);
+ return -EINVAL;
+ }
+
+ if (stream_id <= 0) {
+ pr_err("%s: Invalid stream id\n", __func__);
+ return -EINVAL;
+ }
+
+ pr_debug("%s :session[%d]rate[%d]\n", __func__,
+ ac->session, cfg->sample_rate);
+
+ memset(&fmt, 0, sizeof(struct asm_g711_dec_fmt_blk_v2));
+
+ q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
+ atomic_set(&ac->cmd_state, -1);
+
+ fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
+ fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
+ sizeof(fmt.fmtblk);
+
+ fmt.sample_rate = cfg->sample_rate;
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+ if (rc < 0) {
+ pr_err("%s :Command media format update failed %d\n",
+ __func__, rc);
+ 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));
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return rc;
+}
+EXPORT_SYMBOL(q6asm_media_format_block_g711);
+
int q6asm_stream_media_format_block_vorbis(struct audio_client *ac,
struct asm_vorbis_cfg *cfg, int stream_id)
{
@@ -7150,7 +7301,11 @@ int q6asm_async_read(struct audio_client *ac,
lbuf_phys_addr = (param->paddr - 64);
dir = OUT;
} else {
- lbuf_phys_addr = param->paddr;
+ if (param->flags & COMPRESSED_TIMESTAMP_FLAG)
+ lbuf_phys_addr = param->paddr -
+ sizeof(struct snd_codec_metadata);
+ else
+ lbuf_phys_addr = param->paddr;
dir = OUT;
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 4c66eeaeeb03..b1980df07dce 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2623,8 +2623,7 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
dapm_mark_dirty(widgets[dir], "Route added");
}
- if (dapm->card->instantiated && path->connect)
- dapm_path_invalidate(path);
+ dapm_path_invalidate(path);
return 0;
err: