Merge "msm: pil: Add memory map tracking logic"
diff --git a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
index 5f18893..c1b79ae 100644
--- a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
+++ b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
@@ -41,6 +41,17 @@
The EXPORT_COMPAT is to ensure that memory is only carved out if the
driver is actually enabled, otherwise the memory will not be used.
+If a reservation is needed that isn't associated directly with any one
+driver, the compatible string "qcom,msm-contig-mem" can be used. For
+example:
+
+ qcom,msm-contig-mem {
+ compatible = "qcom,msm-contig-mem";
+ qcom,memory-reservation-type = "EBI1";
+ qcom,memory-reservation-size = <0x280000>; /* 2.5M EBI1 buffer */
+ };
+
+
In order to specify the size and address of the fixed memory which has
previously been removed the memory-fixed binding can be used. This assumes
that the region has been removed by a separate memblock-remove property
diff --git a/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt b/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
new file mode 100644
index 0000000..b429072
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
@@ -0,0 +1,28 @@
+* MSM PM-8x60
+
+PM-8x60 is the low power management device for MSM (Snapdragon class) chipsets.
+This device sets up different components to do low power modes and registers with
+the kernel to be notified of idle and suspend states and when called, follows
+through the set of instructions in putting the application cores to the lowest
+power mode possible.
+
+The required properties for PM-8x60 are:
+
+- compatible: "qcom,pm-8x60"
+
+The optional properties are:
+
+- qcom,use-sync-timer: Indicates whether the target uses the synchronized QTimer.
+- qcom,pc-mode: Indicates the type of power collapse used by the target. The
+ valid values for this are:
+ 0 (Power collapse terminates in TZ; integrated L2 cache controller)
+ 1, (Power collapse doesn't terminate in TZ; external L2 cache controller)
+ 2 (Power collapse terminates in TZ; external L2 cache controller)
+
+Example:
+
+qcom,pm-8x60 {
+ compatible = "qcom,pm-8x60";
+ qcom,pc-mode = <0>;
+ qcom,use-sync-timer;
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
index 88fca69..bcea355 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
@@ -29,6 +29,8 @@
needed
- atmel,need-calibration : specify to indicate whether calibration is
needed during wakeup.
+ - atmel,no-force-update : flag that signifies whether force configuration
+ update is applicable or not
Example:
i2c@f9966000 {
@@ -52,7 +54,8 @@
vcc_i2c-supply = <&pm8941_lvs1>;
atmel,panel-coords = <0 0 479 799>;
atmel,display-coords = <0 0 479 799>;
- atmel,i2c-pull-up = <1>;
+ atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,dig-reg-support;
atmel,key-codes = <
102 139 0 0 0 0 0 0
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index ed4a81d..6004d15 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -39,7 +39,8 @@
atmel,irq-gpio = <&msmgpio 61 0x00>;
atmel,panel-coords = <0 0 760 1424>;
atmel,display-coords = <0 0 720 1280>;
- atmel,i2c-pull-up = <1>;
+ atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,cfg_1 {
atmel,family-id = <0x82>;
atmel,variant-id = <0x19>;
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 39926e2..93f92c7 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -39,7 +39,8 @@
atmel,irq-gpio = <&msmgpio 61 0x00>;
atmel,panel-coords = <0 0 760 1424>;
atmel,display-coords = <0 0 720 1280>;
- atmel,i2c-pull-up = <1>;
+ atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,cfg_1 {
atmel,family-id = <0x82>;
atmel,variant-id = <0x19>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index ae28fb3..e882c17 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -78,7 +78,8 @@
atmel,irq-gpio = <&msmgpio 61 0x00>;
atmel,panel-coords = <0 0 1080 1920>;
atmel,display-coords = <0 0 1080 1920>;
- atmel,i2c-pull-up = <1>;
+ atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,cfg_1 {
atmel,family-id = <0xa2>;
atmel,variant-id = <0x00>;
@@ -393,4 +394,4 @@
qcom,src-sel = <0>; /* CONSTANT */
qcom,master-en = <1>; /* ENABLE MPP */
};
-};
\ No newline at end of file
+};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index c50f650..f4be0dc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -39,7 +39,8 @@
atmel,irq-gpio = <&msmgpio 61 0x00>;
atmel,panel-coords = <0 0 760 1424>;
atmel,display-coords = <0 0 720 1280>;
- atmel,i2c-pull-up = <1>;
+ atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,cfg_1 {
atmel,family-id = <0x82>;
atmel,variant-id = <0x19>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index dcd6e11..467c7ac 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1052,6 +1052,12 @@
qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
};
+ qcom,msm-contig-mem {
+ compatible = "qcom,msm-contig-mem";
+ qcom,memory-reservation-type = "EBI1";
+ qcom,memory-reservation-size = <0x280000>; /* 2.5M EBI1 buffer */
+ };
+
qcom,qcedev@fd440000 {
compatible = "qcom,qcedev";
reg = <0xfd440000 0x20000>,
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
new file mode 100644
index 0000000..86e0cf7
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -0,0 +1,207 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ qcom,spm@f9009000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9009000 0x1000>;
+ qcom,core-id = <0>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x101>;
+ qcom,saw2-spm-dly= <0>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [04 03 04 0f];
+ qcom,saw2-spm-cmd-spc = [34 04 44 14 24 54 03 54 44 14 04 24
+ 3e 0f];
+ qcom,saw2-spm-cmd-pc = [34 04 44 14 24 54 07 54 44 14 04 24
+ 3e 0f];
+ };
+
+ qcom,lpm-resources {
+ compatible = "qcom,lpm-resources";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,lpm-resources@0 {
+ reg = <0x0>;
+ qcom,name = "vdd-dig";
+ qcom,resource-type = <0>;
+ qcom,type = <0x616F646C>; /* "ldoa" */
+ qcom,id = <0x0A>;
+ qcom,key = <0x6e726f63>; /* "corn" */
+ };
+
+ qcom,lpm-resources@1 {
+ reg = <0x1>;
+ qcom,name = "vdd-mem";
+ qcom,resource-type = <0>;
+ qcom,type = <0x616F646C>; /* "ldoa" */
+ qcom,id = <0x0C>;
+ qcom,key = <0x7675>; /* "uv" */
+ };
+
+ qcom,lpm-resources@2 {
+ reg = <0x2>;
+ qcom,name = "pxo";
+ qcom,resource-type = <0>;
+ qcom,type = <0x306b6c63>; /* "clk0" */
+ qcom,id = <0x00>;
+ qcom,key = <0x62616e45>; /* "Enab" */
+ };
+ };
+
+ qcom,lpm-levels {
+ compatible = "qcom,lpm-levels";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,lpm-level@0 {
+ reg = <0x0>;
+ qcom,mode = <0>; /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <3>; /* ACTIVE */
+ qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
+ qcom,latency-us = <100>;
+ qcom,ss-power = <8000>;
+ qcom,energy-overhead = <100000>;
+ qcom,time-overhead = <1>;
+ };
+
+ qcom,lpm-level@1 {
+ reg = <0x1>;
+ qcom,mode = <2>; /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <3>; /* ACTIVE */
+ qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
+ qcom,latency-us = <2000>;
+ qcom,ss-power = <5000>;
+ qcom,energy-overhead = <60100000>;
+ qcom,time-overhead = <3000>;
+ };
+
+ qcom,lpm-level@2 {
+ reg = <0x2>;
+ qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <1>; /* GDHS */
+ qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
+ qcom,latency-us = <3500>;
+ qcom,ss-power = <5000>;
+ qcom,energy-overhead = <60350000>;
+ qcom,time-overhead = <6300>;
+ };
+
+ qcom,lpm-level@3 {
+ reg = <0x3>;
+ qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <0>; /* OFF */
+ qcom,l2 = <0>; /* OFF */
+ qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
+ qcom,latency-us = <6800>;
+ qcom,ss-power = <2000>;
+ qcom,energy-overhead = <71850000>;
+ qcom,time-overhead = <13300>;
+ };
+
+ qcom,lpm-level@4 {
+ reg = <0x4>;
+ qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <0>; /* OFF */
+ qcom,l2 = <0>; /* OFF */
+ qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
+ qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
+ qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
+ qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
+ qcom,latency-us = <9800>;
+ qcom,ss-power = <0>;
+ qcom,energy-overhead = <76350000>;
+ qcom,time-overhead = <28300>;
+ };
+ };
+
+ qcom,pm-boot {
+ compatible = "qcom,pm-boot";
+ qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+ };
+
+ qcom,mpm@fc4281d0 {
+ compatible = "qcom,mpm-v2";
+ reg = <0xfc4281d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+ <0xf9011008 0x4>; /* MSM_APCS_GCC_BASE 4K */
+ reg-names = "vmpm", "ipc";
+ interrupts = <0 171 1>;
+
+ qcom,ipc-bit-offset = <1>;
+
+ qcom,gic-parent = <&intc>;
+ qcom,gic-map = <41 172>, /* usb2_hsic_async_wakeup_irq */
+ <0xff 208>; /* summary_irq_kpss */
+
+ qcom,gpio-parent = <&msmgpio>;
+ qcom,gpio-map = <4 1>,
+ <5 5>,
+ <6 9>,
+ <7 18>,
+ <8 20>,
+ <9 24>,
+ <10 27>,
+ <11 28>,
+ <12 34>,
+ <13 35>,
+ <14 37>,
+ <15 42>,
+ <16 44>,
+ <17 46>,
+ <18 50>,
+ <19 54>,
+ <20 59>,
+ <21 61>,
+ <22 62>,
+ <23 64>,
+ <24 65>,
+ <25 66>,
+ <26 67>,
+ <27 68>,
+ <28 71>,
+ <29 72>,
+ <30 73>,
+ <31 74>,
+ <32 75>,
+ <33 77>,
+ <34 79>,
+ <35 80>,
+ <36 82>,
+ <37 86>;
+ };
+
+ qcom,pm-8x60 {
+ compatible = "qcom,pm-8x60";
+ qcom,pc-mode = <2>; /*MSM_PC_TZ_L2_EXT */
+ qcom,use-sync-timer;
+ };
+};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 0ebeb9c..0a349f7 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -12,6 +12,7 @@
/include/ "skeleton.dtsi"
/include/ "msm9625-ion.dtsi"
+/include/ "msm9625-pm.dtsi"
/ {
model = "Qualcomm MSM 9625";
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 98c1ede..23b4527 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -275,6 +275,7 @@
CONFIG_QPNP_BMS=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_SENSORS_EPM_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8974=y
CONFIG_THERMAL_QPNP=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 328a4dc..1a03b5b 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -276,6 +276,7 @@
CONFIG_QPNP_BMS=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_SENSORS_EPM_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8974=y
CONFIG_THERMAL_QPNP=y
diff --git a/arch/arm/mach-msm/avs.h b/arch/arm/mach-msm/avs.h
index a549e9d..e87bded 100644
--- a/arch/arm/mach-msm/avs.h
+++ b/arch/arm/mach-msm/avs.h
@@ -37,7 +37,8 @@
u32 avs_get_avsdscr(void);
u32 avs_get_tscsr(void);
void avs_set_tscsr(u32 to_tscsr);
-void avs_disable(void);
+u32 avs_disable(void);
+void avs_enable(u32 avscsr);
#else
static inline u32 avs_reset_delays(u32 avsdscr)
{ return 0; }
@@ -48,7 +49,9 @@
static inline u32 avs_get_tscsr(void)
{ return 0; }
static inline void avs_set_tscsr(u32 to_tscsr) {}
-static inline void avs_disable(void) {}
+static inline u32 avs_disable(void)
+{return 0; }
+static inline void avs_enable(u32 avscsr) {}
#endif
/*#define AVSDEBUG(x...) pr_info("AVS: " x);*/
@@ -60,9 +63,13 @@
put_cpu(); \
} while (0);
+/* AVSCSR(0x61) to enable CPU, V and L2 AVS module */
+
#define AVS_ENABLE(cpu, x) do { \
- if (get_cpu() == (cpu)) \
+ if (get_cpu() == (cpu)) { \
avs_reset_delays((x)); \
+ avs_enable(0x61); \
+ } \
put_cpu(); \
} while (0);
diff --git a/arch/arm/mach-msm/avs_hw.S b/arch/arm/mach-msm/avs_hw.S
index 1cc3ce0..efb9c47 100644
--- a/arch/arm/mach-msm/avs_hw.S
+++ b/arch/arm/mach-msm/avs_hw.S
@@ -102,23 +102,23 @@
/* Read r0=AVSDSCR */
mrc p15, 7, r0, c15, c0, 6
-
-/* AVSCSR(0x61) to enable CPU, V and L2 AVS module */
- mov r3, #0x61
- mcr p15, 7, r3, c15, c1, 7
-
bx lr
-
+ .global avs_enable
+avs_enable:
+/* Restore the avs_scr register */
+ mcr p15, 7, r0, c15, c1, 7
+ bx lr
.global avs_disable
avs_disable:
+/* Get the AVSCSR value */
+ mrc p15, 7, r0, c15, c1, 7
/* Clear AVSCSR */
- mov r0, #0
-
+ mov r1, #0
/* Write AVSCSR */
- mcr p15, 7, r0, c15, c1, 7
+ mcr p15, 7, r1, c15, c1, 7
bx lr
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index def9b76..98a82b1 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -49,17 +49,6 @@
#include "modem_notifier.h"
#include "lpm_resources.h"
-#define MSM_KERNEL_EBI1_MEM_SIZE 0x280000
-
-#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
-static unsigned kernel_ebi1_mem_size = MSM_KERNEL_EBI1_MEM_SIZE;
-static int __init kernel_ebi1_mem_size_setup(char *p)
-{
- kernel_ebi1_mem_size = memparse(p, NULL);
- return 0;
-}
-early_param("kernel_ebi1_mem_size", kernel_ebi1_mem_size_setup);
-#endif
static struct memtype_reserve msm8974_reserve_table[] __initdata = {
[MEMTYPE_SMI] = {
@@ -77,13 +66,6 @@
return MEMTYPE_EBI1;
}
-static void __init reserve_ebi_memory(void)
-{
-#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
- msm8974_reserve_table[MEMTYPE_EBI1].size += kernel_ebi1_mem_size;
-#endif
-}
-
static struct resource smd_resource[] = {
{
.name = "modem_smd_in",
@@ -246,14 +228,8 @@
}
};
-static void __init msm8974_calculate_reserve_sizes(void)
-{
- reserve_ebi_memory();
-}
-
static struct reserve_info msm8974_reserve_info __initdata = {
.memtype_reserve_table = msm8974_reserve_table,
- .calculate_reserve_sizes = msm8974_calculate_reserve_sizes,
.paddr_to_memtype = msm8974_paddr_to_memtype,
};
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index b9da615..2f3ab7f 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -939,6 +939,7 @@
&msm9615_rpm_stat_device,
&msm9615_rpm_master_stat_device,
&msm_tsens_device,
+ &msm9615_pm_8x60,
};
static void __init msm9615_i2c_init(void)
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index fe3a4d5..7307f62 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1421,6 +1421,19 @@
},
};
+static struct msm_pm_init_data_type msm_pm_data = {
+ .use_sync_timer = false,
+ .pc_mode = MSM_PM_PC_NOTZ_L2_EXT,
+};
+
+struct platform_device msm9615_pm_8x60 = {
+ .name = "pm-8x60",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_pm_data,
+ },
+};
+
uint32_t __init msm9615_rpm_get_swfi_latency(void)
{
int i;
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 97adb35..16b4eee 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -109,6 +109,8 @@
extern struct platform_device msm_device_sdc3;
extern struct platform_device msm_device_sdc4;
+extern struct platform_device msm9615_pm_8x60;
+
extern struct platform_device msm8960_pc_cntr;
extern struct platform_device msm8064_pc_cntr;
extern struct platform_device msm8930_pc_cntr;
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 1d8f313..ccd0bf7 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -22,7 +22,7 @@
#include "idle.h"
#include "idle-macros.S"
-#ifdef CONFIG_ARCH_MSM_KRAIT
+#ifdef CONFIG_MSM_SCM
#define SCM_SVC_BOOT 0x1
#define SCM_CMD_TERMINATE_PC 0x2
#endif
@@ -127,7 +127,18 @@
cmp r1, #1
bne skip
bl v7_flush_dcache_all
+ ldr r1, =msm_pm_flush_l2_fn
+ ldr r1, [r1]
+ cmp r1, #0
+ blxne r1
+
skip:
+ ldr r1, =msm_pm_disable_l2_fn
+ ldr r1, [r1]
+ cmp r1, #0
+ blxne r1
+ dmb
+
mrc p15, 0, r0, c0, c0, 5 /* MPIDR */
and r0, r0, #15 /* what CPU am I */
@@ -141,7 +152,7 @@
str r2, [r1]
skip_pc_debug1:
-#ifdef CONFIG_ARCH_MSM_KRAIT
+#ifdef CONFIG_MSM_SCM
ldr r0, =SCM_SVC_BOOT
ldr r1, =SCM_CMD_TERMINATE_PC
ldr r2, =msm_pm_flush_l2_flag
@@ -182,6 +193,11 @@
str r2, [r1]
skip_pc_debug2:
+ ldr r1, =msm_pm_enable_l2_fn
+ ldr r1, [r1]
+ cmp r1, #0
+ blxne r1
+ dmb
#ifdef CONFIG_MSM_JTAG
bl msm_jtag_restore_state
@@ -286,11 +302,16 @@
SET_SMP_COHERENCY ON
#endif
-#ifdef CONFIG_MSM_JTAG
+ ldr r1, =msm_pm_enable_l2_fn
+ ldr r1, [r1]
+ cmp r1, #0
stmfd sp!, {lr}
+ blxne r1
+ dmb
+#ifdef CONFIG_MSM_JTAG
bl msm_jtag_restore_state
- ldmfd sp!, {lr}
#endif
+ ldmfd sp!, {lr}
mov r0, #1
bx lr
nop
@@ -377,6 +398,18 @@
msm_pc_debug_counters:
.long 0x0
+ .globl msm_pm_enable_l2_fn
+msm_pm_enable_l2_fn:
+ .long 0x0
+
+ .globl msm_pm_disable_l2_fn
+msm_pm_disable_l2_fn:
+ .long 0x0
+
+ .globl msm_pm_flush_l2_fn
+msm_pm_flush_l2_fn:
+ .long 0x0
+
/*
* Default the l2 flush flag to 1 so that caches are flushed during power
* collapse unless the L2 driver decides to flush them only during L2
diff --git a/arch/arm/mach-msm/idle.h b/arch/arm/mach-msm/idle.h
index 7a939ab..ee3209c 100644
--- a/arch/arm/mach-msm/idle.h
+++ b/arch/arm/mach-msm/idle.h
@@ -33,6 +33,9 @@
int msm_pm_collapse(void);
void msm_pm_collapse_exit(void);
extern void *msm_saved_state;
+extern void (*msm_pm_disable_l2_fn)(void);
+extern void (*msm_pm_enable_l2_fn)(void);
+extern void (*msm_pm_flush_l2_fn)(void);
extern unsigned long msm_saved_state_phys;
#ifdef CONFIG_CPU_V7
diff --git a/arch/arm/mach-msm/include/mach/bam_dmux.h b/arch/arm/mach-msm/include/mach/bam_dmux.h
index f02a882..f11b72c 100644
--- a/arch/arm/mach-msm/include/mach/bam_dmux.h
+++ b/arch/arm/mach-msm/include/mach/bam_dmux.h
@@ -28,6 +28,18 @@
BAM_DMUX_DATA_RMNET_6,
BAM_DMUX_DATA_RMNET_7,
BAM_DMUX_USB_RMNET_0,
+ BAM_DMUX_RESERVED_0, /* 9..11 are reserved*/
+ BAM_DMUX_RESERVED_1,
+ BAM_DMUX_RESERVED_2,
+ BAM_DMUX_DATA_REV_RMNET_0,
+ BAM_DMUX_DATA_REV_RMNET_1,
+ BAM_DMUX_DATA_REV_RMNET_2,
+ BAM_DMUX_DATA_REV_RMNET_3,
+ BAM_DMUX_DATA_REV_RMNET_4,
+ BAM_DMUX_DATA_REV_RMNET_5,
+ BAM_DMUX_DATA_REV_RMNET_6,
+ BAM_DMUX_DATA_REV_RMNET_7,
+ BAM_DMUX_DATA_REV_RMNET_8,
BAM_DMUX_NUM_CHANNELS
};
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 7d7380b..3fe65b8 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -464,3 +464,8 @@
return ret;
}
+
+/* Provide a string that anonymous device tree allocations (those not
+ * directly associated with any driver) can use for their "compatible"
+ * field */
+EXPORT_COMPAT("qcom,msm-contig-mem");
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index f55d509..2eac6b7 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -35,7 +35,7 @@
#include <asm/hardware/gic.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
-#include <asm/hardware/cache-l2x0.h>
+#include <asm/outercache.h>
#ifdef CONFIG_VFP
#include <asm/vfp.h>
#endif
@@ -114,6 +114,7 @@
"standalone_power_collapse",
};
+static struct msm_pm_init_data_type msm_pm_init_data;
static struct hrtimer pm_hrtimer;
static struct msm_pm_sleep_ops pm_sleep_ops;
/*
@@ -473,7 +474,6 @@
}
static void *msm_pm_idle_rs_limits;
-static bool msm_pm_use_qtimer;
static void msm_pm_swfi(void)
{
@@ -499,24 +499,6 @@
msm_pm_config_hw_after_retention();
}
-#ifdef CONFIG_CACHE_L2X0
-static inline bool msm_pm_l2x0_power_collapse(void)
-{
- bool collapsed = 0;
-
- l2cc_suspend();
- collapsed = msm_pm_collapse();
- l2cc_resume();
-
- return collapsed;
-}
-#else
-static inline bool msm_pm_l2x0_power_collapse(void)
-{
- return msm_pm_collapse();
-}
-#endif
-
static bool __ref msm_pm_spm_power_collapse(
unsigned int cpu, bool from_idle, bool notify_rpm)
{
@@ -547,7 +529,7 @@
#ifdef CONFIG_VFP
vfp_pm_suspend();
#endif
- collapsed = msm_pm_l2x0_power_collapse();
+ collapsed = msm_pm_collapse();
msm_pm_boot_config_after_pc(cpu);
@@ -576,11 +558,13 @@
{
unsigned int cpu = smp_processor_id();
unsigned int avsdscr_setting;
+ unsigned int avscsr_enable;
bool collapsed;
avsdscr_setting = avs_get_avsdscr();
- avs_disable();
+ avscsr_enable = avs_disable();
collapsed = msm_pm_spm_power_collapse(cpu, from_idle, false);
+ avs_enable(avscsr_enable);
avs_reset_delays(avsdscr_setting);
return collapsed;
}
@@ -590,6 +574,7 @@
unsigned int cpu = smp_processor_id();
unsigned long saved_acpuclk_rate;
unsigned int avsdscr_setting;
+ unsigned int avscsr_enable;
bool collapsed;
if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
@@ -601,7 +586,7 @@
pr_info("CPU%u: %s: pre power down\n", cpu, __func__);
avsdscr_setting = avs_get_avsdscr();
- avs_disable();
+ avscsr_enable = avs_disable();
if (cpu_online(cpu))
saved_acpuclk_rate = acpuclk_power_collapse();
@@ -643,6 +628,7 @@
}
+ avs_enable(avscsr_enable);
avs_reset_delays(avsdscr_setting);
msm_pm_config_hw_after_power_up();
if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
@@ -657,14 +643,11 @@
{
if (cpu_is_apq8064())
msm_pm_save_cp15 = true;
-
- if (cpu_is_msm8974())
- msm_pm_use_qtimer = true;
}
static int64_t msm_pm_timer_enter_idle(void)
{
- if (msm_pm_use_qtimer)
+ if (msm_pm_init_data.use_sync_timer)
return ktime_to_ns(tick_nohz_get_sleep_length());
return msm_timer_enter_idle();
@@ -672,7 +655,7 @@
static void msm_pm_timer_exit_idle(bool timer_halted)
{
- if (msm_pm_use_qtimer)
+ if (msm_pm_init_data.use_sync_timer)
return;
msm_timer_exit_idle((int) timer_halted);
@@ -682,7 +665,7 @@
{
int64_t time = 0;
- if (msm_pm_use_qtimer)
+ if (msm_pm_init_data.use_sync_timer)
return sched_clock();
time = msm_timer_get_sclk_time(period);
@@ -694,7 +677,7 @@
static int64_t msm_pm_timer_exit_suspend(int64_t time, int64_t period)
{
- if (msm_pm_use_qtimer)
+ if (msm_pm_init_data.use_sync_timer)
return sched_clock() - time;
if (time != 0) {
@@ -1165,3 +1148,73 @@
}
late_initcall(msm_pm_init);
+
+static void __devinit msm_pm_set_flush_fn(uint32_t pc_mode)
+{
+ msm_pm_disable_l2_fn = NULL;
+ msm_pm_enable_l2_fn = NULL;
+ msm_pm_flush_l2_fn = outer_flush_all;
+
+ if (pc_mode == MSM_PM_PC_NOTZ_L2_EXT) {
+ msm_pm_disable_l2_fn = outer_disable;
+ msm_pm_enable_l2_fn = outer_resume;
+ }
+}
+
+static int __devinit msm_pm_8x60_probe(struct platform_device *pdev)
+{
+ char *key = NULL;
+ uint32_t val = 0;
+ int ret = 0;
+
+ if (!pdev->dev.of_node) {
+ struct msm_pm_init_data_type *d = pdev->dev.platform_data;
+
+ if (!d)
+ goto pm_8x60_probe_done;
+
+ msm_pm_init_data.pc_mode = d->pc_mode;
+ msm_pm_set_flush_fn(msm_pm_init_data.pc_mode);
+ msm_pm_init_data.use_sync_timer = d->use_sync_timer;
+ } else {
+ key = "qcom,pc-mode";
+ ret = of_property_read_u32(pdev->dev.of_node, key, &val);
+
+ if (ret) {
+ pr_debug("%s: Cannot read %s,defaulting to 0",
+ __func__, key);
+ val = MSM_PM_PC_TZ_L2_INT;
+ ret = 0;
+ }
+
+ msm_pm_init_data.pc_mode = val;
+ msm_pm_set_flush_fn(msm_pm_init_data.pc_mode);
+
+ key = "qcom,use-sync-timer";
+ msm_pm_init_data.use_sync_timer =
+ of_property_read_bool(pdev->dev.of_node, key);
+ }
+
+pm_8x60_probe_done:
+ return ret;
+}
+
+static struct of_device_id msm_pm_8x60_table[] = {
+ {.compatible = "qcom,pm-8x60"},
+ {},
+};
+
+static struct platform_driver msm_pm_8x60_driver = {
+ .probe = msm_pm_8x60_probe,
+ .driver = {
+ .name = "pm-8x60",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_pm_8x60_table,
+ },
+};
+
+static int __init msm_pm_8x60_init(void)
+{
+ return platform_driver_register(&msm_pm_8x60_driver);
+}
+module_init(msm_pm_8x60_init);
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index 51256ca..faefe34 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -87,6 +87,20 @@
bool notify_rpm, bool collapsed);
};
+enum msm_pm_pc_mode_type {
+ MSM_PM_PC_TZ_L2_INT = 0, /*Power collapse terminates in TZ;
+ integrated L2 cache controller */
+ MSM_PM_PC_NOTZ_L2_EXT = 1, /* Power collapse doesn't terminate in
+ TZ; external L2 cache controller */
+ MSM_PM_PC_TZ_L2_EXT = 2, /* Power collapse terminates in TZ;
+ external L2 cache controller */
+};
+
+struct msm_pm_init_data_type {
+ enum msm_pm_pc_mode_type pc_mode;
+ bool use_sync_timer;
+};
+
struct msm_pm_cpr_ops {
void (*cpr_suspend)(void);
void (*cpr_resume)(void);
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index bec19e2..f9d0316 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -38,6 +38,7 @@
/* Command identifiers */
#define KGSL_CONTEXT_TO_MEM_IDENTIFIER 0x2EADBEEF
#define KGSL_CMD_IDENTIFIER 0x2EEDFACE
+#define KGSL_CMD_INTERNAL_IDENTIFIER 0x2EEDD00D
#define KGSL_START_OF_IB_IDENTIFIER 0x2EADEABE
#define KGSL_END_OF_IB_IDENTIFIER 0x2ABEDEAD
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index daa78ed..e069fa5 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -70,6 +70,14 @@
{CP_WAIT_FOR_IDLE, "WAIT4IDL"},
};
+static const struct pm_id_name pm3_nop_values[] = {
+ {KGSL_CONTEXT_TO_MEM_IDENTIFIER, "CTX_SWCH"},
+ {KGSL_CMD_IDENTIFIER, "CMD__EXT"},
+ {KGSL_CMD_INTERNAL_IDENTIFIER, "CMD__INT"},
+ {KGSL_START_OF_IB_IDENTIFIER, "IB_START"},
+ {KGSL_END_OF_IB_IDENTIFIER, "IB___END"},
+};
+
static uint32_t adreno_is_pm4_len(uint32_t word)
{
if (word == INVALID_RB_CMD)
@@ -129,6 +137,28 @@
return "????????";
}
+static bool adreno_is_pm3_nop_value(uint32_t word)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pm3_nop_values); ++i) {
+ if (word == pm3_nop_values[i].id)
+ return 1;
+ }
+ return 0;
+}
+
+static const char *adreno_pm3_nop_name(uint32_t word)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pm3_nop_values); ++i) {
+ if (word == pm3_nop_values[i].id)
+ return pm3_nop_values[i].name;
+ }
+ return "????????";
+}
+
static void adreno_dump_regs(struct kgsl_device *device,
const int *registers, int size)
{
@@ -245,8 +275,13 @@
"%s", adreno_pm4_name(ptr4[j]));
*argp = -(adreno_is_pm4_len(ptr4[j])+1);
} else {
- lx += scnprintf(linebuf + lx, linebuflen - lx,
- "%8.8X", ptr4[j]);
+ if (adreno_is_pm3_nop_value(ptr4[j]))
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%s", adreno_pm3_nop_name(ptr4[j]));
+ else
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%8.8X", ptr4[j]);
+
if (*argp > 1)
--*argp;
else if (*argp == 1) {
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index da9daf7..e5a790f 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -524,6 +524,9 @@
total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
/* 2 dwords to store the start of command sequence */
total_sizedwords += 2;
+ /* internal ib command identifier for the ringbuffer */
+ total_sizedwords += (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) ? 2 : 0;
+
/*
* Add CP_COND_EXEC commands to generate CP_INTERRUPT only
* for submissions from userspace.
@@ -560,6 +563,11 @@
GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
+ if (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) {
+ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
+ GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_INTERNAL_IDENTIFIER);
+ }
+
if (flags & KGSL_CMD_FLAGS_PMODE) {
/* disable protected mode error checking */
GSL_RB_WRITE(ringcmds, rcmd_gpu,
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index f671806..b3bd8a0 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -363,6 +363,7 @@
int t38_start_addr;
bool update_cfg;
const char *fw_name;
+ bool no_force_update;
};
static struct dentry *debug_base;
@@ -984,9 +985,9 @@
continue;
}
- /* check whether report id is part of T9 or T15 */
id = reportid - data->t9_min_reportid;
+ /* check whether report id is part of T9,T15 or T42*/
if (reportid >= data->t9_min_reportid &&
reportid <= data->t9_max_reportid)
mxt_input_touchevent(data, &message, id);
@@ -1273,25 +1274,18 @@
data->cfg_version[0], data->cfg_version[1],
data->cfg_version[2]);
- /* It is possible that the config data on the controller is not
- * versioned and the version number returns 0. In this case,
- * find a match without the config version checking.
- */
- error = mxt_search_config_array(data,
- data->cfg_version[0] != 0 ? true : false);
+ /* configuration update requires major match */
+ error = mxt_search_config_array(data, true);
+
+ /* if no_force_update is false , try again with false
+ as the second parameter to mxt_search_config_array */
+ if (error && (data->no_force_update == false))
+ error = mxt_search_config_array(data, false);
+
if (error) {
- /* If a match wasn't found for a non-zero config version,
- * it means the controller has the wrong config data. Search
- * for a best match based on controller and firmware version,
- * but not config version.
- */
- if (data->cfg_version[0])
- error = mxt_search_config_array(data, false);
- if (error) {
- dev_err(dev,
- "Unable to find matching config in pdata\n");
- return error;
- }
+ dev_err(dev,
+ "Unable to find matching config in pdata\n");
+ return error;
}
return 0;
@@ -1418,13 +1412,62 @@
return 0;
}
+static int mxt_update_cfg(struct mxt_data *data)
+{
+ int error;
+ const u8 *cfg_ver;
+
+ /* Get config data from platform data */
+ error = mxt_get_config(data);
+ if (error)
+ dev_dbg(&data->client->dev, "Config info not found.\n");
+
+ /* Check register init values */
+ if (data->config_info && data->config_info->config) {
+ if (data->update_cfg) {
+ error = mxt_check_reg_init(data);
+ if (error) {
+ dev_err(&data->client->dev,
+ "Failed to check reg init value\n");
+ return error;
+ }
+
+ error = mxt_backup_nv(data);
+ if (error) {
+ dev_err(&data->client->dev, "Failed to back up NV\n");
+ return error;
+ }
+
+ cfg_ver = data->config_info->config +
+ data->cfg_version_idx;
+ dev_info(&data->client->dev,
+ "Config updated from %d.%d.%d to %d.%d.%d\n",
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2],
+ cfg_ver[0], cfg_ver[1], cfg_ver[2]);
+
+ memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
+ }
+ } else {
+ dev_info(&data->client->dev,
+ "No cfg data defined, skipping check reg init\n");
+ }
+
+ error = mxt_save_objects(data);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+
+
static int mxt_initialize(struct mxt_data *data)
{
struct i2c_client *client = data->client;
struct mxt_info *info = &data->info;
int error;
u8 val;
- const u8 *cfg_ver;
error = mxt_get_info(data);
if (error) {
@@ -1465,46 +1508,9 @@
if (error)
goto free_object_table;
- /* Get config data from platform data */
- error = mxt_get_config(data);
- if (error)
- dev_dbg(&client->dev, "Config info not found.\n");
-
- /* Check register init values */
- if (data->config_info && data->config_info->config) {
- if (data->update_cfg) {
- error = mxt_check_reg_init(data);
- if (error) {
- dev_err(&client->dev,
- "Failed to check reg init value\n");
- goto free_object_table;
- }
-
- error = mxt_backup_nv(data);
- if (error) {
- dev_err(&client->dev, "Failed to back up NV\n");
- goto free_object_table;
- }
-
- cfg_ver = data->config_info->config +
- data->cfg_version_idx;
- dev_info(&client->dev,
- "Config updated from %d.%d.%d to %d.%d.%d\n",
- data->cfg_version[0], data->cfg_version[1],
- data->cfg_version[2],
- cfg_ver[0], cfg_ver[1], cfg_ver[2]);
-
- memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
- }
- } else {
- dev_info(&client->dev,
- "No cfg data defined, skipping check reg init\n");
- }
-
- error = mxt_save_objects(data);
+ error = mxt_update_cfg(data);
if (error)
goto free_object_table;
-
/* Update matrix size at info struct */
error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
if (error)
@@ -1732,6 +1738,30 @@
return fw_name;
}
+static ssize_t mxt_force_cfg_update_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mxt_data *data = dev_get_drvdata(dev);
+ int flag = buf[0]-'0';
+ int error;
+ data->no_force_update = !flag;
+
+ if (data->state == APPMODE) {
+ disable_irq(data->irq);
+ error = mxt_update_cfg(data);
+ enable_irq(data->irq);
+ if (error)
+ return error;
+ } else {
+ dev_err(dev,
+ "Not in APPMODE, Unable to force cfg update\n");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
static ssize_t mxt_update_fw_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -1742,7 +1772,7 @@
u8 bootldr_id;
u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
-
+ data->no_force_update = false;
/* If fw_name is set, then the existing firmware has an upgrade */
if (!data->fw_name) {
/*
@@ -1824,10 +1854,12 @@
static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
+static DEVICE_ATTR(force_cfg_update, 0664, NULL, mxt_force_cfg_update_store);
static struct attribute *mxt_attrs[] = {
&dev_attr_object.attr,
&dev_attr_update_fw.attr,
+ &dev_attr_force_cfg_update.attr,
NULL
};
@@ -2433,6 +2465,10 @@
pdata->i2c_pull_up = of_property_read_bool(np, "atmel,i2c-pull-up");
pdata->digital_pwr_regulator = of_property_read_bool(np,
"atmel,dig-reg-support");
+
+ pdata->no_force_update = of_property_read_bool(np,
+ "atmel,no-force-update");
+
/* reset, irq gpio info */
pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
0, &pdata->reset_gpio_flags);
@@ -2583,6 +2619,7 @@
data->client = client;
data->input_dev = input_dev;
data->pdata = pdata;
+ data->no_force_update = pdata->no_force_update;
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index ac143b1..fde7cb7 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -39,6 +39,17 @@
#include <asm/unaligned.h>
static unsigned int rds_buf = 100;
+static int oda_agt;
+static int grp_mask;
+static int rt_plus_carrier = -1;
+static int ert_carrier = -1;
+static unsigned char ert_buf[256];
+static unsigned char ert_len;
+static unsigned char c_byt_pair_index;
+static char utf_8_flag;
+static char rt_ert_flag;
+static char formatting_dir;
+
module_param(rds_buf, uint, 0);
MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
@@ -108,7 +119,11 @@
static struct video_device *priv_videodev;
static int iris_do_calibration(struct iris_device *radio);
-
+static void hci_buff_ert(struct iris_device *radio,
+ struct rds_grp_data *rds_buf);
+static void hci_ev_rt_plus(struct iris_device *radio,
+ struct rds_grp_data rds_buf);
+static void hci_ev_ert(struct iris_device *radio);
static int update_spur_table(struct iris_device *radio);
static struct v4l2_queryctrl iris_v4l2_queryctrl[] = {
{
@@ -921,6 +936,20 @@
return radio_hci_send_cmd(hdev, opcode, 0, NULL);
}
+static int hci_fm_rds_grp_mask_req(struct radio_hci_dev *hdev,
+ unsigned long param)
+{
+ __u16 opcode = 0;
+
+ struct hci_fm_rds_grp_req *fm_grp_mask =
+ (struct hci_fm_rds_grp_req *)param;
+
+ opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+ HCI_OCF_FM_RDS_GRP);
+ return radio_hci_send_cmd(hdev, opcode, sizeof(*fm_grp_mask),
+ fm_grp_mask);
+}
+
static int hci_fm_rds_grp_process_req(struct radio_hci_dev *hdev,
unsigned long param)
{
@@ -1313,7 +1342,13 @@
static int hci_fm_rds_grp(struct hci_fm_rds_grp_req *arg,
struct radio_hci_dev *hdev)
{
- return 0;
+ int ret = 0;
+ struct hci_fm_rds_grp_req *fm_grp_mask = arg;
+
+ ret = radio_hci_request(hdev, hci_fm_rds_grp_mask_req, (unsigned
+ long)fm_grp_mask, RADIO_HCI_TIMEOUT);
+
+ return ret;
}
static int hci_fm_rds_grps_process(__u32 *arg, struct radio_hci_dev *hdev)
@@ -2078,6 +2113,234 @@
iris_q_event(radio, IRIS_EVT_MONO);
}
+static void hci_ev_raw_rds_group_data(struct radio_hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct iris_device *radio;
+ unsigned char blocknum, index;
+ struct rds_grp_data temp;
+ unsigned int mask_bit;
+ unsigned short int aid, agt, gtc;
+ unsigned short int carrier;
+
+ radio = video_get_drvdata(video_get_dev());
+ index = RDSGRP_DATA_OFFSET;
+
+ for (blocknum = 0; blocknum < RDS_BLOCKS_NUM; blocknum++) {
+ temp.rdsBlk[blocknum].rdsLsb =
+ (skb->data[index]);
+ temp.rdsBlk[blocknum].rdsMsb =
+ (skb->data[index+1]);
+ index = index + 2;
+ }
+
+ aid = AID(temp.rdsBlk[3].rdsLsb, temp.rdsBlk[3].rdsMsb);
+ gtc = GTC(temp.rdsBlk[1].rdsMsb);
+ agt = AGT(temp.rdsBlk[1].rdsLsb);
+
+ if (gtc == GRP_3A) {
+ switch (aid) {
+ case ERT_AID:
+ /* calculate the grp mask for RDS grp
+ * which will contain actual eRT text
+ *
+ * Bit Pos 0 1 2 3 4 5 6 7
+ * Grp Type 0A 0B 1A 1B 2A 2B 3A 3B
+ *
+ * similary for rest grps
+ */
+ mask_bit = (((agt >> 1) << 1) + (agt & 1));
+ oda_agt = (1 << mask_bit);
+ utf_8_flag = (temp.rdsBlk[2].rdsLsb & 1);
+ formatting_dir = EXTRACT_BIT(temp.rdsBlk[2].rdsLsb,
+ ERT_FORMAT_DIR_BIT);
+ if (ert_carrier != agt)
+ iris_q_event(radio, IRIS_EVT_NEW_ODA);
+ ert_carrier = agt;
+ break;
+ case RT_PLUS_AID:
+ /* calculate the grp mask for RDS grp
+ * which will contain actual eRT text
+ *
+ * Bit Pos 0 1 2 3 4 5 6 7
+ * Grp Type 0A 0B 1A 1B 2A 2B 3A 3B
+ *
+ * similary for rest grps
+ */
+ mask_bit = (((agt >> 1) << 1) + (agt & 1));
+ oda_agt = (1 << mask_bit);
+ /*Extract 5th bit of MSB (b7b6b5b4b3b2b1b0)*/
+ rt_ert_flag = EXTRACT_BIT(temp.rdsBlk[2].rdsMsb,
+ RT_ERT_FLAG_BIT);
+ if (rt_plus_carrier != agt)
+ iris_q_event(radio, IRIS_EVT_NEW_ODA);
+ rt_plus_carrier = agt;
+ break;
+ default:
+ oda_agt = 0;
+ break;
+ }
+ } else {
+ carrier = gtc;
+ if ((carrier == rt_plus_carrier))
+ hci_ev_rt_plus(radio, temp);
+ else if (carrier == ert_carrier)
+ hci_buff_ert(radio, &temp);
+ }
+}
+
+static void hci_buff_ert(struct iris_device *radio,
+ struct rds_grp_data *rds_buf)
+{
+ int i;
+ unsigned short int info_byte = 0;
+ unsigned short int byte_pair_index;
+
+ byte_pair_index = AGT(rds_buf->rdsBlk[1].rdsLsb);
+ if (byte_pair_index == 0) {
+ c_byt_pair_index = 0;
+ ert_len = 0;
+ }
+ if (c_byt_pair_index == byte_pair_index) {
+ c_byt_pair_index++;
+ for (i = 2; i <= 3; i++) {
+ info_byte = rds_buf->rdsBlk[i].rdsLsb;
+ info_byte |= (rds_buf->rdsBlk[i].rdsMsb << 8);
+ ert_buf[ert_len++] = rds_buf->rdsBlk[i].rdsMsb;
+ ert_buf[ert_len++] = rds_buf->rdsBlk[i].rdsLsb;
+ if ((utf_8_flag == 0)
+ && (info_byte == CARRIAGE_RETURN)) {
+ ert_len -= 2;
+ break;
+ } else if ((utf_8_flag == 1)
+ &&
+ (rds_buf->rdsBlk[i].rdsMsb
+ == CARRIAGE_RETURN)) {
+ info_byte = CARRIAGE_RETURN;
+ ert_len -= 2;
+ break;
+ } else if ((utf_8_flag == 1)
+ &&
+ (rds_buf->rdsBlk[i].rdsLsb
+ == CARRIAGE_RETURN)) {
+ info_byte = CARRIAGE_RETURN;
+ ert_len--;
+ break;
+ }
+ }
+ if ((byte_pair_index == MAX_ERT_SEGMENT) ||
+ (info_byte == CARRIAGE_RETURN)) {
+ hci_ev_ert(radio);
+ c_byt_pair_index = 0;
+ ert_len = 0;
+ }
+ } else {
+ ert_len = 0;
+ c_byt_pair_index = 0;
+ }
+}
+static void hci_ev_ert(struct iris_device *radio)
+
+{
+ char *data = NULL;
+
+ if (ert_len <= 0)
+ return;
+ data = kmalloc((ert_len + 3), GFP_ATOMIC);
+ if (data != NULL) {
+ data[0] = ert_len;
+ data[1] = utf_8_flag;
+ data[2] = formatting_dir;
+ memcpy((data + 3), ert_buf, ert_len);
+ iris_q_evt_data(radio, data, (ert_len + 3), IRIS_BUF_ERT);
+ iris_q_event(radio, IRIS_EVT_NEW_ERT);
+ kfree(data);
+ }
+}
+
+static void hci_ev_rt_plus(struct iris_device *radio,
+ struct rds_grp_data rds_buf)
+{
+ char tag_type1, tag_type2;
+ char *data = NULL;
+ int len = 0;
+ unsigned short int agt;
+
+ agt = AGT(rds_buf.rdsBlk[1].rdsLsb);
+ /*right most 3 bits of Lsb of block 2
+ * and left most 3 bits of Msb of block 3
+ */
+ tag_type1 = (((agt & TAG1_MSB_MASK) << TAG1_MSB_OFFSET) |
+ (rds_buf.rdsBlk[2].rdsMsb >> TAG1_LSB_OFFSET));
+
+ /*right most 1 bit of lsb of 3rd block
+ * and left most 5 bits of Msb of 4th block
+ */
+ tag_type2 = (((rds_buf.rdsBlk[2].rdsLsb & TAG2_MSB_MASK)
+ << TAG2_MSB_OFFSET) |
+ (rds_buf.rdsBlk[3].rdsMsb >> TAG2_LSB_OFFSET));
+
+ if (tag_type1 != DUMMY_CLASS)
+ len += RT_PLUS_LEN_1_TAG;
+ if (tag_type2 != DUMMY_CLASS)
+ len += RT_PLUS_LEN_1_TAG;
+
+ if (len != 0) {
+ len += 2;
+ data = kmalloc(len, GFP_ATOMIC);
+ } else {
+ FMDERR("Len is zero\n");
+ return ;
+ }
+ if (data != NULL) {
+ data[0] = len;
+ len = 1;
+ data[len++] = rt_ert_flag;
+ if (tag_type1 != DUMMY_CLASS) {
+ data[len++] = tag_type1;
+ /*start position of tag1
+ *right most 5 bits of msb of 3rd block
+ *and left most bit of lsb of 3rd block
+ */
+ data[len++] = (((rds_buf.rdsBlk[2].rdsMsb &
+ TAG1_POS_MSB_MASK)
+ << TAG1_POS_MSB_OFFSET)
+ |
+ (rds_buf.rdsBlk[2].rdsLsb >>
+ TAG1_POS_LSB_OFFSET));
+ /*length of tag1
+ *left most 6 bits of lsb of 3rd block
+ */
+ data[len++] = ((rds_buf.rdsBlk[2].rdsLsb
+ >> TAG1_LEN_OFFSET)
+ &
+ TAG1_LEN_MASK) + 1;
+ }
+ if (tag_type2 != DUMMY_CLASS) {
+ data[len++] = tag_type2;
+ /*start position of tag2
+ *right most 3 bit of msb of 4th block
+ *and left most 3 bits of lsb of 4th block
+ */
+ data[len++] = (((rds_buf.rdsBlk[3].rdsMsb
+ & TAG2_POS_MSB_MASK)
+ << TAG2_POS_MSB_OFFSET)
+ |
+ (rds_buf.rdsBlk[3].rdsLsb
+ >> TAG2_POS_LSB_OFFSET));
+ /*length of tag2
+ *right most 5 bits of lsb of 4th block
+ */
+ data[len++] = (rds_buf.rdsBlk[3].rdsLsb
+ & TAG2_LEN_MASK) + 1;
+ }
+ iris_q_evt_data(radio, data, len, IRIS_BUF_RT_PLUS);
+ iris_q_event(radio, IRIS_EVT_NEW_RT_PLUS);
+ kfree(data);
+ } else {
+ FMDERR("memory allocation failed\n");
+ }
+}
static inline void hci_ev_program_service(struct radio_hci_dev *hdev,
struct sk_buff *skb)
@@ -2217,6 +2480,7 @@
hci_ev_service_available(hdev, skb);
break;
case HCI_EV_RDS_RX_DATA:
+ hci_ev_raw_rds_group_data(hdev, skb);
break;
case HCI_EV_PROGRAM_SERVICE:
hci_ev_program_service(hdev, skb);
@@ -2984,8 +3248,13 @@
}
break;
case V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK:
- radio->rds_grp.rds_grp_enable_mask = ctrl->value;
+ grp_mask = (grp_mask | oda_agt | ctrl->value);
+ radio->rds_grp.rds_grp_enable_mask = grp_mask;
+ radio->rds_grp.rds_buf_size = 1;
+ radio->rds_grp.en_rds_change_filter = 0;
retval = hci_fm_rds_grp(&radio->rds_grp, radio->fm_hdev);
+ if (retval < 0)
+ FMDERR("error in setting group mask\n");
break;
case V4L2_CID_PRIVATE_IRIS_RDSGROUP_PROC:
rds_grps_proc = radio->g_rds_grp_proc_ps | ctrl->value;
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 0bc2228..75856b2a 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -452,6 +452,10 @@
static struct ion_client *res_trk_create_ion_client(void){
struct ion_client *video_client;
video_client = msm_ion_client_create(-1, "video_client");
+ if (IS_ERR_OR_NULL(video_client)) {
+ VCDRES_MSG_ERROR("%s: Unable to create ION client\n", __func__);
+ video_client = NULL;
+ }
return video_client;
}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
index 3b40640..9fb8162 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -125,9 +125,8 @@
alloc_size,
SZ_4K,
buff_addr->mem_type, 0);
- if (!buff_addr->alloc_handle) {
- ERR("\n%s(): DDL ION alloc failed\n",
- __func__);
+ if (IS_ERR_OR_NULL(buff_addr->alloc_handle)) {
+ ERR("\n%s(): DDL ION alloc failed\n", __func__);
goto bailout;
}
ret = ion_phys(ddl_context->video_ion_client,
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index aee9dfe..d8b8f18 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -681,6 +681,10 @@
struct ion_client *video_client;
VCDRES_MSG_LOW("%s", __func__);
video_client = msm_ion_client_create(-1, "video_client");
+ if (IS_ERR_OR_NULL(video_client)) {
+ VCDRES_MSG_ERROR("%s: Unable to create ION client\n", __func__);
+ video_client = NULL;
+ }
return video_client;
}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 5fdee02..8d28fd5 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -93,7 +93,7 @@
map_buffer->alloc_handle = ion_alloc(
cctxt->vcd_ion_client, sz, SZ_4K,
memtype, 0);
- if (!map_buffer->alloc_handle) {
+ if (IS_ERR_OR_NULL(map_buffer->alloc_handle)) {
pr_err("%s() ION alloc failed", __func__);
goto bailout;
}
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index 348a231..fe23993 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -74,6 +74,7 @@
u32 irq_gpio_flags;
int *key_codes;
bool need_calibration;
+ bool no_force_update;
u8(*read_chg) (void);
int (*init_hw) (bool);
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index db69518..0efeff4 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -363,6 +363,53 @@
#define HCI_REQ_CANCELED 2
#define HCI_REQ_STATUS 3
+#define MAX_RAW_RDS_GRPS 21
+
+#define RDSGRP_DATA_OFFSET 0x1
+
+/*RT PLUS*/
+#define DUMMY_CLASS 0
+#define RT_PLUS_LEN_1_TAG 3
+#define RT_ERT_FLAG_BIT 5
+
+/*TAG1*/
+#define TAG1_MSB_OFFSET 3
+#define TAG1_MSB_MASK 7
+#define TAG1_LSB_OFFSET 5
+#define TAG1_POS_MSB_MASK 31
+#define TAG1_POS_MSB_OFFSET 1
+#define TAG1_POS_LSB_OFFSET 7
+#define TAG1_LEN_OFFSET 1
+#define TAG1_LEN_MASK 63
+
+/*TAG2*/
+#define TAG2_MSB_OFFSET 5
+#define TAG2_MSB_MASK 1
+#define TAG2_LSB_OFFSET 3
+#define TAG2_POS_MSB_MASK 7
+#define TAG2_POS_MSB_OFFSET 3
+#define TAG2_POS_LSB_OFFSET 5
+#define TAG2_LEN_MASK 31
+
+#define AGT_MASK 31
+/*Extract 5 left most bits of lsb of 2nd block*/
+#define AGT(x) (x & AGT_MASK)
+/*16 bits of 4th block*/
+#define AID(lsb, msb) ((msb << 8) | (lsb))
+/*Extract 5 right most bits of msb of 2nd block*/
+#define GTC(blk2msb) (blk2msb >> 3)
+
+#define GRP_3A 0x6
+#define RT_PLUS_AID 0x4bd7
+
+/*ERT*/
+#define ERT_AID 0x6552
+#define CARRIAGE_RETURN 0x000D
+#define MAX_ERT_SEGMENT 31
+#define ERT_FORMAT_DIR_BIT 1
+
+#define EXTRACT_BIT(data, bit_pos) ((data & (1 << bit_pos)) >> bit_pos)
+
struct hci_ev_tune_status {
__u8 sub_event;
__le32 station_freq;
@@ -375,9 +422,19 @@
__u8 intf_det_th;
} __packed;
+struct rds_blk_data {
+ __u8 rdsMsb;
+ __u8 rdsLsb;
+ __u8 blockStatus;
+} __packed;
+
+struct rds_grp_data {
+ struct rds_blk_data rdsBlk[4];
+} __packed;
+
struct hci_ev_rds_rx_data {
__u8 num_rds_grps;
- __u8 rds_grp_data[12];
+ struct rds_grp_data rds_grp_data[MAX_RAW_RDS_GRPS];
} __packed;
struct hci_ev_prg_service {
@@ -628,7 +685,10 @@
IRIS_EVT_NEW_AF_LIST,
IRIS_EVT_TXRDSDAT,
IRIS_EVT_TXRDSDONE,
- IRIS_EVT_RADIO_DISABLED
+ IRIS_EVT_RADIO_DISABLED,
+ IRIS_EVT_NEW_ODA,
+ IRIS_EVT_NEW_RT_PLUS,
+ IRIS_EVT_NEW_ERT,
};
enum emphasis_type {
FM_RX_EMP75 = 0x0,
@@ -660,7 +720,7 @@
IRIS_REGION_OTHER
};
-#define STD_BUF_SIZE (128)
+#define STD_BUF_SIZE (256)
enum iris_buf_t {
IRIS_BUF_SRCH_LIST,
@@ -674,7 +734,9 @@
IRIS_BUF_RDS_CNTRS,
IRIS_BUF_RD_DEFAULT,
IRIS_BUF_CAL_DATA,
- IRIS_BUF_MAX
+ IRIS_BUF_RT_PLUS,
+ IRIS_BUF_ERT,
+ IRIS_BUF_MAX,
};
enum iris_xfr_t {
diff --git a/include/media/tavarua.h b/include/media/tavarua.h
index 1cccb2b..881b851 100644
--- a/include/media/tavarua.h
+++ b/include/media/tavarua.h
@@ -52,7 +52,7 @@
#define SRCH_MASK (1 << SRCH200KHZ_OFFSET)
/* Standard buffer size */
-#define STD_BUF_SIZE (128)
+#define STD_BUF_SIZE (256)
/* Search direction */
#define SRCH_DIR_UP (0)
#define SRCH_DIR_DOWN (1)
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 8c35ada..23c1d51 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -61,7 +61,7 @@
#define RT_PROXY_PORT_001_TX 0x2001 /* index = 31 */
#define SECONDARY_PCM_RX 12 /* index = 32 */
#define SECONDARY_PCM_TX 13 /* index = 33 */
-
+#define PSEUDOPORT_01 0x8001 /* index =34 */
#define AFE_PORT_INVALID 0xFFFF
#define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
@@ -299,6 +299,14 @@
int num_ch; /* 1 to 8 */
} __packed;
+struct afe_port_pseudo_cfg {
+ u16 bit_width;
+ u16 num_channels;
+ u16 data_format;
+ u16 timing_mode;
+ u16 reserved;
+} __packed;
+
#define AFE_PORT_AUDIO_IF_CONFIG 0x000100d3
#define AFE_PORT_AUDIO_SLIM_SCH_CONFIG 0x000100e4
#define AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG 0x000100D9
@@ -312,6 +320,7 @@
struct afe_port_slimbus_cfg slimbus;
struct afe_port_slimbus_sch_cfg slim_sch;
struct afe_port_rtproxy_cfg rtproxy;
+ struct afe_port_pseudo_cfg pseudo;
} __attribute__((packed));
struct afe_audioif_config_command {
@@ -574,6 +583,19 @@
u32 rate;
u8 dev_channel_mapping[8];
} __packed;
+
+struct adm_multi_channel_copp_open_v3 {
+ struct apr_hdr hdr;
+ u16 flags;
+ u16 mode;
+ u16 endpoint_id1;
+ u16 endpoint_id2;
+ u32 topology_id;
+ u16 channel_config;
+ u16 bit_width;
+ u32 rate;
+ u8 dev_channel_mapping[8];
+};
#define ADM_CMD_MEMORY_MAP 0x00010C30
struct adm_cmd_memory_map{
struct apr_hdr hdr;
@@ -914,7 +936,38 @@
* An unused channel is set to zero.
*/
};
+struct asm_dts_enc_cfg {
+ uint32_t sample_rate;
+ /*
+ * Samples at which input is to be encoded.
+ * Supported values:
+ * 44100 -- encode at 44.1 Khz
+ * 48000 -- encode at 48 Khz
+ */
+ uint32_t num_channels;
+ /*
+ * Number of channels for multi-channel encoding.
+ * Supported values: 1 to 6
+ */
+
+ uint8_t channel_mapping[6];
+ /*
+ * Channel array of size 16. Channel[i] mapping describes channel I.
+ * Each element i of the array describes channel I inside the buffer
+ * where num_channels. An unused channel is set to zero. Only first
+ * num_channels elements are valid
+
+ * Supported values:
+ * - # PCM_CHANNEL_L
+ * - # PCM_CHANNEL_R
+ * - # PCM_CHANNEL_C
+ * - # PCM_CHANNEL_LS
+ * - # PCM_CHANNEL_RS
+ * - # PCM_CHANNEL_LFE
+ */
+
+};
struct asm_adpcm_cfg {
u16 ch_cfg;
u16 bits_per_sample;
@@ -1107,6 +1160,7 @@
struct asm_sbc_read_cfg sbc;
struct asm_amrwb_read_cfg amrwb;
struct asm_multi_channel_pcm_fmt_blk mpcm;
+ struct asm_dts_enc_cfg dts;
} __attribute__((packed)) cfg;
};
@@ -1209,6 +1263,148 @@
u32 flags;
u32 format;
} __packed;
+#define ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK 0x00010DBA
+struct asm_stream_cmd_open_transcode_loopback {
+ struct apr_hdr hdr;
+ uint32_t mode_flags;
+ /*
+ * All bits are reserved. Clients must set them to zero.
+ */
+
+ uint32_t src_format_id;
+ /*
+ * Specifies the media format of the input audio stream.
+
+ * Supported values:
+ * - #ASM_MEDIA_FMT_LINEAR_PCM
+ * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM
+ */
+
+ uint32_t sink_format_id;
+ /*
+ * Specifies the media format of the output stream.
+
+ * Supported values:
+ * - #ASM_MEDIA_FMT_LINEAR_PCM
+ * - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM
+ * - #ASM_MEDIA_FMT_DTS
+ */
+
+ uint32_t audproc_topo_id;
+ /*
+ * Postprocessing topology ID, which specifies the topology (order of
+ * processing) of postprocessing algorithms.
+
+ * Supported values:
+ * - #ASM_STREAM_POSTPROC_TOPO_ID_DEFAULT
+ * - #ASM_STREAM_POSTPROC_TOPO_ID_PEAKMETER
+ * - #ASM_STREAM_POSTPROC_TOPO_ID_NONE
+ * - #ASM_STREAM_POSTPROC_TOPO_ID_MCH_PEAK_VOL
+ */
+
+ uint16_t src_endpoint_type;
+ /*
+ * Specifies the source endpoint that provides the input samples.
+
+ * Supported values:
+ * - 0 -- Tx device matrix or stream router
+ * (gateway to the hardware ports)
+ * - All other values are reserved
+
+ * Clients must set this field to zero. Otherwise, an error is returned.
+ */
+
+ uint16_t sink_endpoint_type;
+ /*
+ * Specifies the sink endpoint type.
+
+ * Supported values:
+ * - 0 -- Rx device matrix or stream router
+ * (gateway to the hardware ports)
+ * - All other values are reserved
+
+ * Clients must set this field to zero. Otherwise, an error is returned.
+ */
+
+ uint16_t bits_per_sample;
+ /*
+ * Number of bits per sample processed by the ASM modules.
+ * Supported values: 16, 24
+ */
+
+ uint16_t reserved;
+ /*
+ * This field must be set to zero.
+ */
+} __packed;
+
+/*
+* ID of the DTS mix LFE channel to front channels parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_MIX_LFE_TO_FRONT
+*/
+#define ASM_PARAM_ID_DTS_MIX_LFE_TO_FRONT 0x00010DB6
+
+/*
+* ID of the DTS DRC ratio parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_DRC_RATIO
+*/
+#define ASM_PARAM_ID_DTS_DRC_RATIO 0x00010DB7
+
+/*
+* ID of the DTS enable dialog normalization parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_ENABLE_DIALNORM
+*/
+#define ASM_PARAM_ID_DTS_ENABLE_DIALNORM 0x00010DB8
+
+/*
+* ID of the DTS enable parse REV2AUX parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_ENABLE_PARSE_REV2AUX
+*/
+#define ASM_PARAM_ID_DTS_ENABLE_PARSE_REV2AUX 0x00010DB9
+
+struct asm_dts_generic_param {
+ int32_t generic_parameter;
+ /*
+ * #ASM_PARAM_ID_DTS_MIX_LFE_TO_FRONT:
+ * - if enabled, mixes LFE channel to front
+ * while downmixing (if necessary)
+ * - Supported values: 1-> enable, 0-> disable
+ * - Default: disabled
+
+ * #ASM_PARAM_ID_DTS_DRC_RATIO:
+ * - percentage of DRC ratio.
+ * - Supported values: 0-100
+ * - Default: 0, DRC is disabled.
+
+ * #ASM_PARAM_ID_DTS_ENABLE_DIALNORM:
+ * - flag to enable dialog normalization post processing.
+ * - Supported values: 1-> enable, 0-> disable.
+ * - Default: enabled.
+
+ * #ASM_PARAM_ID_DTS_ENABLE_PARSE_REV2AUX:
+ * - flag to enable parsing of rev2aux chunk in the bitstream.
+ * This chunk contains broadcast metadata.
+ * - Supported values: 1-> enable, 0-> disable.
+ * - Default: disabled.
+ */
+};
+
+struct asm_stream_cmd_dts_dec_param {
+ struct apr_hdr hdr;
+ u32 param_id;
+ u32 param_size;
+ struct asm_dts_generic_param generic_param;
+} __packed;
+
#define ASM_STREAM_CMD_OPEN_READWRITE 0x00010BCC
@@ -1238,7 +1434,7 @@
u8 session_id; /*ASM session ID*/
u16 afe_port_id;
u32 num_channels;
- u32 sampleing_rate;
+ u32 sampling_rate;
} __packed;
#define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
index f5c2d13..b95fa3c 100644
--- a/include/sound/compress_params.h
+++ b/include/sound/compress_params.h
@@ -418,6 +418,8 @@
__u32 ch_mode;
__u32 format;
__u32 align;
+ __u32 transcode_dts;
+ struct snd_dec_dts dts;
union snd_codec_options options;
__u32 reserved[3];
};
diff --git a/include/sound/q6adm.h b/include/sound/q6adm.h
index 676c4cb..70c68a8 100644
--- a/include/sound/q6adm.h
+++ b/include/sound/q6adm.h
@@ -37,6 +37,8 @@
int adm_close(int port);
+int adm_pseudo_close(int port);
+
int adm_matrix_map(int session_id, int path, int num_copps,
unsigned int *port_id, int copp_id);
@@ -45,6 +47,12 @@
void adm_ec_ref_rx_id(int port_id);
+int adm_connect_afe_port_v2(int mode, int session_id, int port_id,
+ int sample_rate, int channels);
+
+int adm_multi_ch_copp_pseudo_open_v3(int port_id, int path, int rate,
+ int channel_mode, int topology);
+
#ifdef CONFIG_RTAC
int adm_get_copp_id(int port_id);
#endif
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index a7264e8..8451ac6 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.h
@@ -70,6 +70,7 @@
IDX_RT_PROXY_PORT_001_TX = 31,
IDX_SECONDARY_PCM_RX = 32,
IDX_SECONDARY_PCM_TX = 33,
+ IDX_PSEUDOPORT_01 = 34,
AFE_MAX_PORTS
};
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index b0d74ba..6b4c17b 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -55,6 +55,7 @@
#define ENCDEC_SBCBITRATE 0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
#define ENCDEC_CFG_BLK 0x0003
+#define DTS_ENC_SAMPLE_RATE48k 48000
#define CMD_PAUSE 0x0001
#define CMD_FLUSH 0x0002
@@ -194,6 +195,11 @@
int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format);
+int q6asm_open_transcode_loopback(struct audio_client *ac, uint32_t channels);
+
+int q6asm_enc_cfg_blk_dts(struct audio_client *ac,
+ uint32_t sample_rate, uint32_t channels);
+
int q6asm_open_read_write(struct audio_client *ac,
uint32_t rd_format,
uint32_t wr_format);
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 016ef94..90c96b4 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -1486,6 +1486,20 @@
.ignore_pmdown_time = 1, /* dainlink has playback support */
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
+
+ },
+ {
+ .name = "MSM8960 Pseudo",
+ .stream_name = "Pseudo",
+ .cpu_dai_name = "Pseudo",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_PSEUDO,
},
/* Backend DAI Links */
{
@@ -1624,6 +1638,18 @@
.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
.be_hw_params_fixup = mpq8064_auxpcm_be_params_fixup,
},
+ {
+ .name = LPASS_BE_PSEUDO,
+ .stream_name = "PSEUDO Playback",
+ .cpu_dai_name = "msm-dai-q6.32769",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_PSEUDO_PORT,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ },
};
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index eeabb78..5b0eb9c 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -474,7 +474,23 @@
default:
return -EINVAL;
}
-
+ if (compr->info.codec_param.codec.transcode_dts) {
+ msm_pcm_routing_reg_pseudo_stream(
+ MSM_FRONTEND_DAI_PSEUDO,
+ prtd->enc_audio_client->perf_mode,
+ prtd->enc_audio_client->session,
+ SNDRV_PCM_STREAM_CAPTURE,
+ 48000, runtime->channels > 6 ?
+ 6 : runtime->channels);
+ pr_debug("%s: cmd: DTS ENCDEC CFG BLK\n", __func__);
+ ret = q6asm_enc_cfg_blk_dts(prtd->enc_audio_client,
+ DTS_ENC_SAMPLE_RATE48k,
+ runtime->channels > 6 ?
+ 6 : runtime->channels);
+ if (ret < 0)
+ pr_err("%s: CMD: DTS ENCDEC CFG BLK failed\n",
+ __func__);
+ }
prtd->enabled = 1;
prtd->cmd_ack = 0;
@@ -650,6 +666,8 @@
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
pr_debug("%s: Trigger start\n", __func__);
q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+ if (prtd->enc_audio_client)
+ q6asm_run_nowait(prtd->enc_audio_client, 0, 0, 0);
atomic_set(&prtd->start, 1);
break;
case SNDRV_PCM_TRIGGER_STOP:
@@ -660,6 +678,8 @@
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
+ if (prtd->enc_audio_client)
+ q6asm_cmd_nowait(prtd->enc_audio_client, CMD_PAUSE);
atomic_set(&prtd->start, 0);
runtime->render_flag &= ~SNDRV_RENDER_STOPPED;
break;
@@ -811,6 +831,8 @@
atomic_set(&prtd->pending_buffer, 0);
prtd->pcm_irq_pos = 0;
q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ if (prtd->enc_audio_client)
+ q6asm_cmd(prtd->enc_audio_client, CMD_CLOSE);
compressed_audio.prtd = NULL;
q6asm_audio_client_buf_free_contiguous(dir,
prtd->audio_client);
@@ -827,6 +849,12 @@
soc_prtd->dai_link->be_id,
SNDRV_PCM_STREAM_PLAYBACK);
}
+ if (compr->info.codec_param.codec.transcode_dts) {
+ msm_pcm_routing_dereg_pseudo_stream(MSM_FRONTEND_DAI_PSEUDO,
+ prtd->enc_audio_client->session);
+ }
+ if (prtd->enc_audio_client)
+ q6asm_audio_client_free(prtd->enc_audio_client);
q6asm_audio_client_free(prtd->audio_client);
kfree(prtd);
return 0;
@@ -968,6 +996,29 @@
prtd->session_id,
substream->stream);
+ if (compr->info.codec_param.codec.transcode_dts) {
+ prtd->enc_audio_client =
+ q6asm_audio_client_alloc(
+ (app_cb)compr_event_handler, compr);
+ if (!prtd->enc_audio_client) {
+ pr_err("%s: Could not allocate " \
+ "memory\n", __func__);
+ return -ENOMEM;
+ }
+ prtd->enc_audio_client->perf_mode = false;
+ pr_debug("%s Setting up loopback path\n",
+ __func__);
+ ret = q6asm_open_transcode_loopback(
+ prtd->enc_audio_client,
+ params_channels(params));
+ if (ret < 0) {
+ pr_err("%s: Session transcode " \
+ "loopback open failed\n",
+ __func__);
+ return -ENODEV;
+ }
+ }
+
break;
}
} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -1117,6 +1168,22 @@
pr_err("%s: ERROR: copy from user\n", __func__);
return rc;
}
+ /*
+ * DTS Security needed for the transcode path
+ */
+ if (compr->info.codec_param.codec.transcode_dts) {
+ char modelId[128];
+ struct snd_dec_dts opt_dts =
+ compr->info.codec_param.codec.dts;
+ int modelIdLength = opt_dts.modelIdLength;
+ if (copy_from_user(modelId, (void *)opt_dts.modelId,
+ modelIdLength))
+ pr_err("%s: ERROR: copy modelId\n", __func__);
+ modelId[modelIdLength] = '\0';
+ pr_debug("%s: Received modelId =%s,length=%d\n",
+ __func__, modelId, modelIdLength);
+ core_set_dts_model_id(modelIdLength, modelId);
+ }
switch (compr->info.codec_param.codec.id) {
case SND_AUDIOCODEC_MP3:
/* For MP3 we dont need any other parameter */
@@ -1150,7 +1217,7 @@
case SND_AUDIOCODEC_DTS: {
char modelId[128];
struct snd_dec_dts opt_dts =
- compr->info.codec_param.codec.options.dts;
+ compr->info.codec_param.codec.dts;
int modelIdLength = opt_dts.modelIdLength;
pr_debug("SND_AUDIOCODEC_DTS\n");
if (copy_from_user(modelId, (void *)opt_dts.modelId,
@@ -1166,7 +1233,7 @@
case SND_AUDIOCODEC_DTS_LBR:{
char modelId[128];
struct snd_dec_dts opt_dts =
- compr->info.codec_param.codec.options.dts;
+ compr->info.codec_param.codec.dts;
int modelIdLength = opt_dts.modelIdLength;
pr_debug("SND_AUDIOCODEC_DTS_LBR\n");
if (copy_from_user(modelId, (void *)opt_dts.modelId,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index dc8d9e6..e91ed86 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -477,6 +477,32 @@
.ops = &msm_fe_dai_ops,
.name = "SGLTE",
},
+ {
+ .playback = {
+ .stream_name = "Pseudo Playback",
+ .aif_name = "MM_DL9",
+ .rates = (SNDRV_PCM_RATE_8000_48000 |
+ SNDRV_PCM_RATE_KNOT),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "Pseudo Capture",
+ .aif_name = "MM_UL9",
+ .rates = (SNDRV_PCM_RATE_8000_48000|
+ SNDRV_PCM_RATE_KNOT),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_Multimedia_dai_ops,
+ .name = "Pseudo",
+ },
};
static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 18c2329..8cc0eaa 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -660,6 +660,24 @@
return 0;
}
+static int msm_dai_q6_pseudo_hw_params(struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+
+ dai_data->rate = params_rate(params);
+ dai_data->channels = params_channels(params) > 6 ?
+ params_channels(params) : 6;
+
+ dai_data->port_config.pseudo.bit_width = 16;
+ dai_data->port_config.pseudo.num_channels =
+ dai_data->channels;
+ dai_data->port_config.pseudo.data_format = 0;
+ dai_data->port_config.pseudo.timing_mode = 1;
+ dai_data->port_config.pseudo.reserved = 16;
+ return 0;
+}
+
/* Current implementation assumes hw_param is called once
* This may not be the case but what to do when ADM and AFE
* port are already opened and parameter changes
@@ -703,6 +721,9 @@
case RT_PROXY_DAI_002_RX:
rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
break;
+ case PSEUDOPORT_01:
+ rc = msm_dai_q6_pseudo_hw_params(params, dai);
+ break;
case VOICE_PLAYBACK_TX:
case VOICE_RECORD_RX:
case VOICE_RECORD_TX:
@@ -1819,6 +1840,20 @@
.probe = msm_dai_q6_dai_probe,
.remove = msm_dai_q6_dai_remove,
};
+static struct snd_soc_dai_driver msm_dai_q6_pseudo_dai = {
+ .playback = {
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+ SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 6,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_ops,
+ .probe = msm_dai_q6_dai_probe,
+ .remove = msm_dai_q6_dai_remove,
+};
/* To do: change to register DAIs as batch */
static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
@@ -1915,6 +1950,10 @@
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_incall_record_dai);
break;
+ case PSEUDOPORT_01:
+ rc = snd_soc_register_dai(&pdev->dev,
+ &msm_dai_q6_pseudo_dai);
+ break;
default:
rc = -ENODEV;
break;
diff --git a/sound/soc/msm/msm-pcm-q6.h b/sound/soc/msm/msm-pcm-q6.h
index 2678498..86e5c54 100644
--- a/sound/soc/msm/msm-pcm-q6.h
+++ b/sound/soc/msm/msm-pcm-q6.h
@@ -59,6 +59,7 @@
uint16_t source; /* Encoding source bit mask */
struct audio_client *audio_client;
+ struct audio_client *enc_audio_client;
uint16_t session_id;
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 800bea8..378baf1 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -194,6 +194,7 @@
{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
{ SECONDARY_PCM_RX, 0, 0, 0, 0, 0},
{ SECONDARY_PCM_TX, 0, 0, 0, 0, 0},
+ { PSEUDOPORT_01, 0, 0, 0, 0, 0},
};
@@ -215,7 +216,8 @@
{INVALID_SESSION, INVALID_SESSION},
/* MULTIMEDIA8 */
{INVALID_SESSION, INVALID_SESSION},
-
+ /* PSEUDO */
+ {INVALID_SESSION, INVALID_SESSION},
};
static uint8_t is_be_dai_extproc(int be_dai)
@@ -298,6 +300,59 @@
mutex_unlock(&routing_lock);
}
+void msm_pcm_routing_reg_pseudo_stream(int fedai_id, bool perf_mode,
+ int dspst_id, int stream_type,
+ int sample_rate, int channels)
+{
+ int i, session_type, path_type, port_type, mode, ret;
+ struct route_payload payload;
+ pr_debug("%s:fedai_id = %d dspst_id = %d stream_type %d",
+ __func__, fedai_id, dspst_id, stream_type);
+
+ if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
+ session_type = SESSION_TYPE_RX;
+ path_type = ADM_PATH_PLAYBACK;
+ port_type = MSM_AFE_PORT_TYPE_RX;
+ } else {
+ session_type = SESSION_TYPE_TX;
+ path_type = ADM_PATH_LIVE_REC;
+ port_type = MSM_AFE_PORT_TYPE_TX;
+ }
+
+ mutex_lock(&routing_lock);
+
+ payload.num_copps = 0;
+ adm_multi_ch_copp_pseudo_open_v3(PSEUDOPORT_01,
+ path_type, sample_rate, channels,
+ DEFAULT_COPP_TOPOLOGY);
+
+ payload.copp_ids[payload.num_copps++] = PSEUDOPORT_01;
+
+ for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
+ if (test_bit(fedai_id, &msm_bedais[i].fe_sessions))
+ msm_bedais[i].perf_mode = perf_mode;
+ if (!is_be_dai_extproc(i) &&
+ (msm_bedais[i].active) &&
+ (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
+
+ mode = afe_get_port_type(msm_bedais[i].port_id);
+ ret = adm_connect_afe_port_v2(mode, dspst_id,
+ msm_bedais[i].port_id,
+ msm_bedais[i].sample_rate,
+ msm_bedais[i].channel);
+
+ if (ret < 0)
+ pr_err("%s: adm_connect_afe_port_v2 failed\n",
+ __func__);
+ }
+ }
+ if (payload.num_copps)
+ adm_matrix_map(dspst_id, path_type,
+ payload.num_copps, payload.copp_ids, 0);
+
+ mutex_unlock(&routing_lock);
+}
+
void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode, int dspst_id,
int stream_type)
{
@@ -375,6 +430,32 @@
mutex_unlock(&routing_lock);
}
+void msm_pcm_routing_dereg_pseudo_stream(int fedai_id, int dspst_id)
+{
+ int i, mode, ret;
+ pr_debug("%s:fedai_id = %d dspst_id = %d",
+ __func__, fedai_id, dspst_id);
+
+ mutex_lock(&routing_lock);
+
+ adm_pseudo_close(PSEUDOPORT_01);
+ for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
+ if (!is_be_dai_extproc(i) &&
+ (msm_bedais[i].active) &&
+ (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
+
+ mode = afe_get_port_type(msm_bedais[i].port_id);
+ ret = adm_disconnect_afe_port(mode, dspst_id,
+ msm_bedais[i].port_id);
+ if (ret < 0)
+ pr_err("%s: adm_connect_afe_port_v2 failed\n",
+ __func__);
+ }
+ }
+
+ mutex_unlock(&routing_lock);
+
+}
void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
{
int i, port_type, session_type;
@@ -1210,6 +1291,9 @@
SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("Pseudo", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_PSEUDO, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
@@ -1291,6 +1375,17 @@
SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("Pseudo", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_PSEUDO, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+static const struct snd_kcontrol_new pseudo_mixer_controls[] = {
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PSEUDO_PORT,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_PSEUDO_PORT,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
/* incall music delivery mixer */
static const struct snd_kcontrol_new incall_music_delivery_mixer_controls[] = {
@@ -2163,6 +2258,7 @@
SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL9", "Pseudo Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
@@ -2201,6 +2297,7 @@
0, 0, 0 , 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
+ SND_SOC_DAPM_AIF_OUT("PSEUDO", "PSEUDO Playback", 0, 0, 0 , 0),
SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_I2S_TX", "Secondary I2S Capture", 0, 0, 0, 0),
@@ -2260,6 +2357,8 @@
slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)),
+ SND_SOC_DAPM_MIXER("PSEUDO Mixer", SND_SOC_NOPM, 0, 0,
+ pseudo_mixer_controls, ARRAY_SIZE(pseudo_mixer_controls)),
SND_SOC_DAPM_MIXER("MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
mi2s_rx_mixer_controls, ARRAY_SIZE(mi2s_rx_mixer_controls)),
SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
@@ -2398,6 +2497,7 @@
{"SEC_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
{"SEC_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
{"SEC_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+ {"SEC_RX Audio Mixer", "Pseudo", "MM_DL9"},
{"SEC_I2S_RX", NULL, "SEC_RX Audio Mixer"},
{"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -2418,8 +2518,12 @@
{"HDMI Mixer", "MultiMedia6", "MM_DL6"},
{"HDMI Mixer", "MultiMedia7", "MM_DL7"},
{"HDMI Mixer", "MultiMedia8", "MM_DL8"},
+ {"HDMI Mixer", "Pseudo", "MM_DL9"},
{"HDMI", NULL, "HDMI Mixer"},
+ {"PSEUDO Mixer", "MultiMedia4", "MM_DL4"},
+ {"PSEUDO", NULL, "PSEUDO Mixer"},
+
/* incall */
{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -2665,6 +2769,7 @@
{"BE_OUT", NULL, "SLIMBUS_3_RX"},
{"BE_OUT", NULL, "SLIMBUS_4_RX"},
{"BE_OUT", NULL, "HDMI"},
+ {"BE_OUT", NULL, "PSEUDO"},
{"BE_OUT", NULL, "MI2S_RX"},
{"PRI_I2S_TX", NULL, "BE_IN"},
{"SEC_I2S_TX", NULL, "BE_IN"},
@@ -2784,7 +2889,14 @@
for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
if (fe_dai_map[i][session_type] != INVALID_SESSION) {
channels = bedai->channel;
- if ((playback || capture)
+ if (bedai->port_id == PSEUDOPORT_01) {
+ adm_multi_ch_copp_pseudo_open_v3(bedai->port_id,
+ path_type,
+ bedai->sample_rate,
+ channels > 6 ? 6 :
+ channels,
+ DEFAULT_COPP_TOPOLOGY);
+ } else if ((playback || capture)
&& ((channels == 2) || (channels == 1)) &&
bedai->perf_mode) {
adm_multi_ch_copp_open(bedai->port_id,
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index e11133e..32ab063 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -18,6 +18,7 @@
#define LPASS_BE_SLIMBUS_0_RX "SLIMBUS_0_RX"
#define LPASS_BE_SLIMBUS_0_TX "SLIMBUS_0_TX"
#define LPASS_BE_HDMI "HDMI"
+#define LPASS_BE_PSEUDO "PSEUDO"
#define LPASS_BE_INT_BT_SCO_RX "INT_BT_SCO_RX"
#define LPASS_BE_INT_BT_SCO_TX "INT_BT_SCO_TX"
#define LPASS_BE_INT_FM_RX "INT_FM_RX"
@@ -61,6 +62,7 @@
MSM_FRONTEND_DAI_MULTIMEDIA6,
MSM_FRONTEND_DAI_MULTIMEDIA7,
MSM_FRONTEND_DAI_MULTIMEDIA8,
+ MSM_FRONTEND_DAI_PSEUDO,
MSM_FRONTEND_DAI_CS_VOICE,
MSM_FRONTEND_DAI_VOIP,
MSM_FRONTEND_DAI_AFE_RX,
@@ -71,8 +73,8 @@
MSM_FRONTEND_DAI_MAX,
};
-#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA8 + 1)
-#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA8
+#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_PSEUDO + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_PSEUDO
enum {
MSM_BACKEND_DAI_PRI_I2S_RX = 0,
@@ -106,6 +108,7 @@
MSM_BACKEND_DAI_EXTPROC_EC_TX,
MSM_BACKEND_DAI_SEC_AUXPCM_RX,
MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_BACKEND_DAI_PSEUDO_PORT,
MSM_BACKEND_DAI_MAX,
};
@@ -118,6 +121,12 @@
void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
int stream_type, int enable);
+void msm_pcm_routing_reg_pseudo_stream(int fedai_id, bool perf_mode,
+ int dspst_id, int stream_type, int sample_rate,
+ int channels);
+
+void msm_pcm_routing_dereg_pseudo_stream(int fedai_id, int dspst_id);
+
void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type);
int lpa_set_volume(unsigned volume);
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index c6970f1..00394aa 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -45,7 +45,7 @@
static struct acdb_cal_block mem_addr_audvol[MAX_AUDPROC_TYPES];
static struct adm_ctl this_adm;
-
+static int pseudo_copp[2];
int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
{
@@ -293,6 +293,8 @@
case ADM_CMD_MATRIX_MAP_ROUTINGS:
case ADM_CMD_CONNECT_AFE_PORT:
case ADM_CMD_DISCONNECT_AFE_PORT:
+ case ADM_CMD_CONNECT_AFE_PORT_V2:
+ case ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3:
atomic_set(&this_adm.copp_stat[index], 1);
wake_up(&this_adm.wait);
break;
@@ -305,9 +307,10 @@
}
switch (data->opcode) {
+
+ case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN_V3:
case ADM_CMDRSP_COPP_OPEN:
- case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN:
- case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN_V3: {
+ case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN: {
struct adm_copp_open_respond *open = data->payload;
if (open->copp_id == INVALID_COPP_ID) {
pr_err("%s: invalid coppid rxed %d\n",
@@ -316,6 +319,10 @@
wake_up(&this_adm.wait);
break;
}
+ if (index == IDX_PSEUDOPORT_01)
+ pseudo_copp[
+ atomic_read(&this_adm.copp_cnt[index])] =
+ open->copp_id;
atomic_set(&this_adm.copp_id[index], open->copp_id);
atomic_set(&this_adm.copp_stat[index], 1);
pr_debug("%s: coppid rxed=%d\n", __func__,
@@ -337,6 +344,79 @@
return 0;
}
+int adm_connect_afe_port_v2(int mode, int session_id, int port_id,
+ int sample_rate, int channels)
+{
+ struct adm_cmd_connect_afe_port_v2 cmd;
+ int ret = 0;
+ int index;
+
+ pr_debug("%s: port %d session id:%d\n", __func__,
+ port_id, session_id);
+
+ port_id = afe_convert_virtual_to_portid(port_id);
+
+ if (afe_validate_port(port_id) < 0) {
+ pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+ return -ENODEV;
+ }
+ if (this_adm.apr == NULL) {
+ this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+ 0xFFFFFFFF, &this_adm);
+ if (this_adm.apr == NULL) {
+ pr_err("%s: Unable to register ADM\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+ rtac_set_adm_handle(this_adm.apr);
+ }
+ index = afe_get_port_index(port_id);
+ pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+ cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ cmd.hdr.pkt_size = sizeof(cmd);
+ cmd.hdr.src_svc = APR_SVC_ADM;
+ cmd.hdr.src_domain = APR_DOMAIN_APPS;
+ cmd.hdr.src_port = port_id;
+ cmd.hdr.dest_svc = APR_SVC_ADM;
+ cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+ cmd.hdr.dest_port = port_id;
+ cmd.hdr.token = port_id;
+ cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V2;
+
+ cmd.mode = mode;
+ cmd.session_id = session_id;
+ cmd.afe_port_id = port_id;
+ cmd.num_channels = channels;
+ cmd.sampling_rate = sample_rate;
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
+ if (ret < 0) {
+ pr_err("%s:ADM enable for port %d failed\n",
+ __func__, port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ ret = wait_event_timeout(this_adm.wait,
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s ADM connect AFE failed for port %d\n", __func__,
+ port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ atomic_inc(&this_adm.copp_cnt[index]);
+ return 0;
+
+fail_cmd:
+
+ return ret;
+
+}
+
static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
{
s32 result = 0;
@@ -718,6 +798,138 @@
return ret;
}
+int adm_multi_ch_copp_pseudo_open_v3(int port_id, int path,
+ int rate, int channel_mode,
+ int topology)
+{
+ struct adm_multi_channel_copp_open_v3 open;
+ int ret = 0;
+ int index;
+
+ pr_debug("%s: port %d path:%d rate:%d mode:%d\n", __func__,
+ port_id, path, rate, channel_mode);
+
+ port_id = afe_convert_virtual_to_portid(port_id);
+
+ if (afe_validate_port(port_id) < 0) {
+ pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+ return -ENODEV;
+ }
+
+ index = afe_get_port_index(port_id);
+ pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+ if (this_adm.apr == NULL) {
+ this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+ 0xFFFFFFFF, &this_adm);
+ if (this_adm.apr == NULL) {
+ pr_err("%s: Unable to register ADM\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+ rtac_set_adm_handle(this_adm.apr);
+ }
+
+
+ {
+ open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ open.hdr.pkt_size = sizeof(open);
+ open.hdr.src_svc = APR_SVC_ADM;
+ open.hdr.src_domain = APR_DOMAIN_APPS;
+ open.hdr.src_port = port_id;
+ open.hdr.dest_svc = APR_SVC_ADM;
+ open.hdr.dest_domain = APR_DOMAIN_ADSP;
+ open.hdr.dest_port = port_id;
+ open.hdr.token = port_id;
+ open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3;
+ memset(open.dev_channel_mapping, 0, 8);
+
+ if (channel_mode == 1) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
+ } else if (channel_mode == 2) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channel_mode == 4) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_RB;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
+ } else if (channel_mode == 6) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
+ open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+ } else if (channel_mode == 8) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
+ open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+ open.dev_channel_mapping[6] = PCM_CHANNEL_FLC;
+ open.dev_channel_mapping[7] = PCM_CHANNEL_FRC;
+ } else {
+ pr_err("%s invalid num_chan %d\n", __func__,
+ channel_mode);
+ return -EINVAL;
+ }
+
+ open.mode = path;
+ open.endpoint_id1 = port_id;
+ open.endpoint_id2 = 0xFFFF;
+ open.bit_width = 16;
+
+ if (path == ADM_PATH_PLAYBACK)
+ open.topology_id = get_adm_rx_topology();
+ else {
+ open.topology_id = get_adm_tx_topology();
+ if ((open.topology_id ==
+ VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
+ (open.topology_id ==
+ VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
+ rate = 16000;
+ }
+
+ if (open.topology_id == 0)
+ open.topology_id = topology;
+
+ open.channel_config = channel_mode & 0x00FF;
+ open.rate = rate;
+ open.flags = 0;
+
+ pr_debug("%s: channel_config=%d port_id=%d rate=%d" \
+ "topology_id=0x%X\n", __func__, open.channel_config,\
+ open.endpoint_id1, open.rate,\
+ open.topology_id);
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
+ if (ret < 0) {
+ pr_err("%s:ADM enable for port %d failed\n",
+ __func__, port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ ret = wait_event_timeout(this_adm.wait,
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s ADM open failed for port %d\n", __func__,
+ port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ }
+ atomic_inc(&this_adm.copp_cnt[index]);
+ return 0;
+
+fail_cmd:
+ return ret;
+
+}
int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
int topology, int perfmode)
@@ -1127,6 +1339,56 @@
pr_debug("%s ec_ref_rx:%d", __func__, this_adm.ec_ref_rx);
}
+int adm_pseudo_close(int port_id)
+{
+ struct apr_hdr close;
+
+ int ret = 0, i = 0;
+ int index = 0;
+ int pseudo_copp_cnt;
+ index = afe_get_port_index(port_id);
+ if (afe_validate_port(port_id) < 0)
+ return -EINVAL;
+
+ pseudo_copp_cnt = atomic_read(&this_adm.copp_cnt[index]);
+ pr_debug("%s port_id=%d index %d copp_cnt %d\n", __func__, port_id,
+ index, pseudo_copp_cnt);
+
+ for (i = 0; i < pseudo_copp_cnt; i++) {
+ close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ close.pkt_size = sizeof(close);
+ close.src_svc = APR_SVC_ADM;
+ close.src_domain = APR_DOMAIN_APPS;
+ close.src_port = port_id;
+ close.dest_svc = APR_SVC_ADM;
+ close.dest_domain = APR_DOMAIN_ADSP;
+ close.dest_port = pseudo_copp[i];
+ close.token = port_id;
+ close.opcode = ADM_CMD_COPP_CLOSE;
+
+ atomic_set(&this_adm.copp_id[index], RESET_COPP_ID);
+ atomic_set(&this_adm.copp_stat[index], 0);
+
+
+ pr_debug("%s:coppid %d portid=%d index=%d coppcnt=%d\n",
+ __func__,
+ atomic_read(&this_adm.copp_id[index]),
+ port_id, index,
+ atomic_read(&this_adm.copp_cnt[index]));
+
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
+
+ ret = wait_event_timeout(this_adm.wait,
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ }
+
+ atomic_set(&this_adm.copp_cnt[index], 0);
+ return ret;
+
+}
+
int adm_close(int port_id)
{
struct apr_hdr close;
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index a4f4b60..9c62a2e 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -156,6 +156,7 @@
case VOICE_PLAYBACK_TX:
case RT_PROXY_PORT_001_RX:
case SLIMBUS_4_RX:
+ case PSEUDOPORT_01:
ret = MSM_AFE_PORT_TYPE_RX;
break;
@@ -225,6 +226,7 @@
case RT_PROXY_PORT_001_TX:
case SLIMBUS_4_RX:
case SLIMBUS_4_TX:
+ case PSEUDOPORT_01:
{
ret = 0;
break;
@@ -295,6 +297,7 @@
case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
+ case PSEUDOPORT_01: return IDX_PSEUDOPORT_01;
default: return -EINVAL;
}
@@ -331,6 +334,9 @@
case RT_PROXY_PORT_001_TX:
ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
break;
+ case PSEUDOPORT_01:
+ ret_size = SIZEOF_CFG_CMD(afe_port_pseudo_cfg);
+ break;
case PCM_RX:
case PCM_TX:
case SECONDARY_PCM_RX:
@@ -506,6 +512,11 @@
else
config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
break;
+ case PSEUDOPORT_01:
+ config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+ pr_debug("%s, config, opcode=%x\n", __func__,
+ config.hdr.opcode);
+ break;
default:
config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
break;
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 5f3bff2..7b52956 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -893,6 +893,7 @@
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
+ case ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK:
if (atomic_read(&ac->cmd_state) && wakeup_flag) {
atomic_set(&ac->cmd_state, 0);
pr_debug("response payload[1]:%d",
@@ -1065,6 +1066,114 @@
return 0;
}
+int q6asm_open_transcode_loopback(struct audio_client *ac, uint32_t channels)
+{
+ int rc = 0x00;
+ struct asm_stream_cmd_open_transcode_loopback open;
+
+ if ((ac == NULL) || (ac->apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s: session[%d] channels = %d", __func__, ac->session,
+ channels);
+
+ q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
+
+ open.hdr.opcode = ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK;
+
+ open.mode_flags = 0;
+
+ if (channels > 2)
+ open.src_format_id = MULTI_CHANNEL_PCM;
+ else
+ open.src_format_id = LINEAR_PCM;
+
+
+ open.sink_format_id = DTS;
+ open.audproc_topo_id = DEFAULT_POPP_TOPOLOGY;
+ open.src_endpoint_type = 0;
+ open.sink_endpoint_type = 0;
+ open.bits_per_sample = 16;
+ open.reserved = 0;
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
+ if (rc < 0) {
+ pr_err("%s: open failed op[0x%x]rc[%d]\n", \
+ __func__, open.hdr.opcode, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
+ rc);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
+
+int q6asm_enc_cfg_blk_dts(struct audio_client *ac,
+ uint32_t sample_rate,
+ uint32_t channels)
+{
+ struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
+ int rc = 0;
+
+ pr_debug("%s: sample_rate=%d,channels=%d\n", __func__,
+ sample_rate, channels);
+
+ q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
+
+ enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+ enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
+ enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
+ enc_cfg.enc_blk.frames_per_buf = 0;
+ enc_cfg.enc_blk.format_id = DTS;
+ enc_cfg.enc_blk.cfg_size = sizeof(struct asm_dts_enc_cfg);
+ enc_cfg.enc_blk.cfg.dts.sample_rate = sample_rate;
+ enc_cfg.enc_blk.cfg.dts.num_channels = channels;
+ if (channels == 2) {
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[0] = PCM_CHANNEL_FL;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[1] = PCM_CHANNEL_FR;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[2] = 0;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[3] = 0;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[4] = 0;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[5] = 0;
+ } else if (channels == 4) {
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[0] = PCM_CHANNEL_FL;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[1] = PCM_CHANNEL_FR;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[2] = PCM_CHANNEL_LS;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[3] = PCM_CHANNEL_RS;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[4] = 0;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[5] = 0;
+ } else if (channels == 6) {
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[0] = PCM_CHANNEL_FL;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[1] = PCM_CHANNEL_FR;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[2] = PCM_CHANNEL_LFE;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[3] = PCM_CHANNEL_LS;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[4] = PCM_CHANNEL_RS;
+ enc_cfg.enc_blk.cfg.dts.channel_mapping[5] = PCM_CHANNEL_FC;
+ }
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
+ if (rc < 0) {
+ pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("timeout. waited for FORMAT_UPDATE\n");
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
+
void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size,
uint32_t *index)
{