summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-11-26 17:46:55 -0700
committerLinux Build Service Account <lnxbuild@localhost>2016-11-26 17:46:56 -0700
commita6fff3c86ee7b4fa4e33384634f4ea73b44ffb23 (patch)
tree34deda2952363839768405ddc71d879ca6d9a970
parent9811ea8f33b639a3a2e11661be50c19f2fec9927 (diff)
parentb23cd82dba85b13ace45d0c638452f1b641039cd (diff)
Promotion of kernel.lnx.4.4-161126.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 1086894 I78770eea7fdd57f12d92ff40ed8043987e742024 msm: mdss: refine the calculation of tmds clock rate 1086976 Iae12fa648df17dddd48f3a71e94d06c2c3b03277 soc: qcom: socinfo: Change offset of image OEM attribute 1056661 If225dc4ec2c2e3eb8996f49f4fdf6acd31a50680 Revert "msm: kgsl: Enable limits management on A540v2" 1093546 I8f1cba6e1efa65ae41e674b14bd7598b4b521f05 soc: qcom: msm_bus: Set current index to default value 1092875 I53f89cf6b7c11f32c5e8e5a51a5986fa31424b92 qpnp-smb2: force UFP mode before shutdown 1084600 I53cd6ed709263669edbc34f096a21cddffcf4489 smb-lib: fix null ptr access while handling src change i 1081033 I6fc8323cbcf395a2c24e49e65cc7012709d031a2 input: synaptics_dsx: add checks of user input data 1086894 Ia3ea67cc7658098928a442460198b2dccc8ff8e1 msm: mdss: update vic info when powering on HDMI 1091972 I36ca125143cf9929fb0bd781990bdd8ab1dbeebf ARM: dts: msm: Add thermal mitigation properties to msmf 1091972 Ie564c181db61f6229479a49917cdb9e6c1887fc5 ARM: dts: msm: Add thermal sensor info for msmfalcon 1091566 Ic68cd12cc861d04e107b70e2b96200483f13da26 qpnp-smb2: add support to configure auto recharge 1072067 I7c6ab8bc0e88010eb221788cf8ce4c182e3128d9 ASoc: msm: qdsp6v2: Add support for compress capture 1060631 Icb48ac2624d489ff054dca3158f52c45cc85cce7 msm: camera: Enable secure camera feature 1087473 I09fbda8eb92c81acf24d0ff07ca9c040141680e1 msm: mdss: fix to handle multi-rect configuration in err 1082636 I3db0c20ac5fa47ed278f3d60368c406f472430c1 msm: crypto: fix issues on digest buf and copy_from_user 1090500 Ie592d06d2e09c2e263a2e9485a42eafb368e49cc include: clock: Add audio external clock of_index extrie 1084152 I48b5fc1c9e98994c8a7d92d462138cbacb246005 ASoC: wcd9335: Add dapm ignore suspend for codec dai Change-Id: I0cc98bd7e0978cccd6a24fd1ead5e80d66e76a30 CRs-Fixed: 1056661, 1086894, 1087473, 1081033, 1091566, 1086976, 1093546, 1092875, 1060631, 1072067, 1084152, 1084600, 1090500, 1091972, 1082636
-rw-r--r--Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt8
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi182
-rw-r--r--drivers/crypto/msm/qcedev.c120
-rw-r--r--drivers/gpu/msm/adreno-gpulist.h2
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c7
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c722
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_smmu_api.h59
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c34
-rw-r--r--drivers/power/qcom-charger/smb-lib.c5
-rw-r--r--drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c2
-rw-r--r--drivers/soc/qcom/socinfo.c11
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.c142
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_panel.c54
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_panel.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c110
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_util.c29
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_util.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c51
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c11
-rw-r--r--include/dt-bindings/clock/audio-ext-clk.h10
-rw-r--r--sound/soc/codecs/wcd9335.c1
-rw-r--r--sound/soc/msm/msm-dai-fe.c57
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c470
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c300
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h7
26 files changed, 2097 insertions, 302 deletions
diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
index 9d8670c7594b..382587ea5922 100644
--- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
+++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
@@ -138,6 +138,14 @@ Charger specific properties:
then charge inhibit will be disabled by default.
Allowed values are: 50, 100, 200, 300.
+- qcom,auto-recharge-soc
+ Usage: optional
+ Value type: <empty>
+ Definition: Specifies if automatic recharge needs to be based off battery
+ SOC. If this property is not specified, then auto recharge will
+ be based off battery voltage. For both SOC and battery voltage,
+ charger receives the signal from FG to resume charging.
+
=============================================
Second Level Nodes - SMB2 Charger Peripherals
=============================================
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index f85a40007d3f..ed8bee03b4d0 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -47,6 +47,7 @@
compatible = "arm,armv8";
reg = <0x0 0x0>;
enable-method = "psci";
+ qcom,limits-info = <&mitigation_profile0>;
};
CPU1: cpu@1 {
@@ -54,6 +55,7 @@
compatible = "arm,armv8";
reg = <0x0 0x1>;
enable-method = "psci";
+ qcom,limits-info = <&mitigation_profile0>;
};
CPU2: cpu@2 {
@@ -61,6 +63,7 @@
compatible = "arm,armv8";
reg = <0x0 0x2>;
enable-method = "psci";
+ qcom,limits-info = <&mitigation_profile0>;
};
CPU3: cpu@3 {
@@ -68,6 +71,7 @@
compatible = "arm,armv8";
reg = <0x0 0x3>;
enable-method = "psci";
+ qcom,limits-info = <&mitigation_profile0>;
};
CPU4: cpu@100 {
@@ -75,6 +79,7 @@
compatible = "arm,armv8";
reg = <0x0 0x100>;
enable-method = "psci";
+ qcom,limits-info = <&mitigation_profile1>;
};
CPU5: cpu@101 {
@@ -82,6 +87,7 @@
compatible = "arm,armv8";
reg = <0x0 0x101>;
enable-method = "psci";
+ qcom,limits-info = <&mitigation_profile2>;
};
CPU6: cpu@102 {
@@ -89,6 +95,7 @@
compatible = "arm,armv8";
reg = <0x0 0x102>;
enable-method = "psci";
+ qcom,limits-info = <&mitigation_profile3>;
};
CPU7: cpu@103 {
@@ -96,6 +103,7 @@
compatible = "arm,armv8";
reg = <0x0 0x103>;
enable-method = "psci";
+ qcom,limits-info = <&mitigation_profile4>;
};
cpu-map {
@@ -358,6 +366,180 @@
clock-names = "core", "iface";
};
+ qcom,sensor-information {
+ compatible = "qcom,sensor-information";
+ sensor_information0: qcom,sensor-information-0 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor0";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information1: qcom,sensor-information-1 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor1";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information2: qcom,sensor-information-2 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor2";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information3: qcom,sensor-information-3 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor3";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information4: qcom,sensor-information-4 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor4";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information5: qcom,sensor-information-5 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor5";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information6: qcom,sensor-information-6 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor6";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information7: qcom,sensor-information-7 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor7";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information8: qcom,sensor-information-8 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor8";
+ qcom,scaling-factor = <10>;
+ qcom,alias-name = "gpu";
+ };
+ sensor_information9: qcom,sensor-information-9 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor9";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information10: qcom,sensor-information-10 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor10";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information11: qcom,sensor-information-11 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor11";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information12: qcom,sensor-information-12 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor12";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information13: qcom,sensor-information-13 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor13";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information14: qcom,sensor-information-14 {
+ qcom,sensor-type = "alarm";
+ qcom,sensor-name = "pmfalcon_tz";
+ qcom,scaling-factor = <1000>;
+ };
+ sensor_information15: qcom,sensor-information-15 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "msm_therm";
+ };
+ sensor_information16: qcom,sensor-information-16 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "xo_therm";
+ };
+ sensor_information17: qcom,sensor-information-17 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "pa_therm0";
+ };
+ sensor_information18: qcom,sensor-information-18 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "pa_therm1";
+ };
+ sensor_information19: qcom,sensor-information-19 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "quiet_therm";
+ };
+ sensor_information20: qcom,sensor-information-20 {
+ qcom,sensor-type = "llm";
+ qcom,sensor-name = "limits_sensor-00";
+ };
+ sensor_information21: qcom,sensor-information-21 {
+ qcom,sensor-type = "llm";
+ qcom,sensor-name = "limits_sensor-01";
+ };
+ };
+
+ mitigation_profile0: qcom,limit_info-0 {
+ qcom,temperature-sensor = <&sensor_information1>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile1: qcom,limit_info-1 {
+ qcom,temperature-sensor = <&sensor_information3>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile2: qcom,limit_info-2 {
+ qcom,temperature-sensor = <&sensor_information4>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile3: qcom,limit_info-3 {
+ qcom,temperature-sensor = <&sensor_information5>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile4: qcom,limit_info-4 {
+ qcom,temperature-sensor = <&sensor_information6>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ qcom,msm-thermal {
+ compatible = "qcom,msm-thermal";
+ qcom,sensor-id = <1>;
+ qcom,poll-ms = <100>;
+ qcom,therm-reset-temp = <115>;
+ qcom,core-limit-temp = <70>;
+ qcom,core-temp-hysteresis = <10>;
+ qcom,hotplug-temp = <105>;
+ qcom,hotplug-temp-hysteresis = <20>;
+ qcom,online-hotplug-core;
+ qcom,synchronous-cluster-id = <0 1>;
+ qcom,synchronous-cluster-map = <0 4 &CPU0 &CPU1 &CPU2 &CPU3>,
+ <1 4 &CPU4 &CPU5 &CPU6 &CPU7>;
+
+ qcom,vdd-restriction-temp = <5>;
+ qcom,vdd-restriction-temp-hysteresis = <10>;
+
+ vdd-dig-supply = <&pm2falcon_s3_floor_level>;
+ vdd-gfx-supply = <&gfx_vreg_corner>;
+
+ qcom,vdd-dig-rstr{
+ qcom,vdd-rstr-reg = "vdd-dig";
+ qcom,levels = <RPM_SMD_REGULATOR_LEVEL_NOM
+ RPM_SMD_REGULATOR_LEVEL_TURBO
+ RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,min-level = <RPM_SMD_REGULATOR_LEVEL_NONE>;
+ };
+
+ qcom,vdd-gfx-rstr{
+ qcom,vdd-rstr-reg = "vdd-gfx";
+ qcom,levels = <5 6 6>; /* Nominal, Turbo, Turbo */
+ qcom,min-level = <1>; /* No Request */
+ };
+
+ msm_thermal_freq: qcom,vdd-apps-rstr{
+ qcom,vdd-rstr-reg = "vdd-apps";
+ qcom,levels = <1248000>;
+ qcom,freq-req;
+ };
+ };
+
uartblsp2dm1: serial@0c1b0000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0xc1b0000 0x1000>;
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index e2099c4e7877..433e4783d1d1 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -603,7 +603,7 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
while (len > 0) {
user_src =
(void __user *)qcedev_areq->sha_op_req.data[i].vaddr;
- if (user_src && __copy_from_user(k_src,
+ if (user_src && copy_from_user(k_src,
(void __user *)user_src,
qcedev_areq->sha_op_req.data[i].len))
return -EFAULT;
@@ -639,7 +639,7 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
/* Copy data from user src(s) */
user_src = (void __user *)qcedev_areq->sha_op_req.data[0].vaddr;
- if (user_src && __copy_from_user(k_src,
+ if (user_src && copy_from_user(k_src,
(void __user *)user_src,
qcedev_areq->sha_op_req.data[0].len)) {
kzfree(k_buf_src);
@@ -648,7 +648,7 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq,
k_src += qcedev_areq->sha_op_req.data[0].len;
for (i = 1; i < qcedev_areq->sha_op_req.entries; i++) {
user_src = (void __user *)qcedev_areq->sha_op_req.data[i].vaddr;
- if (user_src && __copy_from_user(k_src,
+ if (user_src && copy_from_user(k_src,
(void __user *)user_src,
qcedev_areq->sha_op_req.data[i].len)) {
kzfree(k_buf_src);
@@ -702,13 +702,6 @@ static int qcedev_sha_update(struct qcedev_async_req *qcedev_areq,
return -EINVAL;
}
- /* verify address src(s) */
- for (i = 0; i < qcedev_areq->sha_op_req.entries; i++)
- if (!access_ok(VERIFY_READ,
- (void __user *)qcedev_areq->sha_op_req.data[i].vaddr,
- qcedev_areq->sha_op_req.data[i].len))
- return -EFAULT;
-
if (qcedev_areq->sha_op_req.data_len > QCE_MAX_OPER_DATA) {
struct qcedev_sha_op_req *saved_req;
@@ -868,19 +861,7 @@ static int qcedev_hash_cmac(struct qcedev_async_req *qcedev_areq,
total = qcedev_areq->sha_op_req.data_len;
- /* verify address src(s) */
- for (i = 0; i < qcedev_areq->sha_op_req.entries; i++)
- if (!access_ok(VERIFY_READ,
- (void __user *)qcedev_areq->sha_op_req.data[i].vaddr,
- qcedev_areq->sha_op_req.data[i].len))
- return -EFAULT;
-
- /* Verify Source Address */
- if (!access_ok(VERIFY_READ,
- (void __user *)qcedev_areq->sha_op_req.authkey,
- qcedev_areq->sha_op_req.authklen))
- return -EFAULT;
- if (__copy_from_user(&handle->sha_ctxt.authkey[0],
+ if (copy_from_user(&handle->sha_ctxt.authkey[0],
(void __user *)qcedev_areq->sha_op_req.authkey,
qcedev_areq->sha_op_req.authklen))
return -EFAULT;
@@ -900,7 +881,7 @@ static int qcedev_hash_cmac(struct qcedev_async_req *qcedev_areq,
for (i = 0; i < qcedev_areq->sha_op_req.entries; i++) {
user_src =
(void __user *)qcedev_areq->sha_op_req.data[i].vaddr;
- if (user_src && __copy_from_user(k_src, (void __user *)user_src,
+ if (user_src && copy_from_user(k_src, (void __user *)user_src,
qcedev_areq->sha_op_req.data[i].len)) {
kzfree(k_buf_src);
return -EFAULT;
@@ -928,12 +909,7 @@ static int qcedev_set_hmac_auth_key(struct qcedev_async_req *areq,
if (areq->sha_op_req.authklen <= QCEDEV_MAX_KEY_SIZE) {
qcedev_sha_init(areq, handle);
- /* Verify Source Address */
- if (!access_ok(VERIFY_READ,
- (void __user *)areq->sha_op_req.authkey,
- areq->sha_op_req.authklen))
- return -EFAULT;
- if (__copy_from_user(&handle->sha_ctxt.authkey[0],
+ if (copy_from_user(&handle->sha_ctxt.authkey[0],
(void __user *)areq->sha_op_req.authkey,
areq->sha_op_req.authklen))
return -EFAULT;
@@ -1146,7 +1122,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
byteoffset = areq->cipher_op_req.byteoffset;
user_src = (void __user *)areq->cipher_op_req.vbuf.src[0].vaddr;
- if (user_src && __copy_from_user((k_align_src + byteoffset),
+ if (user_src && copy_from_user((k_align_src + byteoffset),
(void __user *)user_src,
areq->cipher_op_req.vbuf.src[0].len))
return -EFAULT;
@@ -1156,7 +1132,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
for (i = 1; i < areq->cipher_op_req.entries; i++) {
user_src =
(void __user *)areq->cipher_op_req.vbuf.src[i].vaddr;
- if (user_src && __copy_from_user(k_align_src,
+ if (user_src && copy_from_user(k_align_src,
(void __user *)user_src,
areq->cipher_op_req.vbuf.src[i].len)) {
return -EFAULT;
@@ -1188,7 +1164,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
while (creq->data_len > 0) {
if (creq->vbuf.dst[dst_i].len <= creq->data_len) {
- if (err == 0 && __copy_to_user(
+ if (err == 0 && copy_to_user(
(void __user *)creq->vbuf.dst[dst_i].vaddr,
(k_align_dst + byteoffset),
creq->vbuf.dst[dst_i].len))
@@ -1199,7 +1175,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
creq->data_len -= creq->vbuf.dst[dst_i].len;
dst_i++;
} else {
- if (err == 0 && __copy_to_user(
+ if (err == 0 && copy_to_user(
(void __user *)creq->vbuf.dst[dst_i].vaddr,
(k_align_dst + byteoffset),
creq->data_len))
@@ -1531,36 +1507,6 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
__func__, total, req->data_len);
goto error;
}
- /* Verify Source Address's */
- for (i = 0, total = 0; i < req->entries; i++) {
- if (total < req->data_len) {
- if (!access_ok(VERIFY_READ,
- (void __user *)req->vbuf.src[i].vaddr,
- req->vbuf.src[i].len)) {
- pr_err("%s:SRC RD_VERIFY err %d=0x%lx\n",
- __func__, i, (uintptr_t)
- req->vbuf.src[i].vaddr);
- goto error;
- }
- total += req->vbuf.src[i].len;
- }
- }
-
- /* Verify Destination Address's */
- for (i = 0, total = 0; i < QCEDEV_MAX_BUFFERS; i++) {
- if ((req->vbuf.dst[i].vaddr != 0) &&
- (total < req->data_len)) {
- if (!access_ok(VERIFY_WRITE,
- (void __user *)req->vbuf.dst[i].vaddr,
- req->vbuf.dst[i].len)) {
- pr_err("%s:DST WR_VERIFY err %d=0x%lx\n",
- __func__, i, (uintptr_t)
- req->vbuf.dst[i].vaddr);
- goto error;
- }
- total += req->vbuf.dst[i].len;
- }
- }
return 0;
error:
return -EINVAL;
@@ -1656,11 +1602,7 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
switch (cmd) {
case QCEDEV_IOCTL_ENC_REQ:
case QCEDEV_IOCTL_DEC_REQ:
- if (!access_ok(VERIFY_WRITE, (void __user *)arg,
- sizeof(struct qcedev_cipher_op_req)))
- return -EFAULT;
-
- if (__copy_from_user(&qcedev_areq.cipher_op_req,
+ if (copy_from_user(&qcedev_areq.cipher_op_req,
(void __user *)arg,
sizeof(struct qcedev_cipher_op_req)))
return -EFAULT;
@@ -1673,20 +1615,17 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle);
if (err)
return err;
- if (__copy_to_user((void __user *)arg,
+ if (copy_to_user((void __user *)arg,
&qcedev_areq.cipher_op_req,
sizeof(struct qcedev_cipher_op_req)))
- return -EFAULT;
+ return -EFAULT;
break;
case QCEDEV_IOCTL_SHA_INIT_REQ:
{
struct scatterlist sg_src;
- if (!access_ok(VERIFY_WRITE, (void __user *)arg,
- sizeof(struct qcedev_sha_op_req)))
- return -EFAULT;
- if (__copy_from_user(&qcedev_areq.sha_op_req,
+ if (copy_from_user(&qcedev_areq.sha_op_req,
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1696,9 +1635,9 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
err = qcedev_hash_init(&qcedev_areq, handle, &sg_src);
if (err)
return err;
- if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
+ if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
- return -EFAULT;
+ return -EFAULT;
}
handle->sha_ctxt.init_done = true;
break;
@@ -1708,11 +1647,8 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case QCEDEV_IOCTL_SHA_UPDATE_REQ:
{
struct scatterlist sg_src;
- if (!access_ok(VERIFY_WRITE, (void __user *)arg,
- sizeof(struct qcedev_sha_op_req)))
- return -EFAULT;
- if (__copy_from_user(&qcedev_areq.sha_op_req,
+ if (copy_from_user(&qcedev_areq.sha_op_req,
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1734,10 +1670,15 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
return err;
}
+ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
+ pr_err("Invalid sha_ctxt.diglen %d\n",
+ handle->sha_ctxt.diglen);
+ return -EINVAL;
+ }
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
- if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
+ if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
}
@@ -1749,11 +1690,7 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
pr_err("%s Init was not called\n", __func__);
return -EINVAL;
}
- if (!access_ok(VERIFY_WRITE, (void __user *)arg,
- sizeof(struct qcedev_sha_op_req)))
- return -EFAULT;
-
- if (__copy_from_user(&qcedev_areq.sha_op_req,
+ if (copy_from_user(&qcedev_areq.sha_op_req,
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1767,7 +1704,7 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
- if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
+ if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
handle->sha_ctxt.init_done = false;
@@ -1776,11 +1713,8 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case QCEDEV_IOCTL_GET_SHA_REQ:
{
struct scatterlist sg_src;
- if (!access_ok(VERIFY_WRITE, (void __user *)arg,
- sizeof(struct qcedev_sha_op_req)))
- return -EFAULT;
- if (__copy_from_user(&qcedev_areq.sha_op_req,
+ if (copy_from_user(&qcedev_areq.sha_op_req,
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1798,7 +1732,7 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
- if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
+ if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
}
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h
index d07e6b36dc8f..e6163384f9c1 100644
--- a/drivers/gpu/msm/adreno-gpulist.h
+++ b/drivers/gpu/msm/adreno-gpulist.h
@@ -269,7 +269,7 @@ static const struct adreno_gpu_core adreno_gpulist[] = {
.patchid = ANY_ID,
.features = ADRENO_PREEMPTION | ADRENO_64BIT |
ADRENO_CONTENT_PROTECTION |
- ADRENO_GPMU | ADRENO_SPTP_PC | ADRENO_LM,
+ ADRENO_GPMU | ADRENO_SPTP_PC,
.pm4fw_name = "a530_pm4.fw",
.pfpfw_name = "a530_pfp.fw",
.zap_name = "a540_zap",
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 2282fe005bc7..f001706236ab 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
@@ -1606,6 +1606,13 @@ 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)
{
+ 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;
+ }
+
memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
(const void *)buf,
count);
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
index feede3a14e07..d6b32036f31c 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/dma-buf.h>
#include <asm/dma-iommu.h>
+#include <asm/cacheflush.h>
#include <linux/dma-direction.h>
#include <linux/dma-attrs.h>
#include <linux/of_platform.h>
@@ -23,6 +24,8 @@
#include <linux/dma-mapping.h>
#include <linux/msm_dma_iommu_mapping.h>
#include <linux/workqueue.h>
+#include <soc/qcom/scm.h>
+#include <soc/qcom/secure_buffer.h>
#include "cam_smmu_api.h"
#define SCRATCH_ALLOC_START SZ_128K
@@ -35,10 +38,15 @@
#define COOKIE_MASK ((1<<COOKIE_SIZE)-1)
#define HANDLE_INIT (-1)
#define CAM_SMMU_CB_MAX 2
+#define CAM_SMMU_SID_MAX 4
+
#define GET_SMMU_HDL(x, y) (((x) << COOKIE_SIZE) | ((y) & COOKIE_MASK))
#define GET_SMMU_TABLE_IDX(x) (((x) >> COOKIE_SIZE) & COOKIE_MASK)
+#define CAMERA_DEVICE_ID 0x16
+#define SECURE_SYSCALL_ID 0x18
+
#ifdef CONFIG_CAM_SMMU_DBG
#define CDBG(fmt, args...) pr_err(fmt, ##args)
#else
@@ -104,6 +112,8 @@ struct cam_context_bank_info {
int, void*);
void *token[CAM_SMMU_CB_MAX];
int cb_count;
+ int ref_cnt;
+ int sids[CAM_SMMU_SID_MAX];
};
struct cam_iommu_cb_set {
@@ -136,6 +146,17 @@ struct cam_dma_buff_info {
size_t phys_len;
};
+struct cam_sec_buff_info {
+ struct ion_handle *i_hdl;
+ struct ion_client *i_client;
+ enum dma_data_direction dir;
+ int ref_count;
+ dma_addr_t paddr;
+ struct list_head list;
+ int ion_fd;
+ size_t len;
+};
+
static struct cam_iommu_cb_set iommu_cb_set;
static enum dma_data_direction cam_smmu_translate_dir(
@@ -151,6 +172,9 @@ static int cam_smmu_create_add_handle_in_table(char *name,
static struct cam_dma_buff_info *cam_smmu_find_mapping_by_ion_index(int idx,
int ion_fd);
+static struct cam_sec_buff_info *cam_smmu_find_mapping_by_sec_buf_idx(int idx,
+ int ion_fd);
+
static int cam_smmu_init_scratch_map(struct scratch_mapping *scratch_map,
dma_addr_t base, size_t size,
int order);
@@ -477,10 +501,14 @@ void cam_smmu_reset_iommu_table(enum cam_smmu_init_dir ops)
iommu_cb_set.cb_info[i].state = CAM_SMMU_DETACH;
iommu_cb_set.cb_info[i].dev = NULL;
iommu_cb_set.cb_info[i].cb_count = 0;
+ iommu_cb_set.cb_info[i].ref_cnt = 0;
for (j = 0; j < CAM_SMMU_CB_MAX; j++) {
iommu_cb_set.cb_info[i].token[j] = NULL;
iommu_cb_set.cb_info[i].handler[j] = NULL;
}
+ for (j = 0; j < CAM_SMMU_SID_MAX; j++)
+ iommu_cb_set.cb_info[i].sids[j] = -1;
+
if (ops == CAM_SMMU_TABLE_INIT)
mutex_init(&iommu_cb_set.cb_info[i].lock);
else
@@ -549,6 +577,8 @@ static int cam_smmu_create_add_handle_in_table(char *name,
pr_err("Error: %s already got handle 0x%x\n",
name,
iommu_cb_set.cb_info[i].handle);
+ *hdl = iommu_cb_set.cb_info[i].handle;
+ iommu_cb_set.cb_info[i].ref_cnt++;
mutex_unlock(&iommu_cb_set.cb_info[i].lock);
return -EINVAL;
}
@@ -561,6 +591,7 @@ static int cam_smmu_create_add_handle_in_table(char *name,
/* put handle in the table */
iommu_cb_set.cb_info[i].handle = handle;
iommu_cb_set.cb_info[i].cb_count = 0;
+ iommu_cb_set.cb_info[i].ref_cnt++;
*hdl = handle;
CDBG("%s creates handle 0x%x\n", name, handle);
mutex_unlock(&iommu_cb_set.cb_info[i].lock);
@@ -698,6 +729,23 @@ static struct cam_dma_buff_info *cam_smmu_find_mapping_by_ion_index(int idx,
return NULL;
}
+static struct cam_sec_buff_info *cam_smmu_find_mapping_by_sec_buf_idx(int idx,
+ int ion_fd)
+{
+ struct cam_sec_buff_info *mapping;
+
+ list_for_each_entry(mapping, &iommu_cb_set.cb_info[idx].smmu_buf_list,
+ list) {
+ if (mapping->ion_fd == ion_fd) {
+ CDBG("[sec_cam] find ion_fd %d\n", ion_fd);
+ return mapping;
+ }
+ }
+ pr_err("Error: Cannot find fd %d by index %d\n",
+ ion_fd, idx);
+ return NULL;
+}
+
static void cam_smmu_clean_buffer_list(int idx)
{
int ret;
@@ -754,6 +802,148 @@ static int cam_smmu_attach(int idx)
return ret;
}
+static int cam_smmu_send_syscall_cpp_intf(int vmid, int idx)
+{
+ int rc = 0;
+ struct scm_desc desc = {0};
+ struct cam_context_bank_info *cb = &iommu_cb_set.cb_info[idx];
+ uint32_t sid_info;
+
+
+ sid_info = cb->sids[0]; /* CPP SID */
+
+ desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL);
+ desc.args[0] = CAMERA_DEVICE_ID;
+ desc.args[1] = SCM_BUFFER_PHYS(&sid_info);
+ desc.args[2] = sizeof(uint32_t);
+ desc.args[3] = vmid;
+ /*
+ * Syscall to hypervisor to switch CPP SID's
+ * between secure and non-secure contexts
+ */
+ dmac_flush_range(&sid_info, &sid_info + 1);
+ if (scm_call2(SCM_SIP_FNID(SCM_SVC_MP, SECURE_SYSCALL_ID),
+ &desc)){
+ pr_err("call to hypervisor failed\n");
+ return -EINVAL;
+ }
+ return rc;
+}
+
+static int cam_smmu_send_syscall_pix_intf(int vmid, int idx)
+{
+ int rc = 0;
+ struct scm_desc desc = {0};
+ uint32_t *sid_info = NULL;
+ struct cam_context_bank_info *cb = &iommu_cb_set.cb_info[idx];
+
+ sid_info = kzalloc(sizeof(uint32_t) * 2, GFP_KERNEL);
+ if (!sid_info)
+ return -ENOMEM;
+
+ sid_info[0] = cb->sids[0]; /* VFE 0 Image SID */
+ sid_info[1] = cb->sids[2]; /* VFE 1 Image SID */
+
+ desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL);
+ desc.args[0] = CAMERA_DEVICE_ID;
+ desc.args[1] = SCM_BUFFER_PHYS(sid_info);
+ desc.args[2] = sizeof(uint32_t) * 2;
+ desc.args[3] = vmid;
+ /*
+ * Syscall to hypervisor to switch VFE SID's
+ * between secure and non-secure contexts
+ */
+ dmac_flush_range(sid_info, sid_info + 2);
+ if (scm_call2(SCM_SIP_FNID(SCM_SVC_MP, SECURE_SYSCALL_ID),
+ &desc)){
+ pr_err("call to hypervisor failed\n");
+ kfree(sid_info);
+ return -EINVAL;
+ }
+
+ kfree(sid_info);
+ return rc;
+}
+
+static int cam_smmu_detach_device(int idx)
+{
+ struct cam_context_bank_info *cb = &iommu_cb_set.cb_info[idx];
+
+ /* detach the mapping to device */
+ arm_iommu_detach_device(cb->dev);
+ iommu_cb_set.cb_info[idx].state = CAM_SMMU_DETACH;
+ return 0;
+}
+
+static int cam_smmu_attach_sec_cpp(int idx)
+{
+ /*
+ * When switching to secure, detach CPP NS, do scm call
+ * with CPP SID and no need of attach again, because
+ * all cpp sids are shared in SCM call. so no need of
+ * attach again.
+ */
+
+ if (cam_smmu_send_syscall_cpp_intf(VMID_CP_CAMERA, idx)) {
+ pr_err("error: syscall failed\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cam_smmu_detach_sec_cpp(int idx)
+{
+ /*
+ * When exiting secure, do scm call to attach
+ * with CPP SID in NS mode.
+ */
+ if (cam_smmu_send_syscall_cpp_intf(VMID_HLOS, idx)) {
+ pr_err("error: syscall failed\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cam_smmu_attach_sec_vfe_ns_stats(int idx)
+{
+ /*
+ *When switching to secure, for secure pixel and non-secure stats
+ *localizing scm/attach of non-secure SID's in attach secure
+ */
+ if (cam_smmu_send_syscall_pix_intf(VMID_CP_CAMERA, idx)) {
+ pr_err("error: syscall failed\n");
+ return -EINVAL;
+ }
+
+ if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) {
+ if (cam_smmu_attach(idx)) {
+ pr_err("error: failed to attach\n");
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int cam_smmu_detach_sec_vfe_ns_stats(int idx)
+{
+ /*
+ *While exiting from secure mode for secure pixel and non-secure stats,
+ *localizing detach/scm of non-secure SID's to detach secure
+ */
+ if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_DETACH) {
+ if (cam_smmu_detach_device(idx) < 0) {
+ pr_err("Error: ARM IOMMU detach failed\n");
+ return -ENODEV;
+ }
+ }
+
+ if (cam_smmu_send_syscall_pix_intf(VMID_HLOS, idx)) {
+ pr_err("error: syscall failed\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd,
enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr,
size_t *len_ptr)
@@ -805,7 +995,7 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd,
} else {
rc = -EINVAL;
pr_err("Error: table sgl is null\n");
- goto err_unmap_sg;
+ goto err_map_addr;
}
/* fill up mapping_info */
@@ -813,7 +1003,7 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd,
if (!mapping_info) {
pr_err("Error: No enough space!\n");
rc = -ENOSPC;
- goto err_unmap_sg;
+ goto err_map_addr;
}
mapping_info->ion_fd = ion_fd;
mapping_info->buf = buf;
@@ -831,7 +1021,7 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd,
if (!*paddr_ptr || !*len_ptr) {
pr_err("Error: Space Allocation failed!\n");
rc = -ENOSPC;
- goto err_unmap_sg;
+ goto err_mapping_info;
}
CDBG("ion_fd = %d, dev = %pK, paddr= %pK, len = %u\n", ion_fd,
(void *)iommu_cb_set.cb_info[idx].dev,
@@ -841,6 +1031,12 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd,
list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_list);
return 0;
+err_mapping_info:
+ kzfree(mapping_info);
+err_map_addr:
+ msm_dma_unmap_sg(iommu_cb_set.cb_info[idx].dev,
+ table->sgl, table->nents,
+ dma_dir, buf);
err_unmap_sg:
dma_buf_unmap_attachment(attach, table, dma_dir);
err_detach:
@@ -851,6 +1047,98 @@ err_out:
return rc;
}
+static int cam_smmu_map_secure_buffer_and_add_to_list(int idx,
+ struct dma_buf *buf,
+ enum dma_data_direction dma_dir, dma_addr_t *paddr_ptr,
+ size_t *len_ptr)
+{
+ int rc = -1;
+ struct cam_dma_buff_info *mapping_info;
+ struct dma_buf_attachment *attach = NULL;
+ struct sg_table *table = NULL;
+
+ attach = dma_buf_attach(buf, iommu_cb_set.cb_info[idx].dev);
+ if (IS_ERR_OR_NULL(attach)) {
+ rc = PTR_ERR(attach);
+ pr_err("Error: dma buf attach failed\n");
+ goto err_put;
+ }
+
+ table = dma_buf_map_attachment(attach, dma_dir);
+ if (IS_ERR_OR_NULL(table)) {
+ rc = PTR_ERR(table);
+ pr_err("Error: dma buf map attachment failed\n");
+ goto err_detach;
+ }
+
+ rc = msm_dma_map_sg_lazy(iommu_cb_set.cb_info[idx].dev, table->sgl,
+ table->nents, dma_dir, buf);
+ if (!rc) {
+ pr_err("Error: msm_dma_map_sg_lazy failed\n");
+ goto err_unmap_sg;
+ }
+
+ if (table->sgl) {
+ CDBG("DMA buf: %p, device: %p, attach: %p, table: %p\n",
+ (void *)buf,
+ (void *)iommu_cb_set.cb_info[idx].dev,
+ (void *)attach, (void *)table);
+ CDBG("table sgl: %p, rc: %d, dma_address: 0x%x\n",
+ (void *)table->sgl, rc,
+ (unsigned int)table->sgl->dma_address);
+ } else {
+ rc = -EINVAL;
+ pr_err("Error: table sgl is null\n");
+ goto err_map_addr;
+ }
+
+ /* fill up mapping_info */
+ mapping_info = kzalloc(sizeof(struct cam_dma_buff_info), GFP_KERNEL);
+ if (!mapping_info) {
+ rc = -ENOSPC;
+ goto err_map_addr;
+ }
+ mapping_info->ion_fd = 0;
+ mapping_info->buf = buf;
+ mapping_info->attach = attach;
+ mapping_info->table = table;
+ mapping_info->paddr = sg_dma_address(table->sgl);
+ mapping_info->len = (size_t)sg_dma_len(table->sgl);
+ mapping_info->dir = dma_dir;
+ mapping_info->ref_count = 1;
+
+ /* return paddr and len to client */
+ *paddr_ptr = sg_dma_address(table->sgl);
+ *len_ptr = (size_t)sg_dma_len(table->sgl);
+
+ if (!*paddr_ptr || !*len_ptr) {
+ pr_err("Error: Invalid dma address/length\n");
+ rc = -ENOSPC;
+ goto err_mapping_info;
+ }
+ CDBG("dev = %p, paddr= %p, len = %u\n",
+ (void *)iommu_cb_set.cb_info[idx].dev,
+ (void *)*paddr_ptr, (unsigned int)*len_ptr);
+
+ /* add to the list */
+ list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_list);
+
+ return 0;
+
+err_mapping_info:
+ kzfree(mapping_info);
+err_map_addr:
+ msm_dma_unmap_sg(iommu_cb_set.cb_info[idx].dev,
+ table->sgl, table->nents,
+ dma_dir, buf);
+err_unmap_sg:
+ dma_buf_unmap_attachment(attach, table, dma_dir);
+err_detach:
+ dma_buf_detach(buf, attach);
+err_put:
+ return rc;
+}
+
static int cam_smmu_unmap_buf_and_remove_from_list(
struct cam_dma_buff_info *mapping_info,
int idx)
@@ -951,7 +1239,23 @@ int cam_smmu_ops(int handle, enum cam_smmu_ops_param ops)
break;
}
case CAM_SMMU_DETACH: {
- ret = 0;
+ ret = cam_smmu_detach_device(idx);
+ break;
+ }
+ case CAM_SMMU_ATTACH_SEC_VFE_NS_STATS: {
+ ret = cam_smmu_attach_sec_vfe_ns_stats(idx);
+ break;
+ }
+ case CAM_SMMU_DETACH_SEC_VFE_NS_STATS: {
+ ret = cam_smmu_detach_sec_vfe_ns_stats(idx);
+ break;
+ }
+ case CAM_SMMU_ATTACH_SEC_CPP: {
+ ret = cam_smmu_attach_sec_cpp(idx);
+ break;
+ }
+ case CAM_SMMU_DETACH_SEC_CPP: {
+ ret = cam_smmu_detach_sec_cpp(idx);
break;
}
case CAM_SMMU_VOTE:
@@ -1126,7 +1430,7 @@ int cam_smmu_get_phy_addr_scratch(int handle,
size_t virt_len,
size_t phys_len)
{
- int idx, rc;
+ int idx, rc = 0;
unsigned int iommu_dir;
if (!paddr_ptr || !virt_len || !phys_len) {
@@ -1250,12 +1554,384 @@ int cam_smmu_put_phy_addr_scratch(int handle,
pr_err("Error: unmap or remove list fail\n");
goto handle_err;
}
+handle_err:
+ mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
+ return rc;
+}
+
+int cam_smmu_get_phy_addr_secure_scratch(int handle,
+ enum cam_smmu_map_dir dir,
+ struct dma_buf *scratch_buf,
+ dma_addr_t *paddr_ptr,
+ size_t *len_ptr)
+{
+ int idx, rc;
+ enum dma_data_direction dma_dir;
+
+ if (!paddr_ptr || !len_ptr) {
+ pr_err("Error: Input pointer or lengths invalid\n");
+ return -EINVAL;
+ }
+
+ dma_dir = cam_smmu_translate_dir(dir);
+ if (dma_dir == DMA_NONE) {
+ pr_err("Error: translate direction failed. dir = %d\n", dir);
+ return -EINVAL;
+ }
+
+ idx = GET_SMMU_TABLE_IDX(handle);
+ if (handle == HANDLE_INIT || idx < 0 || idx >= iommu_cb_set.cb_num) {
+ pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+ idx, handle);
+ return -EINVAL;
+ }
+
+ mutex_lock(&iommu_cb_set.cb_info[idx].lock);
+ if (iommu_cb_set.cb_info[idx].handle != handle) {
+ pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+ iommu_cb_set.cb_info[idx].handle, handle);
+ rc = -EINVAL;
+ goto error;
+ }
+
+ CDBG("%s: smmu handle = %x, idx = %d, dir = %d\n",
+ __func__, handle, idx, dir);
+
+ if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) {
+ pr_err("Error: Device %s should call SMMU attach before map buffer\n",
+ iommu_cb_set.cb_info[idx].name);
+ rc = -EINVAL;
+ goto error;
+ }
+
+ rc = cam_smmu_map_secure_buffer_and_add_to_list(idx,
+ scratch_buf,
+ dma_dir,
+ paddr_ptr,
+ len_ptr);
+ if (rc < 0) {
+ pr_err("Error: mapping or add list fail\n");
+ goto error;
+ }
+
+ CDBG("Mapped scratch buffer physical address is %lx\n",
+ (unsigned long)*paddr_ptr);
+error:
+ mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
+ return rc;
+}
+
+int cam_smmu_put_phy_addr_secure_scratch(int handle,
+ dma_addr_t paddr)
+{
+ int idx;
+ int rc = -1;
+ struct cam_dma_buff_info *mapping_info;
+
+ /* find index in the iommu_cb_set.cb_info */
+ idx = GET_SMMU_TABLE_IDX(handle);
+ if (handle == HANDLE_INIT || idx < 0 || idx >= iommu_cb_set.cb_num) {
+ pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+ idx, handle);
+ return -EINVAL;
+ }
+
+ mutex_lock(&iommu_cb_set.cb_info[idx].lock);
+ if (iommu_cb_set.cb_info[idx].handle != handle) {
+ pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+ iommu_cb_set.cb_info[idx].handle, handle);
+ rc = -EINVAL;
+ goto handle_err;
+ }
+
+ /* Based on virtual address and index, we can find mapping info
+ * of the scratch buffer
+ */
+ mapping_info = cam_smmu_find_mapping_by_virt_address(idx, paddr);
+ if (!mapping_info) {
+ pr_err("Error: Invalid params\n");
+ rc = -EINVAL;
+ goto handle_err;
+ }
+
+ /* unmapping one buffer from device */
+ rc = cam_smmu_unmap_buf_and_remove_from_list(mapping_info, idx);
+ if (rc < 0) {
+ pr_err("Error: unmap or remove list fail\n");
+ goto handle_err;
+ }
+ CDBG("Unmap secure scratch buffer %lx success fully\n",
+ (unsigned long)paddr);
handle_err:
mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
return rc;
}
+int cam_smmu_alloc_get_stage2_scratch_mem(int handle,
+ enum cam_smmu_map_dir dir, struct ion_client *client,
+ struct ion_handle **sc_handle, ion_phys_addr_t *addr,
+ size_t *len_ptr)
+{
+ int idx, rc = 0;
+ enum dma_data_direction dma_dir;
+
+ dma_dir = cam_smmu_translate_dir(dir);
+ if (dma_dir == DMA_NONE) {
+ pr_err("Error: translate direction failed. dir = %d\n", dir);
+ return -EINVAL;
+ }
+ idx = GET_SMMU_TABLE_IDX(handle);
+ if (handle == HANDLE_INIT || idx < 0 || idx >= iommu_cb_set.cb_num) {
+ pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+ idx, handle);
+ return -EINVAL;
+ }
+ if (iommu_cb_set.cb_info[idx].handle != handle) {
+ pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+ iommu_cb_set.cb_info[idx].handle, handle);
+ return -EINVAL;
+ }
+
+ if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) {
+ pr_err("Error: Device %s should call SMMU attach before map buffer\n",
+ iommu_cb_set.cb_info[idx].name);
+ return -EINVAL;
+ }
+ *sc_handle = ion_alloc(client, SZ_2M, SZ_2M,
+ ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID),
+ ION_FLAG_SECURE | ION_FLAG_CP_CAMERA);
+ if (IS_ERR_OR_NULL((void *) (*sc_handle))) {
+ rc = -ENOMEM;
+ goto err_ion_handle;
+ }
+
+ /* return addr and len to client */
+ rc = ion_phys(client, *sc_handle, addr, len_ptr);
+ if (rc) {
+ pr_err("%s: ION Get Physical failed, rc = %d\n",
+ __func__, rc);
+ rc = -EINVAL;
+ goto err_ion_phys;
+ }
+
+ CDBG("dev = %pK, paddr= %pK, len = %u\n",
+ (void *)iommu_cb_set.cb_info[idx].dev,
+ (void *)*addr, (unsigned int)*len_ptr);
+ return rc;
+
+err_ion_phys:
+ ion_free(client, *sc_handle);
+
+err_ion_handle:
+ *sc_handle = NULL;
+ return rc;
+}
+
+int cam_smmu_free_stage2_scratch_mem(int handle,
+ struct ion_client *client, struct ion_handle *sc_handle)
+{
+ int idx = 0;
+ /* find index in the iommu_cb_set.cb_info */
+ idx = GET_SMMU_TABLE_IDX(handle);
+ if (handle == HANDLE_INIT || idx < 0 || idx >= iommu_cb_set.cb_num) {
+ pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+ idx, handle);
+ return -EINVAL;
+ }
+ ion_free(client, sc_handle);
+ return 0;
+}
+
+static int cam_smmu_secure_unmap_buf_and_remove_from_list(
+ struct cam_sec_buff_info *mapping_info,
+ int idx)
+{
+ if (!mapping_info) {
+ pr_err("Error: List doesn't exist\n");
+ return -EINVAL;
+ }
+ ion_free(mapping_info->i_client, mapping_info->i_hdl);
+ list_del_init(&mapping_info->list);
+
+ /* free one buffer */
+ kfree(mapping_info);
+ return 0;
+}
+
+int cam_smmu_put_stage2_phy_addr(int handle, int ion_fd)
+{
+ int idx, rc;
+ struct cam_sec_buff_info *mapping_info;
+
+ /* find index in the iommu_cb_set.cb_info */
+ idx = GET_SMMU_TABLE_IDX(handle);
+ if (handle == HANDLE_INIT || idx < 0 || idx >= iommu_cb_set.cb_num) {
+ pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+ idx, handle);
+ return -EINVAL;
+ }
+
+ mutex_lock(&iommu_cb_set.cb_info[idx].lock);
+ if (iommu_cb_set.cb_info[idx].handle != handle) {
+ pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+ iommu_cb_set.cb_info[idx].handle, handle);
+ rc = -EINVAL;
+ goto put_addr_end;
+ }
+
+ /* based on ion fd and index, we can find mapping info of buffer */
+ mapping_info = cam_smmu_find_mapping_by_sec_buf_idx(idx, ion_fd);
+ if (!mapping_info) {
+ pr_err("Error: Invalid params! idx = %d, fd = %d\n",
+ idx, ion_fd);
+ rc = -EINVAL;
+ goto put_addr_end;
+ }
+
+ mapping_info->ref_count--;
+ if (mapping_info->ref_count > 0) {
+ CDBG("There are still %u buffer(s) with same fd %d",
+ mapping_info->ref_count, mapping_info->ion_fd);
+ rc = 0;
+ goto put_addr_end;
+ }
+
+ /* unmapping one buffer from device */
+ rc = cam_smmu_secure_unmap_buf_and_remove_from_list(mapping_info, idx);
+ if (rc < 0) {
+ pr_err("Error: unmap or remove list fail\n");
+ goto put_addr_end;
+ }
+
+put_addr_end:
+ mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
+ return rc;
+}
+EXPORT_SYMBOL(cam_smmu_put_stage2_phy_addr);
+
+static int cam_smmu_map_stage2_buffer_and_add_to_list(int idx, int ion_fd,
+ enum dma_data_direction dma_dir, struct ion_client *client,
+ dma_addr_t *paddr_ptr,
+ size_t *len_ptr)
+{
+ int rc = 0;
+ struct ion_handle *i_handle = NULL;
+ struct cam_sec_buff_info *mapping_info;
+
+
+ /* clean the content from clients */
+ *paddr_ptr = (dma_addr_t)NULL;
+ *len_ptr = (size_t)0;
+
+ if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) {
+ pr_err("Error: Device %s should call SMMU attach before map buffer\n",
+ iommu_cb_set.cb_info[idx].name);
+ return -EINVAL;
+ }
+
+ i_handle = ion_import_dma_buf(client, ion_fd);
+ if (IS_ERR_OR_NULL((void *)(i_handle))) {
+ pr_err("%s: ion import dma buffer failed\n", __func__);
+ return -EINVAL;
+ }
+
+ /* return addr and len to client */
+ rc = ion_phys(client, i_handle, paddr_ptr, len_ptr);
+ if (rc) {
+ pr_err("%s: ION Get Physical failed, rc = %d\n",
+ __func__, rc);
+ return -EINVAL;
+ }
+
+ /* fill up mapping_info */
+ mapping_info = kzalloc(sizeof(struct cam_sec_buff_info), GFP_KERNEL);
+ if (!mapping_info)
+ return -ENOSPC;
+
+ mapping_info->ion_fd = ion_fd;
+ mapping_info->paddr = *paddr_ptr;
+ mapping_info->len = *len_ptr;
+ mapping_info->dir = dma_dir;
+ mapping_info->ref_count = 1;
+ mapping_info->i_hdl = i_handle;
+ mapping_info->i_client = client;
+
+ CDBG("ion_fd = %d, dev = %pK, paddr= %pK, len = %u\n", ion_fd,
+ (void *)iommu_cb_set.cb_info[idx].dev,
+ (void *)*paddr_ptr, (unsigned int)*len_ptr);
+
+ /* add to the list */
+ list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_list);
+
+ return rc;
+}
+
+int cam_smmu_get_stage2_phy_addr(int handle,
+ int ion_fd, enum cam_smmu_map_dir dir,
+ struct ion_client *client, ion_phys_addr_t *paddr_ptr,
+ size_t *len_ptr)
+{
+ int idx, rc;
+ enum dma_data_direction dma_dir;
+ enum cam_smmu_buf_state buf_state;
+
+ if (!paddr_ptr || !len_ptr) {
+ pr_err("Error: Input pointers are invalid\n");
+ return -EINVAL;
+ }
+ /* clean the content from clients */
+ *paddr_ptr = (dma_addr_t)NULL;
+ *len_ptr = (size_t)0;
+
+ dma_dir = cam_smmu_translate_dir(dir);
+ if (dma_dir == DMA_NONE) {
+ pr_err("Error: translate direction failed. dir = %d\n", dir);
+ return -EINVAL;
+ }
+
+ idx = GET_SMMU_TABLE_IDX(handle);
+ if (handle == HANDLE_INIT || idx < 0 || idx >= iommu_cb_set.cb_num) {
+ pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
+ idx, handle);
+ return -EINVAL;
+ }
+
+ mutex_lock(&iommu_cb_set.cb_info[idx].lock);
+ if (iommu_cb_set.cb_info[idx].handle != handle) {
+ pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
+ iommu_cb_set.cb_info[idx].handle, handle);
+ rc = -EINVAL;
+ goto get_addr_end;
+ }
+
+ if (iommu_cb_set.cb_info[idx].state != CAM_SMMU_ATTACH) {
+ pr_err("Error: Device %s should call SMMU attach before map buffer\n",
+ iommu_cb_set.cb_info[idx].name);
+ rc = -EINVAL;
+ goto get_addr_end;
+ }
+
+ buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr);
+ if (buf_state == CAM_SMMU_BUFF_EXIST) {
+ CDBG("ion_fd:%d already in the list, give same addr back",
+ ion_fd);
+ rc = 0;
+ goto get_addr_end;
+ }
+ rc = cam_smmu_map_stage2_buffer_and_add_to_list(idx, ion_fd, dma_dir,
+ client, paddr_ptr, len_ptr);
+ if (rc < 0) {
+ pr_err("Error: mapping or add list fail\n");
+ goto get_addr_end;
+ }
+
+get_addr_end:
+ mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
+ return rc;
+}
+
+
int cam_smmu_get_phy_addr(int handle, int ion_fd,
enum cam_smmu_map_dir dir, dma_addr_t *paddr_ptr,
size_t *len_ptr)
@@ -1383,6 +2059,11 @@ int cam_smmu_destroy_handle(int handle)
}
mutex_lock(&iommu_cb_set.cb_info[idx].lock);
+ if (--iommu_cb_set.cb_info[idx].ref_cnt != 0) {
+ mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
+ return 0;
+ }
+
if (iommu_cb_set.cb_info[idx].handle != handle) {
pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
iommu_cb_set.cb_info[idx].handle, handle);
@@ -1469,6 +2150,28 @@ end:
return rc;
}
+static int cam_smmu_populate_sids(struct device *dev,
+ struct cam_context_bank_info *cb)
+{
+ int i, j, rc = 0;
+ unsigned int cnt = 0;
+ const void *property;
+
+ /* set the name of the context bank */
+ property = of_get_property(dev->of_node, "iommus", &cnt);
+ cnt /= 4;
+ for (i = 0, j = 0; i < cnt; i = i + 2, j++) {
+ rc = of_property_read_u32_index(dev->of_node,
+ "iommus", i + 1, &cb->sids[j]);
+ if (rc < 0)
+ pr_err("misconfiguration, can't fetch SID\n");
+
+ pr_err("__debug cnt = %d, cb->name: :%s sid [%d] = %d\n,",
+ cnt, cb->name, j, cb->sids[j]);
+ }
+ return rc;
+}
+
static int cam_alloc_smmu_context_banks(struct device *dev)
{
struct device_node *domains_child_node = NULL;
@@ -1541,6 +2244,11 @@ static int cam_populate_smmu_context_banks(struct device *dev,
goto cb_init_fail;
}
+ /* populate SID's for each cb */
+ rc = cam_smmu_populate_sids(dev, cb);
+ if (rc < 0)
+ pr_err("Error: failed to populate sids : %s\n", cb->name);
+
/* Check if context bank supports scratch buffers */
if (of_property_read_bool(dev->of_node, "qcom,scratch-buf-support"))
cb->scratch_buf_support = 1;
@@ -1549,9 +2257,9 @@ static int cam_populate_smmu_context_banks(struct device *dev,
/* set the secure/non secure domain type */
if (of_property_read_bool(dev->of_node, "qcom,secure-context"))
- cb->is_secure = CAM_SECURE;
+ cb->is_secure = true;
else
- cb->is_secure = CAM_NON_SECURE;
+ cb->is_secure = false;
CDBG("cb->name :%s, cb->is_secure :%d, cb->scratch_support :%d\n",
cb->name, cb->is_secure, cb->scratch_buf_support);
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.h b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.h
index 59d085989a9c..3b8481f8bf7e 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.h
+++ b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.h
@@ -23,6 +23,8 @@
#include <linux/random.h>
#include <linux/spinlock_types.h>
#include <linux/mutex.h>
+#include <linux/msm_ion.h>
+
/*
* Enum for possible CAM SMMU operations
@@ -31,6 +33,10 @@
enum cam_smmu_ops_param {
CAM_SMMU_ATTACH,
CAM_SMMU_DETACH,
+ CAM_SMMU_ATTACH_SEC_VFE_NS_STATS,
+ CAM_SMMU_DETACH_SEC_VFE_NS_STATS,
+ CAM_SMMU_ATTACH_SEC_CPP,
+ CAM_SMMU_DETACH_SEC_CPP,
CAM_SMMU_VOTE,
CAM_SMMU_DEVOTE,
CAM_SMMU_OPS_INVALID
@@ -87,6 +93,59 @@ int cam_smmu_get_phy_addr(int handle,
int cam_smmu_put_phy_addr(int handle, int ion_fd);
/**
+ * @param handle: Client has to pass back the smmu handle provided.
+ * @param ion_fd: ION handle identifying the memory buffer.
+ * @dir : Mapping direction: which will traslate toDMA_BIDIRECTIONAL,
+ * DMA_TO_DEVICE or DMA_FROM_DEVICE
+ * @client : Client has to pass the ion_client pointer created by the client.
+ * @phys_addr : Pointer to physical address where mapped address will be
+ * returned.
+ * @len : Length of buffer mapped returned by CAM SMMU driver.
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int cam_smmu_get_stage2_phy_addr(int handle,
+ int ion_fd, enum cam_smmu_map_dir dir,
+ struct ion_client *client, ion_phys_addr_t *addr,
+ size_t *len_ptr);
+
+/**
+ * @param handle: Handle to identify the CAMSMMU client (VFE, CPP, FD etc.)
+ * @param ion_fd: ION handle identifying the memory buffer.
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int cam_smmu_put_stage2_phy_addr(int handle, int ion_fd);
+
+/**
+ * @param handle: Client has to pass back the smmu handle provided.
+ * @dir : Mapping direction: which will traslate toDMA_BIDIRECTIONAL,
+ * DMA_TO_DEVICE or DMA_FROM_DEVICE, client has to pass.
+ * @client : Client has to pass the ion_client pointer created by the client.
+ * @ion_handle : handle to the buffer returned by CAM SMMU driver.
+ * @phys_addr : Pointer to physical address where mapped address will be
+ * returned.
+ * @len : Length of buffer mapped returned by CAM SMMU driver.
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int cam_smmu_alloc_get_stage2_scratch_mem(int handle,
+ enum cam_smmu_map_dir dir, struct ion_client *client,
+ struct ion_handle **sc_handle, ion_phys_addr_t *addr,
+ size_t *len_ptr);
+
+
+/**
+ * @param handle: Client has to pass back the smmu handle provided.
+ * @client : Client has to pass the ion_client pointer provided by SMMU
+ * driver.
+ * @ion_handle : Client has to pass the ion_handle provided by SMMU
+ * driver.
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+
+int cam_smmu_free_stage2_scratch_mem(int handle,
+ struct ion_client *client, struct ion_handle *sc_handle);
+
+/**
* @brief : Allocates a scratch buffer
*
* This function allocates a scratch virtual buffer of length virt_len in the
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index 7accaa3a1673..039ffcc24c23 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -214,7 +214,6 @@ static struct smb_params v1_params = {
#define STEP_CHARGING_MAX_STEPS 5
struct smb_dt_props {
- bool no_battery;
int fcc_ua;
int usb_icl_ua;
int otg_cl_ua;
@@ -226,7 +225,9 @@ struct smb_dt_props {
struct device_node *revid_dev_node;
int float_option;
int chg_inhibit_thr_mv;
+ bool no_battery;
bool hvdcp_disable;
+ bool auto_recharge_soc;
};
struct smb2 {
@@ -344,6 +345,8 @@ static int smb2_parse_dt(struct smb2 *chip)
return -EINVAL;
}
+ chip->dt.auto_recharge_soc = of_property_read_bool(node,
+ "qcom,auto-recharge-soc");
return 0;
}
@@ -1295,6 +1298,28 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
+ if (chip->dt.auto_recharge_soc) {
+ rc = smblib_masked_write(chg, FG_UPDATE_CFG_2_SEL_REG,
+ SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT |
+ VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT,
+ VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure FG_UPDATE_CFG2_SEL_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+ } else {
+ rc = smblib_masked_write(chg, FG_UPDATE_CFG_2_SEL_REG,
+ SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT |
+ VBT_LT_CHG_RECHARGE_THRESH_SEL_BIT,
+ SOC_LT_CHG_RECHARGE_THRESH_SEL_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure FG_UPDATE_CFG2_SEL_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+
return rc;
}
@@ -1837,8 +1862,13 @@ static void smb2_shutdown(struct platform_device *pdev)
struct smb2 *chip = platform_get_drvdata(pdev);
struct smb_charger *chg = &chip->chg;
+ /* configure power role for UFP */
+ smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+ TYPEC_POWER_ROLE_CMD_MASK, UFP_EN_CMD_BIT);
+
+ /* force HVDCP to 5V */
smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
- HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
+ HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
}
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index 3403474565be..52805357ef92 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -505,15 +505,14 @@ static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
{
- const struct apsd_result *apsd_result;
+ const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
/* if PD is active, APSD is disabled so won't have a valid result */
if (chg->pd_active) {
chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
- return 0;
+ return apsd_result;
}
- apsd_result = smblib_get_apsd_result(chg);
chg->usb_psy_desc.type = apsd_result->pst;
return apsd_result;
}
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c
index deb7231a4ed1..10fb4cc8ebff 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c
@@ -869,7 +869,7 @@ static void unregister_client_adhoc(uint32_t cl)
}
curr = client->curr;
- if (curr >= pdata->num_usecases) {
+ if ((curr < 0) || (curr >= pdata->num_usecases)) {
MSM_BUS_ERR("Invalid index Defaulting curr to 0");
curr = 0;
}
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 826a22355429..f93ee29123fe 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -42,8 +42,8 @@
#define SMEM_IMAGE_VERSION_NAME_SIZE 75
#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20
#define SMEM_IMAGE_VERSION_VARIANT_OFFSET 75
-#define SMEM_IMAGE_VERSION_OEM_SIZE 32
-#define SMEM_IMAGE_VERSION_OEM_OFFSET 96
+#define SMEM_IMAGE_VERSION_OEM_SIZE 33
+#define SMEM_IMAGE_VERSION_OEM_OFFSET 95
#define SMEM_IMAGE_VERSION_PARTITION_APPS 10
enum {
@@ -974,7 +974,7 @@ msm_get_image_crm_version(struct device *dev,
}
string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
string_address += SMEM_IMAGE_VERSION_OEM_OFFSET;
- return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s\n",
+ return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.33s\n",
string_address);
}
@@ -995,7 +995,7 @@ msm_set_image_crm_version(struct device *dev,
}
store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
store_address += SMEM_IMAGE_VERSION_OEM_OFFSET;
- snprintf(store_address, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s", buf);
+ snprintf(store_address, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.33s", buf);
return count;
}
@@ -1049,7 +1049,8 @@ msm_get_images(struct device *dev,
image_address);
pos += snprintf(buf + pos, PAGE_SIZE - pos, "\tVariant:\t%-.20s\n",
image_address + SMEM_IMAGE_VERSION_VARIANT_OFFSET);
- pos += snprintf(buf + pos, PAGE_SIZE - pos, "\tVersion:\t%-.32s\n\n",
+ pos += snprintf(buf + pos, PAGE_SIZE - pos,
+ "\tVersion:\t%-.33s\n",
image_address + SMEM_IMAGE_VERSION_OEM_OFFSET);
image_address += SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
index b90ac82049c6..0a316fa19909 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
@@ -134,6 +134,7 @@ struct hdmi_edid_ctrl {
u8 it_scan_info;
u8 ce_scan_info;
u8 cea_blks;
+ /* DC: MSB -> LSB: Y420_48|Y420_36|Y420_30|RGB48|RGB36|RGB30|Y444 */
u8 deep_color;
u16 physical_address;
u32 video_resolution; /* selected by user */
@@ -858,6 +859,43 @@ static const u8 *hdmi_edid_find_block(const u8 *in_buf, u32 start_offset,
return NULL;
} /* hdmi_edid_find_block */
+static const u8 *hdmi_edid_find_hfvsdb(const u8 *in_buf)
+{
+ u8 len = 0, i = 0;
+ const u8 *vsd = NULL;
+ u32 vsd_offset = DBC_START_OFFSET;
+ u32 hf_ieee_oui = 0;
+
+ /* Find HF-VSDB with HF-OUI */
+ do {
+ vsd = hdmi_edid_find_block(in_buf, vsd_offset,
+ VENDOR_SPECIFIC_DATA_BLOCK, &len);
+
+ if (!vsd || !len || len > MAX_DATA_BLOCK_SIZE) {
+ if (i == 0)
+ pr_debug("%s: VSDB not found\n", __func__);
+ else
+ pr_debug("%s: no more VSDB found\n", __func__);
+
+ return NULL;
+ }
+
+ hf_ieee_oui = (vsd[1] << 16) | (vsd[2] << 8) | vsd[3];
+
+ if (hf_ieee_oui == HDMI_FORUM_IEEE_OUI) {
+ pr_debug("%s: found HF-VSDB\n", __func__);
+ break;
+ }
+
+ pr_debug("%s: Not a HF OUI 0x%x\n", __func__, hf_ieee_oui);
+
+ i++;
+ vsd_offset = vsd - in_buf + len + 1;
+ } while (1);
+
+ return vsd;
+}
+
static void hdmi_edid_set_y420_support(struct hdmi_edid_ctrl *edid_ctrl,
u32 video_format)
{
@@ -1251,62 +1289,32 @@ static void hdmi_edid_extract_speaker_allocation_data(
static void hdmi_edid_extract_sink_caps(struct hdmi_edid_ctrl *edid_ctrl,
const u8 *in_buf)
{
- u8 len = 0, i = 0;
const u8 *vsd = NULL;
- u32 vsd_offset = DBC_START_OFFSET;
- u32 hf_ieee_oui = 0;
if (!edid_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
+ pr_err("%s: invalid input\n", __func__);
return;
}
- /* Find HF-VSDB with HF-OUI */
- do {
- vsd = hdmi_edid_find_block(in_buf, vsd_offset,
- VENDOR_SPECIFIC_DATA_BLOCK, &len);
-
- if (!vsd || !len || len > MAX_DATA_BLOCK_SIZE) {
- if (i == 0)
- DEV_ERR("%s: VSDB not found\n", __func__);
- else
- DEV_DBG("%s: no more VSDB found\n", __func__);
- break;
- }
-
- hf_ieee_oui = (vsd[1] << 16) | (vsd[2] << 8) | vsd[3];
-
- if (hf_ieee_oui == HDMI_FORUM_IEEE_OUI) {
- DEV_DBG("%s: found HF-VSDB\n", __func__);
- break;
- }
-
- DEV_DBG("%s: Not a HF OUI 0x%x\n", __func__, hf_ieee_oui);
-
- i++;
- vsd_offset = vsd - in_buf + len + 1;
- } while (1);
-
- if (!vsd) {
- DEV_DBG("%s: HF-VSDB not found\n", __func__);
- return;
+ vsd = hdmi_edid_find_hfvsdb(in_buf);
+
+ if (vsd) {
+ /* Max pixel clock is in multiples of 5Mhz. */
+ edid_ctrl->sink_caps.max_pclk_in_hz =
+ vsd[5]*5000000;
+ edid_ctrl->sink_caps.scdc_present =
+ (vsd[6] & 0x80) ? true : false;
+ edid_ctrl->sink_caps.scramble_support =
+ (vsd[6] & 0x08) ? true : false;
+ edid_ctrl->sink_caps.read_req_support =
+ (vsd[6] & 0x40) ? true : false;
+ edid_ctrl->sink_caps.osd_disparity =
+ (vsd[6] & 0x01) ? true : false;
+ edid_ctrl->sink_caps.dual_view_support =
+ (vsd[6] & 0x02) ? true : false;
+ edid_ctrl->sink_caps.ind_view_support =
+ (vsd[6] & 0x04) ? true : false;
}
-
- /* Max pixel clock is in multiples of 5Mhz. */
- edid_ctrl->sink_caps.max_pclk_in_hz =
- vsd[5]*5000000;
- edid_ctrl->sink_caps.scdc_present =
- (vsd[6] & 0x80) ? true : false;
- edid_ctrl->sink_caps.scramble_support =
- (vsd[6] & 0x08) ? true : false;
- edid_ctrl->sink_caps.read_req_support =
- (vsd[6] & 0x40) ? true : false;
- edid_ctrl->sink_caps.osd_disparity =
- (vsd[6] & 0x01) ? true : false;
- edid_ctrl->sink_caps.dual_view_support =
- (vsd[6] & 0x02) ? true : false;
- edid_ctrl->sink_caps.ind_view_support =
- (vsd[6] & 0x04) ? true : false;
}
static void hdmi_edid_extract_latency_fields(struct hdmi_edid_ctrl *edid_ctrl,
@@ -1404,12 +1412,19 @@ static void hdmi_edid_extract_dc(struct hdmi_edid_ctrl *edid_ctrl,
edid_ctrl->deep_color = (vsd[6] >> 0x3) & 0xF;
- DEV_DBG("%s: deep color: Y444|RGB30|RGB36|RGB48: (%d|%d|%d|%d)\n",
- __func__,
+ vsd = hdmi_edid_find_hfvsdb(in_buf);
+
+ if (vsd)
+ edid_ctrl->deep_color |= (vsd[7] & 0x07) << 4;
+
+ pr_debug("deep color: Y444|RGB30|RGB36|RGB48|Y420_30|Y420_36|Y420_48: (%d|%d|%d|%d|%d|%d|%d)\n",
(int) (edid_ctrl->deep_color & BIT(0)) >> 0,
(int) (edid_ctrl->deep_color & BIT(1)) >> 1,
(int) (edid_ctrl->deep_color & BIT(2)) >> 2,
- (int) (edid_ctrl->deep_color & BIT(3)) >> 3);
+ (int) (edid_ctrl->deep_color & BIT(3)) >> 3,
+ (int) (edid_ctrl->deep_color & BIT(4)) >> 4,
+ (int) (edid_ctrl->deep_color & BIT(5)) >> 5,
+ (int) (edid_ctrl->deep_color & BIT(6)) >> 6);
}
static u32 hdmi_edid_check_header(const u8 *edid_buf)
@@ -2398,8 +2413,8 @@ u32 hdmi_edid_get_sink_mode(void *input)
*
* This API returns deep color for different formats supported by sink.
* Deep color support for Y444 (BIT(0)), RGB30 (BIT(1)), RGB36 (BIT(2),
- * RGB 48 (BIT(3)) is provided in a 8 bit integer. The MSB 8 bits are
- * not used.
+ * RGB 48 (BIT(3)), Y420_30 (BIT(4)), Y420_36 (BIT(5)), Y420_48 (BIT(6))
+ * is provided in a 8 bit integer. The MSB 8 bits are not used.
*
* Return: deep color data.
*/
@@ -2416,6 +2431,25 @@ u8 hdmi_edid_get_deep_color(void *input)
}
/**
+ * hdmi_edid_get_max_pclk() - get max pclk supported. Sink side's limitation
+ * should be concerned as well.
+ * @input: edid parser data
+ *
+ * Return: max pclk rate
+ */
+u32 hdmi_edid_get_max_pclk(void *input)
+{
+ struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+
+ if (!edid_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return 0;
+ }
+
+ return edid_ctrl->init_data.max_pclk_khz;
+}
+
+/**
* hdmi_edid_get_hdr_data() - get the HDR capabiliies of the sink
* @input: edid parser data
*
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.h b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
index ce6cecbb2e03..43e1adb1f139 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
@@ -60,6 +60,7 @@ void *hdmi_edid_init(struct hdmi_edid_init_data *init_data);
bool hdmi_edid_is_s3d_mode_supported(void *input,
u32 video_mode, u32 s3d_mode);
u8 hdmi_edid_get_deep_color(void *edid_ctrl);
+u32 hdmi_edid_get_max_pclk(void *edid_ctrl);
void hdmi_edid_get_hdr_data(void *edid_ctrl,
struct hdmi_edid_hdr_data **hdr_data);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.c b/drivers/video/fbdev/msm/mdss_hdmi_panel.c
index 522debfba8ce..a8a56e3a8745 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.c
@@ -602,14 +602,51 @@ end:
return rc;
}
+static int hdmi_panel_setup_dc(struct hdmi_panel *panel)
+{
+ u32 hdmi_ctrl_reg;
+ u32 vbi_pkt_reg;
+ int rc = 0;
+
+ pr_debug("Deep Color: %s\n", panel->data->dc_enable ? "ON" : "OFF");
+
+ /* enable deep color if supported */
+ if (panel->data->dc_enable) {
+ hdmi_ctrl_reg = DSS_REG_R(panel->io, HDMI_CTRL);
+
+ /* GC CD override */
+ hdmi_ctrl_reg |= BIT(27);
+
+ /* enable deep color for RGB888 30 bits */
+ hdmi_ctrl_reg |= BIT(24);
+ DSS_REG_W(panel->io, HDMI_CTRL, hdmi_ctrl_reg);
+
+ /* Enable GC_CONT and GC_SEND in General Control Packet
+ * (GCP) register so that deep color data is
+ * transmitted to the sink on every frame, allowing
+ * the sink to decode the data correctly.
+ *
+ * GC_CONT: 0x1 - Send GCP on every frame
+ * GC_SEND: 0x1 - Enable GCP Transmission
+ */
+ vbi_pkt_reg = DSS_REG_R(panel->io, HDMI_VBI_PKT_CTRL);
+ vbi_pkt_reg |= BIT(5) | BIT(4);
+ DSS_REG_W(panel->io, HDMI_VBI_PKT_CTRL, vbi_pkt_reg);
+ }
+
+ return rc;
+}
+
static int hdmi_panel_setup_scrambler(struct hdmi_panel *panel)
{
int rc = 0;
int timeout_hsync;
u32 reg_val = 0;
u32 tmds_clock_ratio = 0;
+ u32 tmds_clock = 0;
bool scrambler_on = false;
struct msm_hdmi_mode_timing_info *timing = NULL;
+ struct mdss_panel_info *pinfo = NULL;
if (!panel) {
pr_err("invalid input\n");
@@ -622,13 +659,22 @@ static int hdmi_panel_setup_scrambler(struct hdmi_panel *panel)
return -EINVAL;
}
+ pinfo = panel->data->pinfo;
+ if (!pinfo) {
+ pr_err("invalid panel data\n");
+ return -EINVAL;
+ }
+
/* Scrambling is supported from HDMI TX 4.0 */
if (panel->version < HDMI_TX_SCRAMBLER_MIN_TX_VERSION) {
pr_debug("scrambling not supported by tx\n");
return 0;
}
- if (timing->pixel_freq > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) {
+ tmds_clock = hdmi_tx_setup_tmds_clk_rate(timing->pixel_freq,
+ pinfo->out_format, panel->data->dc_enable);
+
+ if (tmds_clock > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) {
scrambler_on = true;
tmds_clock_ratio = 1;
} else {
@@ -798,6 +844,12 @@ static int hdmi_panel_power_on(void *input)
pr_err("scrambler setup failed. rc=%d\n", rc);
goto err;
}
+
+ rc = hdmi_panel_setup_dc(panel);
+ if (rc) {
+ pr_err("Deep Color setup failed. rc=%d\n", rc);
+ goto err;
+ }
end:
panel->on = true;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.h b/drivers/video/fbdev/msm/mdss_hdmi_panel.h
index 6fa9af13d46e..cb40f0cad55e 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_panel.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.h
@@ -28,6 +28,7 @@
* @infoframe: set to true if infoframes should be sent to sink
* @is_it_content: set to true if content is IT
* @scrambler: set to true if scrambler needs to be enabled
+ * @dc_enable: set to true if deep color is enabled
*/
struct hdmi_panel_data {
struct mdss_panel_info *pinfo;
@@ -39,6 +40,7 @@ struct hdmi_panel_data {
bool infoframe;
bool is_it_content;
bool scrambler;
+ bool dc_enable;
};
/**
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index d01d163af5fa..ff44d0ae4ac5 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -35,6 +35,7 @@
#include "mdss.h"
#include "mdss_panel.h"
#include "mdss_hdmi_mhl.h"
+#include "mdss_hdmi_util.h"
#define DRV_NAME "hdmi-tx"
#define COMPATIBLE_NAME "qcom,hdmi-tx"
@@ -58,13 +59,6 @@
#define AUDIO_POLL_SLEEP_US (5 * 1000)
#define AUDIO_POLL_TIMEOUT_US (AUDIO_POLL_SLEEP_US * 1000)
-#define HDMI_TX_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO 2
-#define HDMI_TX_YUV422_24BPP_PCLK_TMDS_CH_RATE_RATIO 1
-#define HDMI_TX_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO 1
-
-#define HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ 340000
-#define HDMI_TX_SCRAMBLER_TIMEOUT_MSEC 200
-
/* Maximum pixel clock rates for hdmi tx */
#define HDMI_DEFAULT_MAX_PCLK_RATE 148500
#define HDMI_TX_3_MAX_PCLK_RATE 297000
@@ -111,7 +105,6 @@ static irqreturn_t hdmi_tx_isr(int irq, void *data);
static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
enum hdmi_tx_power_module_type module, int enable);
-static int hdmi_tx_setup_tmds_clk_rate(struct hdmi_tx_ctrl *hdmi_ctrl);
static void hdmi_tx_fps_work(struct work_struct *work);
static int hdmi_tx_pinctrl_set_state(struct hdmi_tx_ctrl *hdmi_ctrl,
enum hdmi_tx_power_module_type module, bool active);
@@ -318,11 +311,29 @@ static inline bool hdmi_tx_metadata_type_one(struct hdmi_tx_ctrl *hdmi_ctrl)
return hdr_data->metadata_type_one;
}
+static inline bool hdmix_tx_sink_dc_support(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ void *edid_fd = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID);
+
+ if (hdmi_ctrl->panel_data.panel_info.out_format == MDP_Y_CBCR_H2V2)
+ return (hdmi_edid_get_deep_color(edid_fd) & BIT(4));
+ else
+ return (hdmi_edid_get_deep_color(edid_fd) & BIT(1));
+}
+
static inline bool hdmi_tx_dc_support(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- return hdmi_ctrl->dc_feature_on && hdmi_ctrl->dc_support &&
- (hdmi_edid_get_deep_color(
- hdmi_tx_get_fd(HDMI_TX_FEAT_EDID)) & BIT(1));
+ /* actual pixel clock if deep color is enabled */
+ void *edid_fd = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID);
+ u32 tmds_clk_with_dc = hdmi_tx_setup_tmds_clk_rate(
+ hdmi_ctrl->timing.pixel_freq,
+ hdmi_ctrl->panel.pinfo->out_format,
+ true);
+
+ return hdmi_ctrl->dc_feature_on &&
+ hdmi_ctrl->dc_support &&
+ hdmix_tx_sink_dc_support(hdmi_ctrl) &&
+ (tmds_clk_with_dc <= hdmi_edid_get_max_pclk(edid_fd));
}
static const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
@@ -349,7 +360,10 @@ static const char *hdmi_tx_io_name(u32 type)
static void hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
{
if (hdmi_ctrl && hdmi_ctrl->audio_ops.on) {
- u32 pclk = hdmi_tx_setup_tmds_clk_rate(hdmi_ctrl);
+ u32 pclk = hdmi_tx_setup_tmds_clk_rate(
+ hdmi_ctrl->timing.pixel_freq,
+ hdmi_ctrl->panel.pinfo->out_format,
+ hdmi_ctrl->panel.dc_enable);
hdmi_ctrl->audio_ops.on(hdmi_ctrl->audio_data,
pclk, &hdmi_ctrl->audio_params);
@@ -2345,7 +2359,6 @@ static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
struct dss_io_data *io = NULL;
/* Defaults: Disable block, HDMI mode */
u32 hdmi_ctrl_reg = BIT(1);
- u32 vbi_pkt_reg;
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -2383,27 +2396,6 @@ static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
* longer be used
*/
hdmi_ctrl_reg |= BIT(31);
-
- /* enable deep color if supported */
- if (hdmi_tx_dc_support(hdmi_ctrl)) {
- /* GC CD override */
- hdmi_ctrl_reg |= BIT(27);
-
- /* enable deep color for RGB888 30 bits */
- hdmi_ctrl_reg |= BIT(24);
-
- /* Enable GC_CONT and GC_SEND in General Control Packet
- * (GCP) register so that deep color data is
- * transmitted to the sink on every frame, allowing
- * the sink to decode the data correctly.
- *
- * GC_CONT: 0x1 - Send GCP on every frame
- * GC_SEND: 0x1 - Enable GCP Transmission
- */
- vbi_pkt_reg = DSS_REG_R(io, HDMI_VBI_PKT_CTRL);
- vbi_pkt_reg |= BIT(5) | BIT(4);
- DSS_REG_W(io, HDMI_VBI_PKT_CTRL, vbi_pkt_reg);
- }
}
DSS_REG_W(io, HDMI_CTRL, hdmi_ctrl_reg);
@@ -2973,44 +2965,6 @@ static int hdmi_tx_get_cable_status(struct platform_device *pdev, u32 vote)
return hpd;
}
-static int hdmi_tx_setup_tmds_clk_rate(struct hdmi_tx_ctrl *hdmi_ctrl)
-{
- u32 rate = 0;
- struct msm_hdmi_mode_timing_info *timing = NULL;
- u32 rate_ratio;
-
- if (!hdmi_ctrl) {
- DEV_ERR("%s: Bad input parameters\n", __func__);
- goto end;
- }
-
- timing = &hdmi_ctrl->timing;
- if (!timing) {
- DEV_ERR("%s: Invalid timing info\n", __func__);
- goto end;
- }
-
- switch (hdmi_ctrl->panel_data.panel_info.out_format) {
- case MDP_Y_CBCR_H2V2:
- rate_ratio = HDMI_TX_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO;
- break;
- case MDP_Y_CBCR_H2V1:
- rate_ratio = HDMI_TX_YUV422_24BPP_PCLK_TMDS_CH_RATE_RATIO;
- break;
- default:
- rate_ratio = HDMI_TX_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO;
- break;
- }
-
- rate = timing->pixel_freq / rate_ratio;
-
- if (hdmi_tx_dc_support(hdmi_ctrl))
- rate += rate >> 2;
-
-end:
- return rate;
-}
-
static inline bool hdmi_tx_hw_is_cable_connected(struct hdmi_tx_ctrl *hdmi_ctrl)
{
return DSS_REG_R(&hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO],
@@ -3117,7 +3071,7 @@ static int hdmi_tx_power_on(struct hdmi_tx_ctrl *hdmi_ctrl)
void *pdata = hdmi_tx_get_fd(HDMI_TX_FEAT_PANEL);
void *edata = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID);
- hdmi_panel_get_vic(&panel_data->panel_info,
+ hdmi_ctrl->vic = hdmi_panel_get_vic(&panel_data->panel_info,
&hdmi_ctrl->ds_data);
if (hdmi_ctrl->vic <= 0) {
@@ -3144,16 +3098,14 @@ static int hdmi_tx_power_on(struct hdmi_tx_ctrl *hdmi_ctrl)
hdmi_ctrl->vic);
hdmi_ctrl->panel.scrambler = hdmi_edid_get_sink_scrambler_support(
edata);
+ hdmi_ctrl->panel.dc_enable = hdmi_tx_dc_support(hdmi_ctrl);
if (hdmi_ctrl->panel_ops.on)
hdmi_ctrl->panel_ops.on(pdata);
- pixel_clk = hdmi_ctrl->timing.pixel_freq * 1000;
-
- if (panel_data->panel_info.out_format == MDP_Y_CBCR_H2V2)
- pixel_clk >>= 1;
- else if (hdmi_tx_dc_support(hdmi_ctrl))
- pixel_clk += pixel_clk >> 2;
+ pixel_clk = hdmi_tx_setup_tmds_clk_rate(hdmi_ctrl->timing.pixel_freq,
+ hdmi_ctrl->panel.pinfo->out_format,
+ hdmi_ctrl->panel.dc_enable) * 1000;
DEV_DBG("%s: setting pixel clk %d\n", __func__, pixel_clk);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.c b/drivers/video/fbdev/msm/mdss_hdmi_util.c
index c9fc8ba8bfdb..89890bcf68df 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_util.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_util.c
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/delay.h>
+#include <linux/msm_mdp.h>
#include "mdss_hdmi_util.h"
#define RESOLUTION_NAME_STR_LEN 30
@@ -26,6 +27,10 @@
#define HDMI_SCDC_UNKNOWN_REGISTER "Unknown register"
+#define HDMI_TX_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO 2
+#define HDMI_TX_YUV422_24BPP_PCLK_TMDS_CH_RATE_RATIO 1
+#define HDMI_TX_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO 1
+
static char res_buf[RESOLUTION_NAME_STR_LEN];
enum trigger_mode {
@@ -738,6 +743,30 @@ ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf, u32 size)
return len;
} /* hdmi_get_video_3d_fmt_2string */
+int hdmi_tx_setup_tmds_clk_rate(u32 pixel_freq, u32 out_format, bool dc_enable)
+{
+ u32 rate_ratio;
+
+ switch (out_format) {
+ case MDP_Y_CBCR_H2V2:
+ rate_ratio = HDMI_TX_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO;
+ break;
+ case MDP_Y_CBCR_H2V1:
+ rate_ratio = HDMI_TX_YUV422_24BPP_PCLK_TMDS_CH_RATE_RATIO;
+ break;
+ default:
+ rate_ratio = HDMI_TX_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO;
+ break;
+ }
+
+ pixel_freq /= rate_ratio;
+
+ if (dc_enable)
+ pixel_freq += pixel_freq >> 2;
+
+ return pixel_freq;
+}
+
static void hdmi_ddc_trigger(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
enum trigger_mode mode, bool seg)
{
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.h b/drivers/video/fbdev/msm/mdss_hdmi_util.h
index 8a7e4d1ebafc..4fd659616bcc 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_util.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_util.h
@@ -16,6 +16,7 @@
#include "video/msm_hdmi_modes.h"
#include "mdss_panel.h"
+#include "mdss_hdmi_panel.h"
/* HDMI_TX Registers */
#define HDMI_CTRL (0x00000000)
@@ -495,6 +496,7 @@ bool hdmi_is_valid_resv_timing(int mode);
void hdmi_reset_resv_timing_info(void);
int hdmi_panel_get_vic(struct mdss_panel_info *pinfo,
struct hdmi_util_ds_data *ds_data);
+int hdmi_tx_setup_tmds_clk_rate(u32 pixel_freq, u32 out_format, bool dc_enable);
/* todo: Fix this. Right now this is defined in mdss_hdmi_tx.c */
void *hdmi_get_featuredata_from_sysfs_dev(struct device *device, u32 type);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 298b8743f0a6..6ba5828479f5 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -1453,6 +1453,21 @@ static void mdss_mdp_overlay_update_pm(struct mdss_overlay_private *mdp5_data)
activate_event_timer(mdp5_data->cpu_pm_hdl, wakeup_time);
}
+static void __unstage_pipe_and_clean_buf(struct msm_fb_data_type *mfd,
+ struct mdss_mdp_pipe *pipe, struct mdss_mdp_data *buf)
+{
+
+ pr_debug("unstaging pipe:%d rect:%d buf:%d\n",
+ pipe->num, pipe->multirect.num, !buf);
+ MDSS_XLOG(pipe->num, pipe->multirect.num, !buf);
+ mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
+ mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right);
+ pipe->dirty = true;
+
+ if (buf)
+ __pipe_buf_mark_cleanup(mfd, buf);
+}
+
static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
{
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
@@ -1573,14 +1588,36 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
ret = mdss_mdp_pipe_queue_data(pipe, buf);
if (IS_ERR_VALUE(ret)) {
- pr_warn("Unable to queue data for pnum=%d\n",
- pipe->num);
- mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left);
- mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_right);
- pipe->dirty = true;
+ pr_warn("Unable to queue data for pnum=%d rect=%d\n",
+ pipe->num, pipe->multirect.num);
+
+ /*
+ * If we fail for a multi-rect pipe, unstage both rects
+ * so we don't leave the pipe configured in multi-rect
+ * mode with only one rectangle staged.
+ */
+ if (pipe->multirect.mode !=
+ MDSS_MDP_PIPE_MULTIRECT_NONE) {
+ struct mdss_mdp_pipe *next_pipe =
+ (struct mdss_mdp_pipe *)
+ pipe->multirect.next;
+
+ if (next_pipe) {
+ struct mdss_mdp_data *next_buf =
+ list_first_entry_or_null(
+ &next_pipe->buf_queue,
+ struct mdss_mdp_data,
+ pipe_list);
+
+ __unstage_pipe_and_clean_buf(mfd,
+ next_pipe, next_buf);
+ } else {
+ pr_warn("cannot find rect pnum=%d\n",
+ pipe->num);
+ }
+ }
- if (buf)
- __pipe_buf_mark_cleanup(mfd, buf);
+ __unstage_pipe_and_clean_buf(mfd, pipe, buf);
}
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index bcf5309993b9..d7678e4d2ae5 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -2702,8 +2702,8 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
if (ret) {
pr_err("pipe pp setup error for pnum=%d\n", pipe->num);
- MDSS_XLOG(pipe->num, pipe->mixer_left->num,
- pipe->play_cnt, 0xbad);
+ MDSS_XLOG(pipe->num, pipe->multirect.num,
+ pipe->mixer_left->num, pipe->play_cnt, 0xbad);
goto done;
}
@@ -2714,13 +2714,14 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
pipe->params_changed = 0;
mdss_mdp_pipe_solidfill_setup(pipe);
- MDSS_XLOG(pipe->num, pipe->mixer_left->num, pipe->play_cnt,
- 0x111);
+ MDSS_XLOG(pipe->num, pipe->multirect.num, pipe->mixer_left->num,
+ pipe->play_cnt, 0x111);
goto update_nobuf;
}
- MDSS_XLOG(pipe->num, pipe->mixer_left->num, pipe->play_cnt, 0x222);
+ MDSS_XLOG(pipe->num, pipe->multirect.num, pipe->mixer_left->num,
+ pipe->play_cnt, 0x222);
if (params_changed) {
pipe->params_changed = 0;
diff --git a/include/dt-bindings/clock/audio-ext-clk.h b/include/dt-bindings/clock/audio-ext-clk.h
index 6e4932342751..c9a8286d7c7f 100644
--- a/include/dt-bindings/clock/audio-ext-clk.h
+++ b/include/dt-bindings/clock/audio-ext-clk.h
@@ -14,9 +14,19 @@
#define __AUDIO_EXT_CLK_H
/* Audio External Clocks */
+#ifdef CONFIG_COMMON_CLK_QCOM
+#define AUDIO_PMI_CLK 0
+#define AUDIO_PMIC_LNBB_CLK 1
+#define AUDIO_AP_CLK 2
+#define AUDIO_AP_CLK2 3
+#define AUDIO_LPASS_MCLK 4
+#define AUDIO_LPASS_MCLK2 5
+#else
#define clk_audio_ap_clk 0x9b5727cb
#define clk_audio_pmi_clk 0xcbfe416d
#define clk_audio_ap_clk2 0x454d1e91
#define clk_audio_lpass_mclk 0xf0f2a284
#define clk_audio_pmi_lnbb_clk 0x57312343
#endif
+
+#endif
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 06e00fdfe6a1..71858e268232 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -13681,6 +13681,7 @@ static int tasha_codec_probe(struct snd_soc_codec *codec)
snd_soc_dapm_ignore_suspend(dapm, "AIF Mix Playback");
snd_soc_dapm_ignore_suspend(dapm, "AIF4 MAD TX");
snd_soc_dapm_ignore_suspend(dapm, "VIfeed");
+ snd_soc_dapm_ignore_suspend(dapm, "AIF5 CPE TX");
}
snd_soc_dapm_sync(dapm);
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index aa036d352f40..9c720acf8ef8 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -2449,6 +2449,63 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
.name = "VoiceMMode2",
.probe = fe_dai_probe,
},
+ {
+ .capture = {
+ .stream_name = "MultiMedia17 Capture",
+ .aif_name = "MM_UL17",
+ .rates = (SNDRV_PCM_RATE_8000_48000|
+ SNDRV_PCM_RATE_KNOT),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE),
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_Multimedia_dai_ops,
+ .compress_new = snd_soc_new_compress,
+ .name = "MultiMedia17",
+ .probe = fe_dai_probe,
+ },
+ {
+ .capture = {
+ .stream_name = "MultiMedia18 Capture",
+ .aif_name = "MM_UL18",
+ .rates = (SNDRV_PCM_RATE_8000_48000|
+ SNDRV_PCM_RATE_KNOT),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE),
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_Multimedia_dai_ops,
+ .compress_new = snd_soc_new_compress,
+ .name = "MultiMedia18",
+ .probe = fe_dai_probe,
+ },
+ {
+ .capture = {
+ .stream_name = "MultiMedia19 Capture",
+ .aif_name = "MM_UL19",
+ .rates = (SNDRV_PCM_RATE_8000_48000|
+ SNDRV_PCM_RATE_KNOT),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE),
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_Multimedia_dai_ops,
+ .compress_new = snd_soc_new_compress,
+ .name = "MultiMedia19",
+ .probe = fe_dai_probe,
+ },
};
static int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index a2cd6c6f98db..90371b8e27f4 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -127,6 +127,11 @@ struct msm_compr_audio {
uint64_t bytes_received; /* from userspace */
uint64_t bytes_sent; /* to DSP */
+ 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*/
+
int32_t first_buffer;
int32_t last_buffer;
int32_t partial_drain_delay;
@@ -362,6 +367,49 @@ static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
return 0;
}
+static int msm_compr_read_buffer(struct msm_compr_audio *prtd)
+{
+ int buffer_length;
+ uint64_t bytes_available;
+ uint64_t buffer_sent;
+ struct audio_aio_read_param param;
+ int ret;
+
+ if (!atomic_read(&prtd->start)) {
+ pr_err("%s: stream is not in started state\n", __func__);
+ return -EINVAL;
+ }
+
+ buffer_length = prtd->codec_param.buffer.fragment_size;
+ bytes_available = prtd->received_total - prtd->bytes_copied;
+ buffer_sent = prtd->bytes_read - prtd->bytes_copied;
+ if (buffer_sent + buffer_length > 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.len = buffer_length;
+ param.uid = buffer_length;
+
+ pr_debug("%s: reading %d bytes from DSP byte_offset = %llu\n",
+ __func__, buffer_length, prtd->bytes_read);
+ ret = q6asm_async_read(prtd->audio_client, &param);
+ if (ret < 0) {
+ pr_err("%s: q6asm_async_read failed - %d\n",
+ __func__, ret);
+ return ret;
+ }
+ prtd->bytes_read += buffer_length;
+ prtd->bytes_read_offset += buffer_length;
+ if (prtd->bytes_read_offset >= prtd->buffer_size)
+ prtd->bytes_read_offset -= prtd->buffer_size;
+
+ return 0;
+}
+
static void compr_event_handler(uint32_t opcode,
uint32_t token, uint32_t *payload, void *priv)
{
@@ -374,6 +422,7 @@ static void compr_event_handler(uint32_t opcode,
int stream_id;
uint32_t stream_index;
unsigned long flags;
+ uint64_t read_size;
if (!prtd) {
pr_err("%s: prtd is NULL\n", __func__);
@@ -459,6 +508,32 @@ static void compr_event_handler(uint32_t opcode,
spin_unlock_irqrestore(&prtd->lock, flags);
break;
+
+ case ASM_DATA_EVENT_READ_DONE_V2:
+ spin_lock_irqsave(&prtd->lock, flags);
+
+ pr_debug("ASM_DATA_EVENT_READ_DONE_V2 offset %d, length %d\n",
+ prtd->byte_offset, payload[4]);
+ /* Always assume read_size is same as fragment_size */
+ read_size = prtd->codec_param.buffer.fragment_size;
+ prtd->byte_offset += read_size;
+ prtd->received_total += read_size;
+ if (prtd->byte_offset >= prtd->buffer_size)
+ prtd->byte_offset -= prtd->buffer_size;
+
+ snd_compr_fragment_elapsed(cstream);
+
+ if (!atomic_read(&prtd->start)) {
+ pr_debug("read_done received while not started, treat as xrun");
+ atomic_set(&prtd->xrun, 1);
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ break;
+ }
+ msm_compr_read_buffer(prtd);
+
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ break;
+
case ASM_DATA_EVENT_RENDERED_EOS:
spin_lock_irqsave(&prtd->lock, flags);
pr_debug("%s: ASM_DATA_CMDRSP_EOS token 0x%x,stream id %d\n",
@@ -511,6 +586,14 @@ static void compr_event_handler(uint32_t opcode,
/* FIXME: A state is a better way, dealing with this*/
spin_lock_irqsave(&prtd->lock, flags);
+
+ if (cstream->direction == SND_COMPRESS_CAPTURE) {
+ atomic_set(&prtd->start, 1);
+ msm_compr_read_buffer(prtd);
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ break;
+ }
+
if (!prtd->bytes_sent) {
bytes_available = prtd->bytes_received - prtd->copied_total;
if (bytes_available < cstream->runtime->fragment_size) {
@@ -958,7 +1041,8 @@ static int msm_compr_init_pp_params(struct snd_compr_stream *cstream,
return ret;
}
-static int msm_compr_configure_dsp(struct snd_compr_stream *cstream)
+static int msm_compr_configure_dsp_for_playback
+ (struct snd_compr_stream *cstream)
{
struct snd_compr_runtime *runtime = cstream->runtime;
struct msm_compr_audio *prtd = runtime->private_data;
@@ -1096,7 +1180,103 @@ static int msm_compr_configure_dsp(struct snd_compr_stream *cstream)
return ret;
}
-static int msm_compr_open(struct snd_compr_stream *cstream)
+static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
+{
+ struct snd_compr_runtime *runtime = cstream->runtime;
+ struct msm_compr_audio *prtd = runtime->private_data;
+ struct snd_soc_pcm_runtime *soc_prtd = cstream->private_data;
+ uint16_t bits_per_sample;
+ uint16_t sample_word_size;
+ int dir = OUT, ret = 0;
+ struct audio_client *ac = prtd->audio_client;
+ uint32_t stream_index;
+
+ switch (prtd->codec_param.codec.format) {
+ case SNDRV_PCM_FORMAT_S24_LE:
+ bits_per_sample = 24;
+ sample_word_size = 32;
+ break;
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ bits_per_sample = 24;
+ sample_word_size = 24;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ bits_per_sample = 32;
+ sample_word_size = 32;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ bits_per_sample = 16;
+ sample_word_size = 16;
+ break;
+ }
+
+ 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,
+ bits_per_sample);
+ if (ret < 0) {
+ pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret);
+ return ret;
+ }
+
+ ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+ ac->perf_mode,
+ prtd->session_id,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret) {
+ pr_err("%s: stream reg failed:%d\n", __func__, ret);
+ return ret;
+ }
+
+ ret = q6asm_set_io_mode(ac, (COMPRESSED_STREAM_IO | ASYNC_IO_MODE));
+ if (ret < 0) {
+ pr_err("%s: Set IO mode failed\n", __func__);
+ return -EINVAL;
+ }
+
+ stream_index = STREAM_ARRAY_INDEX(ac->stream_id);
+ if (stream_index >= MAX_NUMBER_OF_STREAMS || stream_index < 0) {
+ pr_err("%s: Invalid stream index:%d", __func__, stream_index);
+ return -EINVAL;
+ }
+
+ runtime->fragments = prtd->codec_param.buffer.fragments;
+ runtime->fragment_size = prtd->codec_param.buffer.fragment_size;
+ pr_debug("%s: allocate %d buffers each of size %d\n",
+ __func__, runtime->fragments,
+ runtime->fragment_size);
+ ret = q6asm_audio_client_buf_alloc_contiguous(dir, ac,
+ runtime->fragment_size,
+ runtime->fragments);
+ if (ret < 0) {
+ pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
+ return -ENOMEM;
+ }
+
+ prtd->byte_offset = 0;
+ prtd->received_total = 0;
+ prtd->app_pointer = 0;
+ prtd->bytes_copied = 0;
+ prtd->bytes_read = 0;
+ prtd->bytes_read_offset = 0;
+ prtd->buffer = ac->port[dir].buf[0].data;
+ prtd->buffer_paddr = ac->port[dir].buf[0].phys;
+ prtd->buffer_size = runtime->fragments * runtime->fragment_size;
+
+
+ pr_debug("%s: sample_rate = %d channels = %d bps = %d sample_word_size = %d\n",
+ __func__, prtd->sample_rate, prtd->num_channels,
+ bits_per_sample, sample_word_size);
+ ret = q6asm_enc_cfg_blk_pcm_format_support_v3(prtd->audio_client,
+ prtd->sample_rate, prtd->num_channels,
+ bits_per_sample, sample_word_size);
+
+ return ret;
+}
+
+static int msm_compr_playback_open(struct snd_compr_stream *cstream)
{
struct snd_compr_runtime *runtime = cstream->runtime;
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
@@ -1181,15 +1361,80 @@ static int msm_compr_open(struct snd_compr_stream *cstream)
kfree(prtd);
return -ENOMEM;
}
+ pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
+ prtd->audio_client->perf_mode = false;
+ prtd->session_id = prtd->audio_client->session;
+
+ return 0;
+}
+static int msm_compr_capture_open(struct snd_compr_stream *cstream)
+{
+ struct snd_compr_runtime *runtime = cstream->runtime;
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct msm_compr_audio *prtd;
+ struct msm_compr_pdata *pdata =
+ snd_soc_platform_get_drvdata(rtd->platform);
+
+ pr_debug("%s\n", __func__);
+ prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
+ if (prtd == NULL) {
+ pr_err("Failed to allocate memory for msm_compr_audio\n");
+ return -ENOMEM;
+ }
+
+ runtime->private_data = NULL;
+ prtd->cstream = cstream;
+ pdata->cstream[rtd->dai_link->be_id] = cstream;
+
+ prtd->audio_client = q6asm_audio_client_alloc(
+ (app_cb)compr_event_handler, prtd);
+ if (!prtd->audio_client) {
+ pr_err("%s: Could not allocate memory for client\n", __func__);
+ pdata->cstream[rtd->dai_link->be_id] = NULL;
+ kfree(prtd);
+ return -ENOMEM;
+ }
pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
prtd->audio_client->perf_mode = false;
prtd->session_id = prtd->audio_client->session;
+ prtd->codec = FORMAT_LINEAR_PCM;
+ prtd->bytes_copied = 0;
+ prtd->bytes_read = 0;
+ prtd->bytes_read_offset = 0;
+ prtd->received_total = 0;
+ prtd->byte_offset = 0;
+ prtd->sample_rate = 48000;
+ prtd->num_channels = 2;
+ prtd->first_buffer = 0;
+
+ spin_lock_init(&prtd->lock);
+
+ atomic_set(&prtd->eos, 0);
+ atomic_set(&prtd->start, 0);
+ atomic_set(&prtd->drain, 0);
+ atomic_set(&prtd->xrun, 0);
+ atomic_set(&prtd->close, 0);
+ atomic_set(&prtd->wait_on_close, 0);
+ atomic_set(&prtd->error, 0);
+
+ runtime->private_data = prtd;
return 0;
}
-static int msm_compr_free(struct snd_compr_stream *cstream)
+static int msm_compr_open(struct snd_compr_stream *cstream)
+{
+ int ret = 0;
+
+ if (cstream->direction == SND_COMPRESS_PLAYBACK)
+ ret = msm_compr_playback_open(cstream);
+ else if (cstream->direction == SND_COMPRESS_CAPTURE)
+ ret = msm_compr_capture_open(cstream);
+ return ret;
+}
+
+static int msm_compr_playback_free(struct snd_compr_stream *cstream)
{
struct snd_compr_runtime *runtime;
struct msm_compr_audio *prtd;
@@ -1284,6 +1529,76 @@ static int msm_compr_free(struct snd_compr_stream *cstream)
return 0;
}
+static int msm_compr_capture_free(struct snd_compr_stream *cstream)
+{
+ struct snd_compr_runtime *runtime;
+ struct msm_compr_audio *prtd;
+ struct snd_soc_pcm_runtime *soc_prtd;
+ struct msm_compr_pdata *pdata;
+ struct audio_client *ac;
+ int dir = OUT, stream_id;
+ unsigned long flags;
+ uint32_t stream_index;
+
+ if (!cstream) {
+ pr_err("%s cstream is null\n", __func__);
+ return 0;
+ }
+ runtime = cstream->runtime;
+ soc_prtd = cstream->private_data;
+ if (!runtime || !soc_prtd || !(soc_prtd->platform)) {
+ pr_err("%s runtime or soc_prtd or platform is null\n",
+ __func__);
+ return 0;
+ }
+ prtd = runtime->private_data;
+ if (!prtd) {
+ pr_err("%s prtd is null\n", __func__);
+ return 0;
+ }
+ pdata = snd_soc_platform_get_drvdata(soc_prtd->platform);
+ ac = prtd->audio_client;
+ if (!pdata || !ac) {
+ pr_err("%s pdata or ac is null\n", __func__);
+ return 0;
+ }
+
+ spin_lock_irqsave(&prtd->lock, flags);
+ stream_id = ac->stream_id;
+
+ stream_index = STREAM_ARRAY_INDEX(stream_id);
+ if ((stream_index < MAX_NUMBER_OF_STREAMS && stream_index >= 0)) {
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ pr_debug("close stream %d", stream_id);
+ q6asm_stream_cmd(ac, CMD_CLOSE, stream_id);
+ spin_lock_irqsave(&prtd->lock, flags);
+ }
+ spin_unlock_irqrestore(&prtd->lock, flags);
+
+ pdata->cstream[soc_prtd->dai_link->be_id] = NULL;
+ msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
+ SNDRV_PCM_STREAM_CAPTURE);
+
+ q6asm_audio_client_buf_free_contiguous(dir, ac);
+
+ q6asm_audio_client_free(ac);
+
+ kfree(prtd);
+
+ return 0;
+}
+
+static int msm_compr_free(struct snd_compr_stream *cstream)
+{
+ int ret = 0;
+
+ if (cstream->direction == SND_COMPRESS_PLAYBACK)
+ ret = msm_compr_playback_free(cstream);
+ else if (cstream->direction == SND_COMPRESS_CAPTURE)
+ ret = msm_compr_capture_free(cstream);
+ return ret;
+}
+
static bool msm_compr_validate_codec_compr(__u32 codec_id)
{
int32_t i;
@@ -1449,7 +1764,10 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
prtd->partial_drain_delay =
msm_compr_get_partial_drain_delay(frame_sz, prtd->sample_rate);
- ret = msm_compr_configure_dsp(cstream);
+ if (cstream->direction == SND_COMPRESS_PLAYBACK)
+ ret = msm_compr_configure_dsp_for_playback(cstream);
+ else if (cstream->direction == SND_COMPRESS_CAPTURE)
+ ret = msm_compr_configure_dsp_for_capture(cstream);
return ret;
}
@@ -1539,11 +1857,6 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
uint32_t stream_index;
uint16_t bits_per_sample = 16;
- if (cstream->direction != SND_COMPRESS_PLAYBACK) {
- pr_err("%s: Unsupported stream type\n", __func__);
- return -EINVAL;
- }
-
spin_lock_irqsave(&prtd->lock, flags);
if (atomic_read(&prtd->error)) {
pr_err("%s Got RESET EVENTS notification, return immediately",
@@ -1566,7 +1879,8 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
* compress passthrough volume is controlled in
* ADM by adm_send_compressed_device_mute()
*/
- if (prtd->compr_passthr == LEGACY_PCM) {
+ if (prtd->compr_passthr == LEGACY_PCM &&
+ cstream->direction == SND_COMPRESS_PLAYBACK) {
/* set volume for the stream before RUN */
rc = msm_compr_set_volume(cstream,
volume[0], volume[1]);
@@ -1578,8 +1892,9 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
if (rc)
pr_err("%s : init PP params failed : %d\n",
__func__, rc);
+ } else {
+ msm_compr_read_buffer(prtd);
}
-
/* issue RUN command for the stream */
q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
break;
@@ -1589,6 +1904,18 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
prtd->gapless_state.gapless_transition);
stream_id = ac->stream_id;
atomic_set(&prtd->start, 0);
+ if (cstream->direction == SND_COMPRESS_CAPTURE) {
+ q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
+ atomic_set(&prtd->xrun, 0);
+ prtd->received_total = 0;
+ prtd->bytes_copied = 0;
+ prtd->bytes_read = 0;
+ prtd->bytes_read_offset = 0;
+ prtd->byte_offset = 0;
+ prtd->app_pointer = 0;
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ break;
+ }
if (prtd->next_stream) {
pr_debug("%s: interrupt next track wait queues\n",
__func__);
@@ -1979,7 +2306,7 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
}
static int msm_compr_pointer(struct snd_compr_stream *cstream,
- struct snd_compr_tstamp *arg)
+ struct snd_compr_tstamp *arg)
{
struct snd_compr_runtime *runtime = cstream->runtime;
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
@@ -1998,7 +2325,10 @@ static int msm_compr_pointer(struct snd_compr_stream *cstream,
spin_lock_irqsave(&prtd->lock, flags);
tstamp.sampling_rate = prtd->sample_rate;
tstamp.byte_offset = prtd->byte_offset;
- tstamp.copied_total = prtd->copied_total;
+ if (cstream->direction == SND_COMPRESS_PLAYBACK)
+ tstamp.copied_total = prtd->copied_total;
+ else if (cstream->direction == SND_COMPRESS_CAPTURE)
+ tstamp.copied_total = prtd->received_total;
first_buffer = prtd->first_buffer;
if (atomic_read(&prtd->error)) {
pr_err("%s Got RESET EVENTS notification, return error\n",
@@ -2012,37 +2342,39 @@ static int msm_compr_pointer(struct snd_compr_stream *cstream,
spin_unlock_irqrestore(&prtd->lock, flags);
return -ENETRESET;
}
+ if (cstream->direction == SND_COMPRESS_PLAYBACK) {
- gapless_transition = prtd->gapless_state.gapless_transition;
- spin_unlock_irqrestore(&prtd->lock, flags);
-
- if (gapless_transition)
- pr_debug("%s session time in gapless transition",
- __func__);
-
- /*
- - Do not query if no buffer has been given.
- - Do not query on a gapless transition.
- Playback for the 2nd stream can start (thus returning time
- starting from 0) before the driver knows about EOS of first stream.
- */
-
- if (!first_buffer && !gapless_transition) {
- if (pdata->use_legacy_api)
- rc = q6asm_get_session_time_legacy(prtd->audio_client,
- &prtd->marker_timestamp);
- else
- rc = q6asm_get_session_time(prtd->audio_client,
- &prtd->marker_timestamp);
+ gapless_transition = prtd->gapless_state.gapless_transition;
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ if (gapless_transition)
+ pr_debug("%s session time in gapless transition",
+ __func__);
+ /*
+ *- Do not query if no buffer has been given.
+ *- Do not query on a gapless transition.
+ * Playback for the 2nd stream can start (thus returning time
+ * starting from 0) before the driver knows about EOS of first
+ * stream.
+ */
+ if (!first_buffer || gapless_transition) {
- if (rc < 0) {
- pr_err("%s: Get Session Time return value =%lld\n",
- __func__, timestamp);
- if (atomic_read(&prtd->error))
- return -ENETRESET;
+ if (pdata->use_legacy_api)
+ rc = q6asm_get_session_time_legacy(
+ prtd->audio_client, &prtd->marker_timestamp);
else
- return -EAGAIN;
+ rc = q6asm_get_session_time(
+ prtd->audio_client, &prtd->marker_timestamp);
+ if (rc < 0) {
+ pr_err("%s: Get Session Time return =%lld\n",
+ __func__, timestamp);
+ if (atomic_read(&prtd->error))
+ return -ENETRESET;
+ else
+ return -EAGAIN;
+ }
}
+ } else {
+ spin_unlock_irqrestore(&prtd->lock, flags);
}
timestamp = prtd->marker_timestamp;
@@ -2103,8 +2435,8 @@ static int msm_compr_ack(struct snd_compr_stream *cstream,
return 0;
}
-static int msm_compr_copy(struct snd_compr_stream *cstream,
- char __user *buf, size_t count)
+static int msm_compr_playback_copy(struct snd_compr_stream *cstream,
+ char __user *buf, size_t count)
{
struct snd_compr_runtime *runtime = cstream->runtime;
struct msm_compr_audio *prtd = runtime->private_data;
@@ -2166,6 +2498,60 @@ static int msm_compr_copy(struct snd_compr_stream *cstream,
return count;
}
+static int msm_compr_capture_copy(struct snd_compr_stream *cstream,
+ char __user *buf, size_t count)
+{
+ struct snd_compr_runtime *runtime = cstream->runtime;
+ struct msm_compr_audio *prtd = runtime->private_data;
+ void *source;
+ unsigned long flags;
+
+ pr_debug("%s: count = %zd\n", __func__, count);
+ if (!prtd->buffer) {
+ pr_err("%s: Buffer is not allocated yet ??", __func__);
+ return 0;
+ }
+
+ spin_lock_irqsave(&prtd->lock, flags);
+ if (atomic_read(&prtd->error)) {
+ pr_err("%s Got RESET EVENTS notification", __func__);
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ return -ENETRESET;
+ }
+
+ source = prtd->buffer + prtd->app_pointer;
+ /* check if we have requested amount of data to copy to user*/
+ if (count <= prtd->received_total - prtd->bytes_copied) {
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ if (copy_to_user(buf, source, count)) {
+ pr_err("copy_to_user failed");
+ return -EFAULT;
+ }
+ spin_lock_irqsave(&prtd->lock, flags);
+ prtd->app_pointer += count;
+ if (prtd->app_pointer >= prtd->buffer_size)
+ prtd->app_pointer -= prtd->buffer_size;
+ prtd->bytes_copied += count;
+ }
+ msm_compr_read_buffer(prtd);
+
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ return count;
+}
+
+static int msm_compr_copy(struct snd_compr_stream *cstream,
+ char __user *buf, size_t count)
+{
+ int ret = 0;
+
+ pr_debug(" In %s\n", __func__);
+ if (cstream->direction == SND_COMPRESS_PLAYBACK)
+ ret = msm_compr_playback_copy(cstream, buf, count);
+ else if (cstream->direction == SND_COMPRESS_CAPTURE)
+ ret = msm_compr_capture_copy(cstream, buf, count);
+ return ret;
+}
+
static int msm_compr_get_caps(struct snd_compr_stream *cstream,
struct snd_compr_caps *arg)
{
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 9164475386ff..a456cc2ab857 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -548,6 +548,15 @@ static struct msm_pcm_routing_fdai_data
/* MULTIMEDIA16 */
{{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+ /* MULTIMEDIA17 */
+ {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
+ {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+ /* MULTIMEDIA18 */
+ {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
+ {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
+ /* MULTIMEDIA19 */
+ {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} },
+ {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } },
};
static unsigned long session_copp_map[MSM_FRONTEND_DAI_MM_SIZE][2]
@@ -2288,6 +2297,21 @@ static const struct snd_kcontrol_new ext_ec_ref_mux_ul9 =
msm_route_ec_ref_rx_enum[0],
msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put);
+static const struct snd_kcontrol_new ext_ec_ref_mux_ul17 =
+ SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL17 MUX Mux",
+ msm_route_ec_ref_rx_enum[0],
+ msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put);
+
+static const struct snd_kcontrol_new ext_ec_ref_mux_ul18 =
+ SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL18 MUX Mux",
+ msm_route_ec_ref_rx_enum[0],
+ msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put);
+
+static const struct snd_kcontrol_new ext_ec_ref_mux_ul19 =
+ SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL19 MUX Mux",
+ msm_route_ec_ref_rx_enum[0],
+ msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put);
+
static int msm_routing_ext_ec_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -2417,6 +2441,15 @@ static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = {
@@ -2468,6 +2501,15 @@ static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new spdif_rx_mixer_controls[] = {
@@ -2519,6 +2561,16 @@ static const struct snd_kcontrol_new spdif_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SPDIF_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_SPDIF_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_SPDIF_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SPDIF_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+
};
static const struct snd_kcontrol_new slimbus_2_rx_mixer_controls[] = {
@@ -2621,6 +2673,15 @@ static const struct snd_kcontrol_new slimbus_5_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SLIMBUS_5_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_SLIMBUS_5_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_SLIMBUS_5_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SLIMBUS_5_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
@@ -2672,6 +2733,15 @@ static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = {
@@ -2723,6 +2793,15 @@ static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_MI2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new quaternary_mi2s_rx_mixer_controls[] = {
@@ -2774,6 +2853,15 @@ static const struct snd_kcontrol_new quaternary_mi2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new quinary_mi2s_rx_mixer_controls[] = {
@@ -2825,6 +2913,15 @@ static const struct snd_kcontrol_new quinary_mi2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_QUINARY_MI2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_QUINARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_QUINARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_QUINARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = {
@@ -2870,6 +2967,15 @@ static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new secondary_mi2s_rx2_mixer_controls[] = {
@@ -2927,6 +3033,15 @@ static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = {
@@ -2978,6 +3093,15 @@ static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_PRI_MI2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_PRI_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_PRI_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_PRI_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new int0_mi2s_rx_mixer_controls[] = {
@@ -3131,6 +3255,15 @@ static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new display_port_mixer_controls[] = {
@@ -3432,6 +3565,15 @@ static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_INT_BT_SCO_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new int_bt_a2dp_rx_mixer_controls[] = {
@@ -3534,6 +3676,15 @@ static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_INT_FM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_INT_FM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_INT_FM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_INT_FM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
@@ -3585,6 +3736,15 @@ static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
@@ -3636,6 +3796,15 @@ static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
@@ -3687,6 +3856,15 @@ static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new tert_auxpcm_rx_mixer_controls[] = {
@@ -5018,6 +5196,77 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = {
msm_routing_put_audio_mixer),
};
+static const struct snd_kcontrol_new mmul17_mixer_controls[] = {
+ SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("VOC_REC_DL", MSM_BACKEND_DAI_INCALL_RECORD_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+
+static const struct snd_kcontrol_new mmul18_mixer_controls[] = {
+ SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("VOC_REC_DL", MSM_BACKEND_DAI_INCALL_RECORD_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+
+static const struct snd_kcontrol_new mmul19_mixer_controls[] = {
+ SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("VOC_REC_DL", MSM_BACKEND_DAI_INCALL_RECORD_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -8098,6 +8347,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL9", "MultiMedia9 Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL17", "MultiMedia17 Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL18", "MultiMedia18 Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL19", "MultiMedia19 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VOICE2_DL", "Voice2 Playback", 0, 0, 0, 0),
@@ -8796,6 +9048,12 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
mmul6_mixer_controls, ARRAY_SIZE(mmul6_mixer_controls)),
SND_SOC_DAPM_MIXER("MultiMedia8 Mixer", SND_SOC_NOPM, 0, 0,
mmul8_mixer_controls, ARRAY_SIZE(mmul8_mixer_controls)),
+ SND_SOC_DAPM_MIXER("MultiMedia17 Mixer", SND_SOC_NOPM, 0, 0,
+ mmul17_mixer_controls, ARRAY_SIZE(mmul17_mixer_controls)),
+ SND_SOC_DAPM_MIXER("MultiMedia18 Mixer", SND_SOC_NOPM, 0, 0,
+ mmul18_mixer_controls, ARRAY_SIZE(mmul18_mixer_controls)),
+ SND_SOC_DAPM_MIXER("MultiMedia19 Mixer", SND_SOC_NOPM, 0, 0,
+ mmul19_mixer_controls, ARRAY_SIZE(mmul19_mixer_controls)),
SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -9060,6 +9318,12 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
&ext_ec_ref_mux_ul8),
SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL9 MUX", SND_SOC_NOPM, 0, 0,
&ext_ec_ref_mux_ul9),
+ SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL17 MUX", SND_SOC_NOPM, 0, 0,
+ &ext_ec_ref_mux_ul17),
+ SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL18 MUX", SND_SOC_NOPM, 0, 0,
+ &ext_ec_ref_mux_ul18),
+ SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL19 MUX", SND_SOC_NOPM, 0, 0,
+ &ext_ec_ref_mux_ul19),
};
static const struct snd_soc_dapm_route intercon[] = {
@@ -9287,9 +9551,15 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MultiMedia8 Mixer", "SLIM_6_TX", "SLIMBUS_6_TX"},
{"MultiMedia8 Mixer", "SLIM_7_TX", "SLIMBUS_7_TX"},
{"MultiMedia4 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"MultiMedia17 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"MultiMedia18 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"MultiMedia19 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia8 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia2 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
{"MultiMedia4 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
+ {"MultiMedia17 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
+ {"MultiMedia18 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
+ {"MultiMedia19 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
{"MultiMedia8 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
{"MultiMedia3 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia5 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
@@ -9884,10 +10154,16 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
{"MultiMedia3 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
{"MultiMedia4 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+ {"MultiMedia17 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+ {"MultiMedia18 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+ {"MultiMedia19 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
{"MultiMedia5 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
{"MultiMedia8 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
{"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MultiMedia4 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+ {"MultiMedia17 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+ {"MultiMedia18 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+ {"MultiMedia19 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MultiMedia5 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MultiMedia6 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MultiMedia8 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
@@ -9895,6 +10171,9 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
{"MultiMedia3 Mixer", "AFE_PCM_TX", "PCM_TX"},
{"MultiMedia4 Mixer", "AFE_PCM_TX", "PCM_TX"},
+ {"MultiMedia17 Mixer", "AFE_PCM_TX", "PCM_TX"},
+ {"MultiMedia18 Mixer", "AFE_PCM_TX", "PCM_TX"},
+ {"MultiMedia19 Mixer", "AFE_PCM_TX", "PCM_TX"},
{"MultiMedia5 Mixer", "AFE_PCM_TX", "PCM_TX"},
{"MultiMedia8 Mixer", "AFE_PCM_TX", "PCM_TX"},
{"MM_UL1", NULL, "MultiMedia1 Mixer"},
@@ -9905,6 +10184,9 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MM_UL5", NULL, "MultiMedia5 Mixer"},
{"MM_UL6", NULL, "MultiMedia6 Mixer"},
{"MM_UL8", NULL, "MultiMedia8 Mixer"},
+ {"MM_UL17", NULL, "MultiMedia17 Mixer"},
+ {"MM_UL18", NULL, "MultiMedia18 Mixer"},
+ {"MM_UL19", NULL, "MultiMedia19 Mixer"},
{"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -10284,6 +10566,21 @@ static const struct snd_soc_dapm_route intercon[] = {
{"AUDIO_REF_EC_UL9 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"},
{"AUDIO_REF_EC_UL9 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"},
+ {"AUDIO_REF_EC_UL17 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"},
+ {"AUDIO_REF_EC_UL17 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"},
+ {"AUDIO_REF_EC_UL17 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+ {"AUDIO_REF_EC_UL17 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
+
+ {"AUDIO_REF_EC_UL18 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"},
+ {"AUDIO_REF_EC_UL18 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"},
+ {"AUDIO_REF_EC_UL18 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+ {"AUDIO_REF_EC_UL18 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
+
+ {"AUDIO_REF_EC_UL19 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"},
+ {"AUDIO_REF_EC_UL19 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"},
+ {"AUDIO_REF_EC_UL19 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+ {"AUDIO_REF_EC_UL19 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
+
{"MM_UL1", NULL, "AUDIO_REF_EC_UL1 MUX"},
{"MM_UL2", NULL, "AUDIO_REF_EC_UL2 MUX"},
{"MM_UL3", NULL, "AUDIO_REF_EC_UL3 MUX"},
@@ -10292,6 +10589,9 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MM_UL6", NULL, "AUDIO_REF_EC_UL6 MUX"},
{"MM_UL8", NULL, "AUDIO_REF_EC_UL8 MUX"},
{"MM_UL9", NULL, "AUDIO_REF_EC_UL9 MUX"},
+ {"MM_UL17", NULL, "AUDIO_REF_EC_UL17 MUX"},
+ {"MM_UL18", NULL, "AUDIO_REF_EC_UL18 MUX"},
+ {"MM_UL19", NULL, "AUDIO_REF_EC_UL19 MUX"},
{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
{"Voice_Tx Mixer", "PRI_MI2S_TX_Voice", "PRI_MI2S_TX"},
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 4fdfd6bb936d..d64fd640618e 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -182,6 +182,9 @@ enum {
MSM_FRONTEND_DAI_MULTIMEDIA14,
MSM_FRONTEND_DAI_MULTIMEDIA15,
MSM_FRONTEND_DAI_MULTIMEDIA16,
+ MSM_FRONTEND_DAI_MULTIMEDIA17,
+ MSM_FRONTEND_DAI_MULTIMEDIA18,
+ MSM_FRONTEND_DAI_MULTIMEDIA19,
MSM_FRONTEND_DAI_CS_VOICE,
MSM_FRONTEND_DAI_VOIP,
MSM_FRONTEND_DAI_AFE_RX,
@@ -207,8 +210,8 @@ enum {
MSM_FRONTEND_DAI_MAX,
};
-#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA16 + 1)
-#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA16
+#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA19 + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA19
enum {
MSM_BACKEND_DAI_PRI_I2S_RX = 0,