Merge "arm/dt: zinc: Add initial device tree for MSMZINC"
diff --git a/Documentation/cgroups/cpuacct.txt b/Documentation/cgroups/cpuacct.txt
index e21a932..9d73cc0 100644
--- a/Documentation/cgroups/cpuacct.txt
+++ b/Documentation/cgroups/cpuacct.txt
@@ -39,13 +39,6 @@
user and system are in USER_HZ unit.
-cpuacct.cpufreq file gives CPU time (in nanoseconds) spent at each CPU
-frequency. Platform hooks must be implemented inorder to properly track
-time at each CPU frequency.
-
-cpuacct.power file gives CPU power consumed (in milliWatt seconds). Platform
-must provide and implement power callback functions.
-
cpuacct controller uses percpu_counter interface to collect user and
system times. This has two side effects:
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
index 6d22003..195a98d 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
@@ -8,17 +8,24 @@
lpm-level. The units for voltage are dependent on the PMIC used on the target
and are in uV.
-The optional properties are:
-
-- qcom,use-qtimer: Indicates whether the target uses the synchronized QTimer.
-
The required nodes for lpm-levels are:
- compatible: "qcom,lpm-levels"
- reg: The numeric level id
-- qcom,mode: The sleep mode of the processor
-- qcom,xo: The state of XO clock.
-- qcom,l2: The state of L2 cache.
+- qcom,mode: The sleep mode of the processor, values for the property are:
+ "wfi" - Wait for Interrupt
+ "ramp_down_and_wfi" - Ramp down and wait for interrupt
+ "standalone_pc" - Standalone power collapse
+ "pc" - Power Collapse
+ "retention" - Retention
+ "pc_suspend" - Suspended Power Collapse
+ "pc_no_xo_shutdown" - Power Collapse with no XO shutdown
+- qcom,xo: The state of XO clock. Values are "xo_on" and "xo_off"
+- qcom,l2: The state of L2 cache. Values are:
+ "l2_cache_pc" - L2 cache in power collapse
+ "l2_cache_retenetion" - L2 cache in retention
+ "l2_cache_gdhs" - L2 cache in GDHS
+ "l2_cache_active" - L2 cache in active mode
- qcom,vdd-mem-upper-bound: The upper bound value of mem voltage in uV
- qcom,vdd-mem-lower-bound: The lower bound value of mem voltage in uV
- qcom,vdd-dig-upper-bound: The upper bound value of dig voltage in uV
@@ -41,6 +48,7 @@
- qcom,gpio-detectable: The field indicates whether the GPIOs can be detected
by the GPIO interrupt controller during a given low
power mode.
+- qcom,use-qtimer: Indicates whether the target uses the synchronized QTimer.
Example:
@@ -48,9 +56,9 @@
qcom,use-qtimer;
qcom,lpm-level@0 {
reg = <0>;
- qcom,mode = <0>; /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <3>; /* ACTIVE */
+ qcom,mode = "wfi";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
index ccb3465..7b5fda3 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
@@ -20,10 +20,9 @@
- reg: The numeric level id
- qcom,name: The name of the low power resource represented
as a string.
-- qcom,resource-type: The type of the LPM resource.
- MSM_LPM_RPM_RS_TYPE = 0
- MSM_LPM_LOCAL_RS_TYPE = 1
-- qcom,init-value: Initialization value of the LPM resource.
+- qcom,init-value: Initialization value of the LPM resource represented as
+ decimal value for vdd-dig and vdd-mem resources and
+ as string for pxo and l2 resources.
Optional Nodes:
@@ -33,12 +32,13 @@
- qcom,id: The id representing a device within a resource type.
- qcom,key: The key is the specific attribute of the resource being
monitored represented as a hex value.
+- qcom,local-resource-type: The property exists only for locally managed
+ resource and is represented as a bool.
Example:
qcom,lpm-resources@0 {
reg = <0x0>;
qcom,name = "vdd-dig";
- qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
diff --git a/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt b/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
index a372912..c741514 100644
--- a/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
+++ b/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
@@ -18,10 +18,10 @@
- reg: physical IMEM address reserved for PC counters and the size
- 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)
+ valid values for this are:
+ "tz_l2_int" (Power collapse terminates in TZ; integrated L2 cache controller)
+ "no_tz_l2_ext", (Power collapse doesn't terminate in TZ; external L2 cache controller)
+ "tz_l2_ext" (Power collapse terminates in TZ; external L2 cache controller)
- qcom,saw-turns-off-pll: Version of SAW2.1 or can turn off the HFPLL, when
doing power collapse and so the core need to switch to Global PLL before
PC.
@@ -31,6 +31,6 @@
qcom,pm-8x60@fe800664 {
compatible = "qcom,pm-8x60";
reg = <0xfe800664 0x40>;
- qcom,pc-mode = <0>;
+ qcom,pc-mode = "tz_l2_int";
qcom,use-sync-timer;
};
diff --git a/Documentation/devicetree/bindings/arm/msm/pm-boot.txt b/Documentation/devicetree/bindings/arm/msm/pm-boot.txt
index cce9d0e..7ba8a6d 100644
--- a/Documentation/devicetree/bindings/arm/msm/pm-boot.txt
+++ b/Documentation/devicetree/bindings/arm/msm/pm-boot.txt
@@ -16,10 +16,10 @@
- compatible: Must be "qcom,pm-boot"
- qcom,mode: The mode that the target will use for booting
- MSM_PM_BOOT_CONFIG_TZ = 0,
- MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS = 1,
- MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT = 2,
- MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR = 3,
+ "tz" = MSM_PM_BOOT_CONFIG_TZ,
+ "reset_vector_phys" = MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS,
+ "reset_vector_virt" = MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT,
+ "remap_boot_addr" = MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR,
Optional parameters (based on the mode chosen):
@@ -36,5 +36,5 @@
qcom,pm-boot {
compatible = "qcom,pm-boot";
- qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+ qcom,mode = "tz"; /* MSM_PM_BOOT_CONFIG_TZ */
};
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 1885e8a..9f8bbd9 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -15,7 +15,10 @@
"wakeup" : Wakeup interrupt from HSIC during suspend (or XO shutdown).
- hsic,<gpio-name>-gpio : handle to the GPIO node, see "gpios property"
in Documentation/devicetree/bindings/gpio/gpio.txt.
- Optional "gpio-name" can be "strobe" and "data".
+ Optional "gpio-name" can be "strobe", "data" and "resume".
+- hsic,resume-gpio : if present then periperal connected to hsic controller
+ cannot wakeup from XO shutdown using in-band hsic resume. Use resume
+ gpio to wakeup peripheral
- hsic,ignore-cal-pad-config : If present then HSIC CAL PAD configuration
using TLMM is not performed.
- hsic,strobe-pad-offset : Offset of TLMM register for configuring HSIC
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6839263..17a44b3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1830,13 +1830,6 @@
Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only.
-config VMALLOC_RESERVE
- hex "Reserved vmalloc space"
- default 0x08000000
- depends on MMU
- help
- Reserved vmalloc space if not specified on the kernel commandline.
-
source "mm/Kconfig"
config ARCH_MEMORY_PROBE
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
index 6348f5a..2351d9c 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -22,7 +22,7 @@
qcom,saw2-ver-reg = <0xfd0>;
qcom,saw2-cfg = <0x01>;
qcom,saw2-spm-dly= <0x3c102800>;
- qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-ctl = <0x0>;
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 2b 06 26 30 0f];
@@ -39,7 +39,7 @@
qcom,saw2-ver-reg = <0xfd0>;
qcom,saw2-cfg = <0x01>;
qcom,saw2-spm-dly= <0x3c102800>;
- qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-ctl = <0x0>;
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 2b 06 26 30 0f];
@@ -56,7 +56,7 @@
qcom,saw2-ver-reg = <0xfd0>;
qcom,saw2-cfg = <0x01>;
qcom,saw2-spm-dly= <0x3c102800>;
- qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-ctl = <0x0>;
qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 2b 06 26 30 0f];
@@ -73,7 +73,7 @@
qcom,saw2-ver-reg = <0xfd0>;
qcom,saw2-cfg = <0x01>;
qcom,saw2-spm-dly= <0x3c102800>;
- qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-ctl = <0x0>;
qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 2b 06 26 30 0f];
@@ -90,7 +90,7 @@
qcom,saw2-ver-reg = <0xfd0>;
qcom,saw2-cfg = <0x14>;
qcom,saw2-spm-dly= <0x3c102800>;
- qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-ctl = <0x0>;
qcom,saw2-pmic-data0 = <0x0400009c>;
qcom,saw2-pmic-data1 = <0x0000001c>;
qcom,vctl-timeout-us = <50>;
@@ -114,7 +114,6 @@
qcom,lpm-resources@0 {
reg = <0x0>;
qcom,name = "vdd-dig";
- qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
@@ -124,7 +123,6 @@
qcom,lpm-resources@1 {
reg = <0x1>;
qcom,name = "vdd-mem";
- qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x01>;
qcom,key = <0x7675>; /* "uv" */
@@ -134,18 +132,17 @@
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,init-value = <1>; /* On */
+ qcom,init-value = "xo_on";
};
qcom,lpm-resources@3 {
reg = <0x3>;
qcom,name = "l2";
- qcom,resource-type = <1>;
- qcom,init-value = <2>; /* Retention */
+ qcom,local-resource-type;
+ qcom,init-value = "l2_cache_retention";
};
};
@@ -156,9 +153,9 @@
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,mode = "wfi";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -171,9 +168,9 @@
qcom,lpm-level@1 {
reg = <0x1>;
- qcom,mode = <4>; /* MSM_PM_SLEEP_MODE_RETENTION*/
- qcom,xo = <1>; /* ON */
- qcom,l2 = <3>; /* ACTIVE */
+ qcom,mode = "retention";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -187,9 +184,9 @@
qcom,lpm-level@2 {
reg = <0x2>;
- qcom,mode = <2>; /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <3>; /* ACTIVE */
+ qcom,mode = "standalone_pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -202,9 +199,9 @@
qcom,lpm-level@3 {
reg = <0x3>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <1>; /* GDHS */
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_gdhs";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -217,9 +214,9 @@
qcom,lpm-level@4 {
reg = <0x4>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
@@ -232,9 +229,9 @@
qcom,lpm-level@5 {
reg = <0x5>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <1>; /* GDHS */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_gdhs";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -247,9 +244,9 @@
qcom,lpm-level@6 {
reg = <0x6>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -262,9 +259,9 @@
qcom,lpm-level@7 {
reg = <0x7>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
@@ -277,9 +274,9 @@
qcom,lpm-level@8 {
reg = <0x8>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
@@ -293,7 +290,7 @@
qcom,pm-boot {
compatible = "qcom,pm-boot";
- qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+ qcom,mode = "tz";
};
qcom,mpm@fc4281d0 {
@@ -392,7 +389,7 @@
qcom,pm-8x60@fe805664 {
compatible = "qcom,pm-8x60";
reg = <0xfe805664 0x40>;
- qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+ qcom,pc-mode = "tz_l2_int";
qcom,use-sync-timer;
};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 223675d..17de157 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -201,16 +201,14 @@
"DMIC3", "MIC BIAS3 External",
"MIC BIAS3 External", "Digital Mic3",
"DMIC4", "MIC BIAS3 External",
- "MIC BIAS3 External", "Digital Mic4",
- "DMIC5", "MIC BIAS4 External",
- "MIC BIAS4 External", "Digital Mic5",
- "DMIC6", "MIC BIAS4 External",
- "MIC BIAS4 External", "Digital Mic6";
+ "MIC BIAS3 External", "Digital Mic4";
+
qcom,tapan-mclk-clk-freq = <9600000>;
};
qcom,msm-pcm {
compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <0>;
};
qcom,msm-pcm-routing {
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index feb3087..d6e143c 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -114,7 +114,6 @@
qcom,lpm-resources@0 {
reg = <0x0>;
qcom,name = "vdd-dig";
- qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
@@ -124,7 +123,6 @@
qcom,lpm-resources@1 {
reg = <0x1>;
qcom,name = "vdd-mem";
- qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x01>;
qcom,key = <0x7675>; /* "uv" */
@@ -134,18 +132,17 @@
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,init-value = <1>; /* On */
+ qcom,init-value = "xo_on";
};
qcom,lpm-resources@3 {
reg = <0x3>;
qcom,name = "l2";
- qcom,resource-type = <1>;
- qcom,init-value = <2>; /* Retention */
+ qcom,local-resource-type;
+ qcom,init-value = "l2_cache_retention";
};
};
@@ -156,9 +153,9 @@
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,mode = "wfi";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -171,9 +168,9 @@
qcom,lpm-level@1 {
reg = <0x1>;
- qcom,mode = <4>; /* MSM_PM_SLEEP_MODE_RETENTION*/
- qcom,xo = <1>; /* ON */
- qcom,l2 = <3>; /* ACTIVE */
+ qcom,mode = "retention";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -187,9 +184,9 @@
qcom,lpm-level@2 {
reg = <0x2>;
- qcom,mode = <2>; /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <3>; /* ACTIVE */
+ qcom,mode = "standalone_pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -202,9 +199,9 @@
qcom,lpm-level@3 {
reg = <0x3>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <1>; /* GDHS */
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_gdhs";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -217,9 +214,9 @@
qcom,lpm-level@4 {
reg = <0x4>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
@@ -232,9 +229,9 @@
qcom,lpm-level@5 {
reg = <0x5>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <1>; /* GDHS */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_gdhs";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -247,9 +244,9 @@
qcom,lpm-level@6 {
reg = <0x6>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
qcom,vdd-dig-upper-bound = <5>; /* MAX */
@@ -262,9 +259,9 @@
qcom,lpm-level@7 {
reg = <0x7>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
@@ -277,9 +274,9 @@
qcom,lpm-level@8 {
reg = <0x8>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
@@ -293,7 +290,7 @@
qcom,pm-boot {
compatible = "qcom,pm-boot";
- qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+ qcom,mode = "tz";
};
qcom,mpm@fc4281d0 {
@@ -385,7 +382,7 @@
qcom,pm-8x60@fe805664 {
compatible = "qcom,pm-8x60";
reg = <0xfe805664 0x40>;
- qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+ qcom,pc-mode = "tz_l2_int";
qcom,use-sync-timer;
};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 2b1cbb5..45cbc89 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -213,6 +213,7 @@
HSIC_GDSC-supply = <&gdsc_usb_hsic>;
hsic,strobe-gpio = <&msmgpio 144 0x00>;
hsic,data-gpio = <&msmgpio 145 0x00>;
+ hsic,resume-gpio = <&msmgpio 80 0x00>;
hsic,ignore-cal-pad-config;
hsic,strobe-pad-offset = <0x2050>;
hsic,data-pad-offset = <0x2054>;
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index 0b6fa8c..d8a1444 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -139,7 +139,6 @@
qcom,lpm-resources@0 {
reg = <0x0>;
qcom,name = "vdd-dig";
- qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
@@ -149,7 +148,6 @@
qcom,lpm-resources@1 {
reg = <0x1>;
qcom,name = "vdd-mem";
- qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x01>;
qcom,key = <0x7675>; /* "uv" */
@@ -159,18 +157,17 @@
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,init-value = <1>; /* On */
+ qcom,init-value = "xo_on";
};
qcom,lpm-resources@3 {
reg = <0x3>;
qcom,name = "l2";
- qcom,resource-type = <1>;
- qcom,init-value = <2>; /* Retention */
+ qcom,local-resource-type;
+ qcom,init-value = "l2_cache_retention";
};
};
@@ -183,9 +180,9 @@
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,mode = "wfi";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -200,9 +197,9 @@
qcom,lpm-level@1 {
reg = <0x1>;
- qcom,mode = <4>; /* MSM_PM_SLEEP_MODE_RETENTION*/
- qcom,xo = <1>; /* ON */
- qcom,l2 = <3>; /* ACTIVE */
+ qcom,mode = "retention";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -218,9 +215,9 @@
qcom,lpm-level@2 {
reg = <0x2>;
- qcom,mode = <2>; /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <3>; /* ACTIVE */
+ qcom,mode = "standalone_pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -235,9 +232,9 @@
qcom,lpm-level@3 {
reg = <0x3>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <1>; /* GDHS */
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_gdhs";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -252,9 +249,9 @@
qcom,lpm-level@4 {
reg = <0x4>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -269,9 +266,9 @@
qcom,lpm-level@5 {
reg = <0x5>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <1>; /* GDHS */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_gdhs";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -284,9 +281,9 @@
qcom,lpm-level@6 {
reg = <0x6>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -299,9 +296,9 @@
qcom,lpm-level@7 {
reg = <0x7>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode= "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <950000>; /* NORMAL */
qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
@@ -314,9 +311,9 @@
qcom,lpm-level@8 {
reg = <0x8>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode= "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
@@ -330,7 +327,7 @@
qcom,pm-boot {
compatible = "qcom,pm-boot";
- qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+ qcom,mode = "tz";
};
qcom,mpm@fc4281d0 {
@@ -343,7 +340,8 @@
qcom,ipc-bit-offset = <1>;
qcom,gic-parent = <&intc>;
- qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
+ qcom,gic-map = <47 165>, /* usb30_hs_phy_irq */
+ <50 172>, /* usb1_hs_async_wakeup_irq */
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
<0xff 57>, /* mss_to_apps_irq(0) */
@@ -423,7 +421,7 @@
qcom,pm-8x60@fe805664 {
compatible = "qcom,pm-8x60";
reg = <0xfe805664 0x40>;
- qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+ qcom,pc-mode = "tz_l2_int";
qcom,use-sync-timer;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 8cc497b..e020fa4 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -15,8 +15,8 @@
/ {
qcom,spm@f9089000 {
compatible = "qcom,spm-v2";
- #address-cells = <1>;
- #size-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
reg = <0xf9089000 0x1000>;
qcom,core-id = <0>;
qcom,saw2-ver-reg = <0xfd0>;
@@ -29,10 +29,10 @@
qcom,saw2-spm-ctl = <0x1>;
qcom,saw2-spm-cmd-wfi = [03 0b 0f];
qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
- E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+ 30 06 26 30 0F];
qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
- E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+ E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
};
qcom,spm@f9099000 {
@@ -51,8 +51,8 @@
qcom,saw2-spm-ctl = <0x1>;
qcom,saw2-spm-cmd-wfi = [03 0b 0f];
qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
- E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+ 30 06 26 30 0F];
qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
};
@@ -73,8 +73,8 @@
qcom,saw2-spm-ctl = <0x1>;
qcom,saw2-spm-cmd-wfi = [03 0b 0f];
qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
- E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+ 30 06 26 30 0F];
qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
};
@@ -95,8 +95,8 @@
qcom,saw2-spm-ctl = <0x1>;
qcom,saw2-spm-cmd-wfi = [03 0b 0f];
qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
- E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+ 30 06 26 30 0F];
qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
};
@@ -136,7 +136,6 @@
qcom,lpm-resources@0 {
reg = <0x0>;
qcom,name = "vdd-dig";
- qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
@@ -146,7 +145,6 @@
qcom,lpm-resources@1 {
reg = <0x1>;
qcom,name = "vdd-mem";
- qcom,resource-type = <0>;
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x01>;
qcom,key = <0x7675>; /* "uv" */
@@ -156,18 +154,17 @@
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,init-value = <1>; /* On */
+ qcom,init-value = "xo_on";
};
qcom,lpm-resources@3 {
reg = <0x3>;
qcom,name = "l2";
- qcom,resource-type = <1>;
- qcom,init-value = <2>; /* Retention */
+ qcom,local-resource-type;
+ qcom,init-value = "l2_cache_retention";
};
};
@@ -180,9 +177,9 @@
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,mode = "wfi";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -197,9 +194,9 @@
qcom,lpm-level@1 {
reg = <0x1>;
- qcom,mode = <4>; /* MSM_PM_SLEEP_MODE_RETENTION*/
- qcom,xo = <1>; /* ON */
- qcom,l2 = <3>; /* ACTIVE */
+ qcom,mode = "retention";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -215,9 +212,9 @@
qcom,lpm-level@2 {
reg = <0x2>;
- qcom,mode = <2>; /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <3>; /* ACTIVE */
+ qcom,mode = "standalone_pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -232,9 +229,9 @@
qcom,lpm-level@3 {
reg = <0x3>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <1>; /* GDHS */
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_gdhs";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -249,9 +246,9 @@
qcom,lpm-level@4 {
reg = <0x4>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -266,9 +263,9 @@
qcom,lpm-level@5 {
reg = <0x5>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <1>; /* GDHS */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_gdhs";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -281,9 +278,9 @@
qcom,lpm-level@6 {
reg = <0x6>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -296,9 +293,9 @@
qcom,lpm-level@7 {
reg = <0x7>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode= "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <950000>; /* NORMAL */
qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
@@ -311,9 +308,9 @@
qcom,lpm-level@8 {
reg = <0x8>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode= "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
@@ -327,7 +324,7 @@
qcom,pm-boot {
compatible = "qcom,pm-boot";
- qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+ qcom,mode = "tz";
};
qcom,mpm@fc4281d0 {
@@ -340,7 +337,8 @@
qcom,ipc-bit-offset = <1>;
qcom,gic-parent = <&intc>;
- qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
+ qcom,gic-map = <47 165>, /* usb30_hs_phy_irq */
+ <50 172>, /* usb1_hs_async_wakeup_irq */
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
<0xff 57>, /* mss_to_apps_irq(0) */
@@ -420,7 +418,7 @@
qcom,pm-8x60@fe805664 {
compatible = "qcom,pm-8x60";
reg = <0xfe805664 0x40>;
- qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+ qcom,pc-mode = "tz_l2_int";
qcom,use-sync-timer;
qcom,saw-turns-off-pll;
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 3ebdbb6..2a5347e 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1374,8 +1374,8 @@
sfpb_spinlock: qcom,ipc-spinlock@fd484000 {
compatible = "qcom,ipc-spinlock-sfpb";
- reg = <0xfd484000 0x1000>;
- qcom,num-locks = <32>;
+ reg = <0xfd484000 0x400>;
+ qcom,num-locks = <8>;
};
ldrex_spinlock: qcom,ipc-spinlock@fa00000 {
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index e881977..51a3faa 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -38,7 +38,6 @@
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" */
@@ -48,7 +47,6 @@
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" */
@@ -58,11 +56,10 @@
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,init-value = <1>; /* On */
+ qcom,init-value = "xo_on";
};
};
@@ -75,9 +72,9 @@
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,mode = "wfi";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -92,9 +89,9 @@
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,mode = "standalone_pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_active";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -109,9 +106,9 @@
qcom,lpm-level@2 {
reg = <0x2>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <1>; /* GDHS */
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_gdhs";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -126,9 +123,9 @@
qcom,lpm-level@3 {
reg = <0x3>;
- qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <1>; /* ON */
- qcom,l2 = <0>; /* GDHS */
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
@@ -143,9 +140,9 @@
qcom,lpm-level@4 {
reg = <0x4>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -159,9 +156,9 @@
qcom,lpm-level@5 {
reg = <0x5>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
@@ -175,9 +172,9 @@
qcom,lpm-level@6 {
reg = <0x6>;
- qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
- qcom,xo = <0>; /* OFF */
- qcom,l2 = <0>; /* OFF */
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
@@ -191,7 +188,7 @@
qcom,pm-boot {
compatible = "qcom,pm-boot";
- qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+ qcom,mode = "tz";
};
qcom,mpm@fc4281d0 {
@@ -277,7 +274,7 @@
qcom,pm-8x60 {
compatible = "qcom,pm-8x60";
- qcom,pc-mode = <2>; /*MSM_PC_TZ_L2_EXT */
+ qcom,pc-mode = "tz_l2_ext";
qcom,use-sync-timer;
};
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index b163a5d..216fe99 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -105,6 +105,74 @@
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE_NF_EBTABLES=y
CONFIG_BRIDGE_EBT_BROUTE=y
CONFIG_BRIDGE=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index ea10007..224df83 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -474,3 +474,4 @@
CONFIG_PM_WAKELOCKS_LIMIT=0
CONFIG_PM_AUTOSLEEP=y
# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 077c7a6..e42aa77 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -499,3 +499,4 @@
CONFIG_PM_WAKELOCKS_LIMIT=0
CONFIG_PM_AUTOSLEEP=y
# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index f525eee..6e8fe3e 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -323,7 +323,6 @@
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_MSM_RTB=y
CONFIG_MSM_MEMORY_DUMP=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
CONFIG_PM_AUTOSLEEP=y
# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index f3a7b5c..9a32239 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -324,7 +324,6 @@
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_MSM_RTB=y
CONFIG_MSM_MEMORY_DUMP=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
CONFIG_PM_AUTOSLEEP=y
# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index dfcdb9f..c355aeb 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -110,6 +110,7 @@
unsigned long reboot_code_buffer_phys;
void *reboot_code_buffer;
+ arch_kexec();
page_list = image->head & PAGE_MASK;
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index c8bdb5d..48abd35 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2388,12 +2388,6 @@
}
}
-static void __init fsm8064_ep_pcie_init(void)
-{
- msm_device_pcie.dev.platform_data = &ep_pcie_platform_data;
- platform_device_register(&msm_device_pcie);
-}
-
static struct platform_device mpq8064_device_ext_3p3v_vreg = {
.name = "reg-fixed-voltage",
.dev = {
@@ -2401,6 +2395,12 @@
},
};
+static void __init fsm8064_ep_pcie_init(void)
+{
+ msm_device_pcie.dev.platform_data = &ep_pcie_platform_data;
+ platform_device_register(&msm_device_pcie);
+}
+
static struct platform_device apq8064_device_ext_5v_vreg __devinitdata = {
.name = GPIO_REGULATOR_DEV_NAME,
.id = PM8921_MPP_PM_TO_SYS(7),
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index b4f202d..2723e20 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -36,6 +36,7 @@
#ifdef CONFIG_ION_MSM
#include <mach/ion.h>
#endif
+#include <linux/regulator/qpnp-regulator.h>
#include <mach/msm_memtypes.h>
#include <mach/socinfo.h>
#include <mach/board.h>
@@ -96,6 +97,7 @@
msm_rpm_driver_init();
msm_lpmrs_module_init();
msm_spm_device_init();
+ qpnp_regulator_init();
msm_thermal_device_init();
if (machine_is_msm8610_rumi())
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index d8a9c3e..688c6f7 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -203,7 +203,6 @@
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_DOWN,
- .dir = GPIOMUX_OUT_LOW,
};
static struct gpiomux_setting hsic_act_cfg = {
@@ -219,6 +218,19 @@
.dir = GPIOMUX_IN,
};
+static struct gpiomux_setting hsic_resume_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting hsic_resume_susp_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
static struct msm_gpiomux_config msm_hsic_configs[] = {
{
.gpio = 144, /*HSIC_STROBE */
@@ -234,6 +246,13 @@
[GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
},
},
+ {
+ .gpio = 80,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_resume_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_resume_susp_cfg,
+ },
+ },
};
static struct msm_gpiomux_config msm_hsic_hub_configs[] = {
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 46af77d..d02ab66 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -32,6 +32,17 @@
#include "acpuclock.h"
+struct cpufreq_work_struct {
+ struct work_struct work;
+ struct cpufreq_policy *policy;
+ struct completion complete;
+ int frequency;
+ int status;
+};
+
+static DEFINE_PER_CPU(struct cpufreq_work_struct, cpufreq_work);
+static struct workqueue_struct *msm_cpufreq_wq;
+
struct cpufreq_suspend_t {
struct mutex suspend_mutex;
int device_suspended;
@@ -99,6 +110,15 @@
return ret;
}
+static void set_cpu_work(struct work_struct *work)
+{
+ struct cpufreq_work_struct *cpu_work =
+ container_of(work, struct cpufreq_work_struct, work);
+
+ cpu_work->status = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
+ complete(&cpu_work->complete);
+}
+
static int msm_cpufreq_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
@@ -107,11 +127,17 @@
int index;
struct cpufreq_frequency_table *table;
+ struct cpufreq_work_struct *cpu_work = NULL;
+ cpumask_var_t mask;
+
if (!cpu_active(policy->cpu)) {
pr_info("cpufreq: cpu %d is not active.\n", policy->cpu);
return -ENODEV;
}
+ if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+ return -ENOMEM;
+
mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
if (per_cpu(cpufreq_suspend, policy->cpu).device_suspended) {
@@ -133,9 +159,27 @@
policy->cpu, target_freq, relation,
policy->min, policy->max, table[index].frequency);
- ret = set_cpu_freq(policy, table[index].frequency);
+ cpu_work = &per_cpu(cpufreq_work, policy->cpu);
+ cpu_work->policy = policy;
+ cpu_work->frequency = table[index].frequency;
+ cpu_work->status = -ENODEV;
+
+ cpumask_clear(mask);
+ cpumask_set_cpu(policy->cpu, mask);
+ if (cpumask_equal(mask, ¤t->cpus_allowed)) {
+ ret = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
+ goto done;
+ } else {
+ cancel_work_sync(&cpu_work->work);
+ INIT_COMPLETION(cpu_work->complete);
+ queue_work_on(policy->cpu, msm_cpufreq_wq, &cpu_work->work);
+ wait_for_completion(&cpu_work->complete);
+ }
+
+ ret = cpu_work->status;
done:
+ free_cpumask_var(mask);
mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
return ret;
}
@@ -218,6 +262,7 @@
int cur_freq;
int index;
struct cpufreq_frequency_table *table;
+ struct cpufreq_work_struct *cpu_work = NULL;
table = cpufreq_frequency_get_table(policy->cpu);
if (table == NULL)
@@ -247,7 +292,7 @@
CPUFREQ_RELATION_H, &index) &&
cpufreq_frequency_table_target(policy, table, cur_freq,
CPUFREQ_RELATION_L, &index)) {
- pr_info("%s: cpu%d at invalid freq: %d\n", __func__,
+ pr_info("cpufreq: cpu%d at invalid freq: %d\n",
policy->cpu, cur_freq);
return -EINVAL;
}
@@ -268,6 +313,10 @@
policy->cpuinfo.transition_latency =
acpuclk_get_switch_time() * NSEC_PER_USEC;
+ cpu_work = &per_cpu(cpufreq_work, policy->cpu);
+ INIT_WORK(&cpu_work->work, set_cpu_work);
+ init_completion(&cpu_work->complete);
+
return 0;
}
@@ -355,6 +404,7 @@
per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
}
+ msm_cpufreq_wq = create_workqueue("msm-cpufreq");
register_hotcpu_notifier(&msm_cpufreq_cpu_notifier);
return cpufreq_register_driver(&msm_cpufreq_driver);
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index a104a42..d908a65 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -94,7 +94,7 @@
extern int msm_iommu_map_extra(struct iommu_domain *domain,
unsigned long start_iova,
- unsigned long phys_addr,
+ phys_addr_t phys_addr,
unsigned long size,
unsigned long page_size,
int cached);
@@ -104,7 +104,7 @@
unsigned long size,
unsigned long page_size);
-extern int msm_iommu_map_contig_buffer(unsigned long phys,
+extern int msm_iommu_map_contig_buffer(phys_addr_t phys,
unsigned int domain_no,
unsigned int partition_no,
unsigned long size,
@@ -148,7 +148,7 @@
static inline int msm_iommu_map_extra(struct iommu_domain *domain,
unsigned long start_iova,
- unsigned long phys_addr,
+ phys_addr_t phys_addr,
unsigned long size,
unsigned long page_size,
int cached)
@@ -163,7 +163,7 @@
{
}
-static inline int msm_iommu_map_contig_buffer(unsigned long phys,
+static inline int msm_iommu_map_contig_buffer(phys_addr_t phys,
unsigned int domain_no,
unsigned int partition_no,
unsigned long size,
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index f24dc87..5228abc 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -55,7 +55,7 @@
int msm_iommu_map_extra(struct iommu_domain *domain,
unsigned long start_iova,
- unsigned long phy_addr,
+ phys_addr_t phy_addr,
unsigned long size,
unsigned long page_size,
int prot)
@@ -135,7 +135,7 @@
static int msm_iommu_map_iova_phys(struct iommu_domain *domain,
unsigned long iova,
- unsigned long phys,
+ phys_addr_t phys,
unsigned long size,
int cached)
{
@@ -167,7 +167,7 @@
}
-int msm_iommu_map_contig_buffer(unsigned long phys,
+int msm_iommu_map_contig_buffer(phys_addr_t phys,
unsigned int domain_no,
unsigned int partition_no,
unsigned long size,
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 8fe69d9..953f941d 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -28,6 +28,7 @@
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/krait-regulator.h>
#include <linux/debugfs.h>
+#include <linux/syscore_ops.h>
#include <mach/msm_iomap.h>
#include "spm.h"
@@ -292,27 +293,6 @@
return 0;
}
-int krait_power_mdd_enable(int cpu_num, bool on)
-{
- /*
- * Expected to be called when the cpu goes to retention mode as a part
- * of idle power collapse. IT is guaranteed that cpu won't be put in
- * retention while being hotplugged out
- */
- struct krait_power_vreg *kvreg = per_cpu(krait_vregs, cpu_num);
-
- if (!on && kvreg->mode == LDO_MODE) {
- pr_debug("%s using LDO - cannot turn off MDD\n", kvreg->name);
- return -EINVAL;
- }
-
- if (on && kvreg->mode == LDO_MODE)
- return 0;
-
- __krait_power_mdd_enable(kvreg, on);
- return 0;
-}
-
static int switch_to_using_hs(struct krait_power_vreg *kvreg)
{
if (kvreg->mode == HS_MODE)
@@ -342,8 +322,6 @@
krait_masked_write(kvreg, APC_PWR_GATE_CTL,
LDO_PWR_DWN_MASK, LDO_PWR_DWN_MASK);
- /* turn off MDD since LDO is not used */
- __krait_power_mdd_enable(kvreg, false);
kvreg->mode = HS_MODE;
pr_debug("%s using BHS\n", kvreg->name);
return 0;
@@ -362,9 +340,6 @@
if (kvreg->mode == LDO_MODE)
switch_to_using_hs(kvreg);
- /* turn on MDD since LDO is being turned on */
- __krait_power_mdd_enable(kvreg, true);
-
set_krait_ldo_uv(kvreg, kvreg->uV - kvreg->ldo_delta_uV);
/*
@@ -792,8 +767,7 @@
int rc;
mutex_lock(&pvreg->krait_power_vregs_lock);
- if (kvreg->mode == LDO_MODE)
- __krait_power_mdd_enable(kvreg, true);
+ __krait_power_mdd_enable(kvreg, true);
kvreg->online = true;
rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
if (rc < 0)
@@ -823,8 +797,7 @@
goto dis_err;
rc = _set_voltage(rdev, kvreg->uV, kvreg->uV);
- if (kvreg->mode == LDO_MODE)
- __krait_power_mdd_enable(kvreg, false);
+ __krait_power_mdd_enable(kvreg, false);
dis_err:
mutex_unlock(&pvreg->krait_power_vregs_lock);
return rc;
@@ -889,6 +862,8 @@
/* setup the bandgap that configures the reference to the LDO */
writel_relaxed(0x00000190, kvreg->mdd_base + MDD_CONFIG_CTL);
+ /* Enable MDD */
+ writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
mb();
}
@@ -1112,6 +1087,26 @@
{}
};
+static int boot_cpu_mdd_off(void)
+{
+ struct krait_power_vreg *kvreg = per_cpu(krait_vregs, 0);
+
+ __krait_power_mdd_enable(kvreg, false);
+ return 0;
+}
+
+static void boot_cpu_mdd_on(void)
+{
+ struct krait_power_vreg *kvreg = per_cpu(krait_vregs, 0);
+
+ __krait_power_mdd_enable(kvreg, true);
+}
+
+static struct syscore_ops boot_cpu_mdd_ops = {
+ .suspend = boot_cpu_mdd_off,
+ .resume = boot_cpu_mdd_on,
+};
+
static int __devinit krait_pdn_probe(struct platform_device *pdev)
{
int rc;
@@ -1172,6 +1167,7 @@
dent = debugfs_create_dir(KRAIT_REGULATOR_DRIVER_NAME, NULL);
debugfs_create_file("retention_uV",
0644, dent, the_gang, &retention_fops);
+ register_syscore_ops(&boot_cpu_mdd_ops);
return 0;
}
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 8194721..aa33f2c 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -28,6 +28,8 @@
MSM_LPM_LVL_DBG_IDLE_LIMITS = BIT(1),
};
+#define MAX_STR_LEN 30
+
static int msm_lpm_lvl_dbg_msk;
module_param_named(
@@ -41,6 +43,48 @@
static DEFINE_PER_CPU(int , lpm_permitted_level);
static DEFINE_PER_CPU(struct atomic_notifier_head, lpm_notify_head);
+static int msm_pm_get_sleep_mode_value(struct device_node *node,
+ const char *key, uint32_t *sleep_mode_val)
+{
+ int i;
+ struct lpm_lookup_table {
+ uint32_t modes;
+ const char *mode_name;
+ };
+ struct lpm_lookup_table pm_sm_lookup[] = {
+ {MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
+ "wfi"},
+ {MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT,
+ "ramp_down_and_wfi"},
+ {MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
+ "standalone_pc"},
+ {MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ "pc"},
+ {MSM_PM_SLEEP_MODE_RETENTION,
+ "retention"},
+ {MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND,
+ "pc_suspend"},
+ {MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN,
+ "pc_no_xo_shutdown"}
+ };
+ int ret;
+ const char *mode_name;
+
+ ret = of_property_read_string(node, key, &mode_name);
+ if (!ret) {
+ ret = -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(pm_sm_lookup); i++) {
+ if (!strncmp(mode_name, pm_sm_lookup[i].mode_name,
+ MAX_STR_LEN)) {
+ *sleep_mode_val = pm_sm_lookup[i].modes;
+ ret = 0;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
static void msm_lpm_level_update(void)
{
unsigned int lpm_level;
@@ -343,19 +387,19 @@
level->available = false;
key = "qcom,mode";
- ret = of_property_read_u32(node, key, &val);
+ ret = msm_pm_get_sleep_mode_value(node, key, &val);
if (ret)
goto fail;
level->sleep_mode = val;
key = "qcom,xo";
- ret = of_property_read_u32(node, key, &val);
+ ret = msm_lpm_get_xo_value(node, key, &val);
if (ret)
goto fail;
level->rs_limits.pxo = val;
key = "qcom,l2";
- ret = of_property_read_u32(node, key, &val);
+ ret = msm_lpm_get_l2_cache_value(node, key, &val);
if (ret)
goto fail;
level->rs_limits.l2_cache = val;
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index 60184b4..f0e5ebd 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -51,29 +51,39 @@
#define MAX_RS_SIZE (4)
#define IS_RPM_CTL(rs) \
(!strncmp(rs->name, "rpm_ctl", MAX_RS_NAME))
+#define MAX_STR_LEN 30
static bool msm_lpm_beyond_limits_vdd_dig(struct msm_rpmrs_limits *limits);
static void msm_lpm_aggregate_vdd_dig(struct msm_rpmrs_limits *limits);
static void msm_lpm_flush_vdd_dig(int notify_rpm);
static void msm_lpm_notify_vdd_dig(struct msm_rpm_notifier_data
*rpm_notifier_cb);
+static int msm_lpm_init_value_vdd_dig(struct device_node *node,
+ char *key, uint32_t *default_value);
static bool msm_lpm_beyond_limits_vdd_mem(struct msm_rpmrs_limits *limits);
static void msm_lpm_aggregate_vdd_mem(struct msm_rpmrs_limits *limits);
static void msm_lpm_flush_vdd_mem(int notify_rpm);
static void msm_lpm_notify_vdd_mem(struct msm_rpm_notifier_data
*rpm_notifier_cb);
+static int msm_lpm_init_value_vdd_mem(struct device_node *node,
+ char *key, uint32_t *default_value);
+
static bool msm_lpm_beyond_limits_pxo(struct msm_rpmrs_limits *limits);
static void msm_lpm_aggregate_pxo(struct msm_rpmrs_limits *limits);
static void msm_lpm_flush_pxo(int notify_rpm);
static void msm_lpm_notify_pxo(struct msm_rpm_notifier_data
*rpm_notifier_cb);
+static int msm_lpm_init_value_pxo(struct device_node *node,
+ char *key, uint32_t *default_value);
static bool msm_lpm_beyond_limits_l2(struct msm_rpmrs_limits *limits);
static void msm_lpm_flush_l2(int notify_rpm);
static void msm_lpm_aggregate_l2(struct msm_rpmrs_limits *limits);
+static int msm_lpm_init_value_l2(struct device_node *node,
+ char *key, uint32_t *default_value);
static void msm_lpm_flush_rpm_ctl(int notify_rpm);
@@ -127,8 +137,14 @@
void (*flush)(int notify_rpm);
void (*notify)(struct msm_rpm_notifier_data *rpm_notifier_cb);
struct kobj_attribute ko_attr;
+ int (*init_value)(struct device_node *node,
+ char *key, uint32_t *default_value);
};
+struct lpm_lookup_table {
+ uint32_t modes;
+ const char *mode_name;
+};
static struct msm_lpm_resource msm_lpm_l2 = {
.name = "l2",
@@ -138,6 +154,7 @@
.notify = NULL,
.valid = false,
.ko_attr = RPMRS_ATTR(l2),
+ .init_value = msm_lpm_init_value_l2,
};
static struct msm_lpm_resource msm_lpm_vdd_dig = {
@@ -148,6 +165,7 @@
.notify = msm_lpm_notify_vdd_dig,
.valid = false,
.ko_attr = RPMRS_ATTR(vdd_dig),
+ .init_value = msm_lpm_init_value_vdd_dig,
};
static struct msm_lpm_resource msm_lpm_vdd_mem = {
@@ -158,6 +176,7 @@
.notify = msm_lpm_notify_vdd_mem,
.valid = false,
.ko_attr = RPMRS_ATTR(vdd_mem),
+ .init_value = msm_lpm_init_value_vdd_mem,
};
static struct msm_lpm_resource msm_lpm_pxo = {
@@ -168,6 +187,7 @@
.notify = msm_lpm_notify_pxo,
.valid = false,
.ko_attr = RPMRS_ATTR(pxo),
+ .init_value = msm_lpm_init_value_pxo,
};
static struct msm_lpm_resource *msm_lpm_resources[] = {
@@ -444,6 +464,12 @@
__func__, lpm);
}
+static int msm_lpm_init_value_l2(struct device_node *node,
+ char *key, uint32_t *default_value)
+{
+ return msm_lpm_get_l2_cache_value(node, key, default_value);
+}
+
static void msm_lpm_flush_l2(int notify_rpm)
{
struct msm_lpm_resource *rs = &msm_lpm_l2;
@@ -451,6 +477,34 @@
msm_lpm_set_l2_mode(rs->sleep_value, notify_rpm);
}
+int msm_lpm_get_l2_cache_value(struct device_node *node,
+ char *key, uint32_t *l2_val)
+{
+ int i;
+ struct lpm_lookup_table l2_mode_lookup[] = {
+ {MSM_LPM_L2_CACHE_HSFS_OPEN, "l2_cache_pc"},
+ {MSM_LPM_L2_CACHE_GDHS, "l2_cache_gdhs"},
+ {MSM_LPM_L2_CACHE_RETENTION, "l2_cache_retention"},
+ {MSM_LPM_L2_CACHE_ACTIVE, "l2_cache_active"}
+ };
+ const char *l2_str;
+ int ret;
+
+ ret = of_property_read_string(node, key, &l2_str);
+ if (!ret) {
+ ret = -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(l2_mode_lookup); i++) {
+ if (!strncmp(l2_str, l2_mode_lookup[i].mode_name,
+ MAX_STR_LEN)) {
+ *l2_val = l2_mode_lookup[i].modes;
+ ret = 0;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
/* RPM CTL */
static void msm_lpm_flush_rpm_ctl(int notify_rpm)
{
@@ -484,6 +538,12 @@
return ret;
}
+static int msm_lpm_init_value_vdd_dig(struct device_node *node,
+ char *key, uint32_t *default_value)
+{
+ return of_property_read_u32(node, key, default_value);
+}
+
static void msm_lpm_aggregate_vdd_dig(struct msm_rpmrs_limits *limits)
{
struct msm_lpm_resource *rs = &msm_lpm_vdd_dig;
@@ -570,6 +630,12 @@
msm_lpm_notify_common(rpm_notifier_cb, rs);
}
+static int msm_lpm_init_value_vdd_mem(struct device_node *node,
+ char *key, uint32_t *default_value)
+{
+ return of_property_read_u32(node, key, default_value);
+}
+
/*PXO*/
static bool msm_lpm_beyond_limits_pxo(struct msm_rpmrs_limits *limits)
{
@@ -628,11 +694,43 @@
msm_lpm_notify_common(rpm_notifier_cb, rs);
}
+static int msm_lpm_init_value_pxo(struct device_node *node,
+ char *key, uint32_t *default_value)
+{
+ return msm_lpm_get_xo_value(node, key, default_value);
+}
+
static inline bool msm_lpm_use_mpm(struct msm_rpmrs_limits *limits)
{
return (limits->pxo == MSM_LPM_PXO_OFF);
}
+int msm_lpm_get_xo_value(struct device_node *node,
+ char *key, uint32_t *xo_val)
+{
+ int i;
+ struct lpm_lookup_table pxo_mode_lookup[] = {
+ {MSM_LPM_PXO_OFF, "xo_off"},
+ {MSM_LPM_PXO_ON, "xo_on"}
+ };
+ const char *xo_str;
+ int ret;
+
+ ret = of_property_read_string(node, key, &xo_str);
+ if (!ret) {
+ ret = -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(pxo_mode_lookup); i++) {
+ if (!strncmp(xo_str, pxo_mode_lookup[i].mode_name,
+ MAX_STR_LEN)) {
+ *xo_val = pxo_mode_lookup[i].modes;
+ ret = 0;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
/* LPM levels interface */
bool msm_lpm_level_beyond_limit(struct msm_rpmrs_limits *limits)
{
@@ -797,7 +895,7 @@
struct msm_lpm_resource *rs = NULL;
const char *val;
int i;
- uint32_t resource_type;
+ bool local_resource;
key = "qcom,name";
ret = of_property_read_string(node, key, &val);
@@ -822,8 +920,7 @@
}
key = "qcom,init-value";
- ret = of_property_read_u32(node, key,
- &rs->rs_data.default_value);
+ ret = rs->init_value(node, key, &rs->rs_data.default_value);
if (ret) {
pr_err("%s():Failed to read %s\n", __func__, key);
goto fail;
@@ -831,18 +928,13 @@
rs->rs_data.value = rs->rs_data.default_value;
- key = "qcom,resource-type";
- ret = of_property_read_u32(node, key, &resource_type);
- if (ret) {
- pr_err("Failed to read resource-type\n");
- goto fail;
- }
+ key = "qcom,local-resource-type";
+ local_resource = of_property_read_bool(node, key);
- switch (resource_type) {
- case MSM_LPM_RPM_RS_TYPE:
+ if (!local_resource) {
key = "qcom,type";
ret = of_property_read_u32(node, key,
- &rs->rs_data.type);
+ &rs->rs_data.type);
if (ret) {
pr_err("Failed to read type\n");
goto fail;
@@ -873,15 +965,9 @@
goto fail;
}
/* fall through */
-
- case MSM_LPM_LOCAL_RS_TYPE:
- rs->valid = true;
- break;
- default:
- pr_err("%s: Invalid resource type %d", __func__,
- resource_type);
- goto fail;
}
+
+ rs->valid = true;
}
msm_rpm_register_notifier(&msm_lpm_rpm_nblk);
msm_lpm_init_rpm_ctl();
diff --git a/arch/arm/mach-msm/lpm_resources.h b/arch/arm/mach-msm/lpm_resources.h
index 1a2d72d..105cfe6 100644
--- a/arch/arm/mach-msm/lpm_resources.h
+++ b/arch/arm/mach-msm/lpm_resources.h
@@ -17,15 +17,15 @@
#include "test-lpm.h"
enum {
- MSM_LPM_PXO_OFF = 0,
- MSM_LPM_PXO_ON = 1,
+ MSM_LPM_PXO_OFF,
+ MSM_LPM_PXO_ON
};
enum {
- MSM_LPM_L2_CACHE_HSFS_OPEN = 0,
- MSM_LPM_L2_CACHE_GDHS = 1,
- MSM_LPM_L2_CACHE_RETENTION = 2,
- MSM_LPM_L2_CACHE_ACTIVE = 3,
+ MSM_LPM_L2_CACHE_HSFS_OPEN,
+ MSM_LPM_L2_CACHE_GDHS,
+ MSM_LPM_L2_CACHE_RETENTION,
+ MSM_LPM_L2_CACHE_ACTIVE,
};
struct msm_rpmrs_limits {
@@ -99,6 +99,24 @@
uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits);
/**
+ * msm_lpm_get_xo_value() - get the enum value for xo
+ * @node pointer to the device node
+ * @key pxo property key
+ * @xo_val xo enum value
+ */
+int msm_lpm_get_xo_value(struct device_node *node,
+ char *key, uint32_t *xo_val);
+
+/**
+ * msm_lpm_get_l2_cache_value() - get the enum value for l2 cache
+ * @node pointer to the device node
+ * @key l2 cache property key
+ * @l2_val l2 mode enum value
+ */
+int msm_lpm_get_l2_cache_value(struct device_node *node,
+ char *key, uint32_t *l2_val);
+
+/**
* struct msm_lpm_sleep_data - abstraction to get sleep data
* @limits: pointer to the msm_rpmrs_limits structure
* @kernel_sleep: kernel sleep time as decided by the power calculation
diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c
index d1538dd..1589623 100644
--- a/arch/arm/mach-msm/msm_rq_stats.c
+++ b/arch/arm/mach-msm/msm_rq_stats.c
@@ -31,6 +31,7 @@
#include <linux/tick.h>
#include <asm/smp_plat.h>
#include "acpuclock.h"
+#include <linux/suspend.h>
#define MAX_LONG_SIZE 24
#define DEFAULT_RQ_POLL_JIFFIES 1
@@ -206,6 +207,34 @@
return NOTIFY_OK;
}
+static int system_suspend_handler(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ switch (val) {
+ case PM_POST_HIBERNATION:
+ case PM_POST_SUSPEND:
+ rq_info.hotplug_disabled = 0;
+ case PM_HIBERNATION_PREPARE:
+ case PM_SUSPEND_PREPARE:
+ rq_info.hotplug_disabled = 1;
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+ return NOTIFY_OK;
+}
+
+
+static ssize_t hotplug_disable_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ unsigned int val = 0;
+ val = rq_info.hotplug_disabled;
+ return snprintf(buf, MAX_LONG_SIZE, "%d\n", val);
+}
+
+static struct kobj_attribute hotplug_disabled_attr = __ATTR_RO(hotplug_disable);
+
static void def_work_fn(struct work_struct *work)
{
int64_t diff;
@@ -310,6 +339,7 @@
&def_timer_ms_attr.attr,
&run_queue_avg_attr.attr,
&run_queue_poll_ms_attr.attr,
+ &hotplug_disabled_attr.attr,
NULL,
};
@@ -358,6 +388,7 @@
rq_info.def_timer_jiffies = DEFAULT_DEF_TIMER_JIFFIES;
rq_info.rq_poll_last_jiffy = 0;
rq_info.def_timer_last_jiffy = 0;
+ rq_info.hotplug_disabled = 0;
ret = init_rq_attribs();
rq_info.init = 1;
@@ -380,3 +411,16 @@
return ret;
}
late_initcall(msm_rq_stats_init);
+
+static int __init msm_rq_stats_early_init(void)
+{
+ /* Bail out if this is not an SMP Target */
+ if (!is_smp()) {
+ rq_info.init = 0;
+ return -ENOSYS;
+ }
+
+ pm_notifier(system_suspend_handler, 0);
+ return 0;
+}
+core_initcall(msm_rq_stats_early_init);
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index fc9a0fa..958edaf 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -208,16 +208,24 @@
return ret;
}
-static void pil_proxy_unvote(struct pil_desc *desc, unsigned long timeout)
+static void pil_proxy_unvote(struct pil_desc *desc, int immediate)
{
struct pil_priv *priv = desc->priv;
+ unsigned long timeout;
- if (proxy_timeout_ms >= 0)
+ if (proxy_timeout_ms == 0 && !immediate)
+ return;
+ else if (proxy_timeout_ms > 0)
timeout = proxy_timeout_ms;
+ else
+ timeout = desc->proxy_timeout;
- if (timeout && desc->ops->proxy_unvote) {
+ if (desc->ops->proxy_unvote) {
if (WARN_ON(!try_module_get(desc->owner)))
return;
+
+ if (immediate)
+ timeout = 0;
schedule_delayed_work(&priv->proxy, msecs_to_jiffies(timeout));
}
}
@@ -558,7 +566,6 @@
const struct elf32_hdr *ehdr;
struct pil_seg *seg;
const struct firmware *fw;
- unsigned long proxy_timeout = desc->proxy_timeout;
struct pil_priv *priv = desc->priv;
/* Reinitialize for new image */
@@ -633,12 +640,11 @@
ret = desc->ops->auth_and_reset(desc);
if (ret) {
pil_err(desc, "Failed to bring out of reset\n");
- proxy_timeout = 0; /* Remove proxy vote immediately on error */
goto err_boot;
}
pil_info(desc, "Brought out of reset\n");
err_boot:
- pil_proxy_unvote(desc, proxy_timeout);
+ pil_proxy_unvote(desc, ret);
release_fw:
release_firmware(fw);
out:
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index b52d284..7fbbf2c 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -128,6 +128,40 @@
static uint32_t msm_pm_max_sleep_time;
static bool msm_no_ramp_down_pc;
+static int msm_pm_get_pc_mode(struct device_node *node,
+ const char *key, uint32_t *pc_mode_val)
+{
+ struct pc_mode_of {
+ uint32_t mode;
+ char *mode_name;
+ };
+ int i;
+ struct pc_mode_of pc_modes[] = {
+ {MSM_PM_PC_TZ_L2_INT, "tz_l2_int"},
+ {MSM_PM_PC_NOTZ_L2_EXT, "no_tz_l2_ext"},
+ {MSM_PM_PC_TZ_L2_EXT , "tz_l2_ext"} };
+ int ret;
+ const char *pc_mode_str;
+
+ ret = of_property_read_string(node, key, &pc_mode_str);
+ if (ret) {
+ pr_debug("%s: Cannot read %s,defaulting to 0", __func__, key);
+ pc_mode_val = MSM_PM_PC_TZ_L2_INT;
+ ret = 0;
+ } else {
+ ret = -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(pc_modes); i++) {
+ if (!strncmp(pc_mode_str, pc_modes[i].mode_name,
+ strlen(pc_modes[i].mode_name))) {
+ *pc_mode_val = pc_modes[i].mode;
+ ret = 0;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
/*
* Write out the attribute.
*/
@@ -360,12 +394,10 @@
ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
WARN_ON(ret);
- krait_power_mdd_enable(smp_processor_id(), false);
}
static void msm_pm_config_hw_before_retention(void)
{
- krait_power_mdd_enable(smp_processor_id(), true);
return;
}
@@ -619,7 +651,7 @@
int64_t time = 0;
if (msm_pm_use_sync_timer)
- return ktime_to_ns(ktime_get());
+ return sched_clock();
time = msm_timer_get_sclk_time(period);
if (!time)
@@ -631,7 +663,7 @@
static int64_t msm_pm_timer_exit_suspend(int64_t time, int64_t period)
{
if (msm_pm_use_sync_timer)
- return ktime_to_ns(ktime_get()) - time;
+ return sched_clock() - time;
if (time != 0) {
int64_t end_time = msm_timer_get_sclk_time(NULL);
@@ -1257,7 +1289,6 @@
{
char *key = NULL;
struct dentry *dent = NULL;
- uint32_t val = 0;
struct resource *res = NULL;
int i ;
struct msm_pm_init_data_type pdata_local;
@@ -1299,14 +1330,14 @@
} else {
key = "qcom,pc-mode";
- ret = of_property_read_u32(pdev->dev.of_node, key, &val);
+ ret = msm_pm_get_pc_mode(pdev->dev.of_node,
+ key,
+ &pdata_local.pc_mode);
if (ret) {
- pr_debug("%s: Cannot read %s,defaulting to 0",
+ pr_debug("%s: Error reading key %s",
__func__, key);
- val = MSM_PM_PC_TZ_L2_INT;
- ret = 0;
+ return -EINVAL;
}
- pdata_local.pc_mode = val;
key = "qcom,use-sync-timer";
pdata_local.use_sync_timer =
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index c77b19c..3559510 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, 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
@@ -32,6 +32,42 @@
static void (*msm_pm_boot_before_pc)(unsigned int cpu, unsigned long entry);
static void (*msm_pm_boot_after_pc)(unsigned int cpu);
+
+static int msm_pm_get_boot_config_mode(struct device_node *dev,
+ const char *key, uint32_t *boot_config_mode)
+{
+ struct pm_lookup_table {
+ uint32_t boot_config_mode;
+ const char *boot_config_name;
+ };
+ const char *boot_config_str;
+ struct pm_lookup_table boot_config_lookup[] = {
+ {MSM_PM_BOOT_CONFIG_TZ, "tz"},
+ {MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS, "reset_vector_phys"},
+ {MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT, "reset_vector_virt"},
+ {MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR, "remap_boot_addr"}
+ };
+ int ret;
+ int i;
+
+ ret = of_property_read_string(dev, key, &boot_config_str);
+ if (!ret) {
+ ret = -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(boot_config_lookup); i++) {
+ if (!strncmp(boot_config_str,
+ boot_config_lookup[i].boot_config_name,
+ strlen(boot_config_lookup[i].boot_config_name))
+ ) {
+ *boot_config_mode =
+ boot_config_lookup[i].boot_config_mode;
+ ret = 0;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
static void msm_pm_write_boot_vector(unsigned int cpu, unsigned long address)
{
msm_pm_boot_vector[cpu] = address;
@@ -235,11 +271,9 @@
vaddr_val = 0;
key = "qcom,mode";
- ret = of_property_read_u32(pdev->dev.of_node, key, &val);
- if (ret) {
- pr_err("Unable to read boot mode Err(%d).\n", ret);
- return -ENODEV;
- }
+ ret = msm_pm_get_boot_config_mode(pdev->dev.of_node, key, &val);
+ if (ret)
+ goto fail;
pdata.mode = val;
key = "qcom,phy-addr";
diff --git a/arch/arm/mach-msm/pm-boot.h b/arch/arm/mach-msm/pm-boot.h
index 8ca3bb5..2d5110d 100644
--- a/arch/arm/mach-msm/pm-boot.h
+++ b/arch/arm/mach-msm/pm-boot.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, 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
@@ -18,10 +18,10 @@
/* end */
enum {
- MSM_PM_BOOT_CONFIG_TZ = 0,
- MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS = 1,
- MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT = 2,
- MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR = 3,
+ MSM_PM_BOOT_CONFIG_TZ ,
+ MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS,
+ MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT,
+ MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR ,
};
struct msm_pm_boot_platform_data {
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index c77304d..793b778 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -95,11 +95,11 @@
};
enum msm_pm_pc_mode_type {
- MSM_PM_PC_TZ_L2_INT = 0, /*Power collapse terminates in TZ;
+ MSM_PM_PC_TZ_L2_INT, /*Power collapse terminates in TZ;
integrated L2 cache controller */
- MSM_PM_PC_NOTZ_L2_EXT = 1, /* Power collapse doesn't terminate in
+ MSM_PM_PC_NOTZ_L2_EXT, /* Power collapse doesn't terminate in
TZ; external L2 cache controller */
- MSM_PM_PC_TZ_L2_EXT = 2, /* Power collapse terminates in TZ;
+ MSM_PM_PC_TZ_L2_EXT, /* Power collapse terminates in TZ;
external L2 cache controller */
};
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 2ec87b8..892b007 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -425,9 +425,9 @@
writel_relaxed(1, l2x0_base + L2X0_CTRL);
}
- outer_cache.inv_range = l2x0_inv_range;
- outer_cache.clean_range = l2x0_clean_range;
- outer_cache.flush_range = l2x0_flush_range;
+ outer_cache.inv_range = l2x0_inv_range;
+ outer_cache.clean_range = l2x0_clean_range;
+ outer_cache.flush_range = l2x0_flush_range;
outer_cache.sync = l2x0_cache_sync;
outer_cache.flush_all = l2x0_flush_all;
outer_cache.inv_all = l2x0_inv_all;
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 6ae5d03..6d28042 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -37,6 +37,7 @@
unsigned char dci_cumulative_event_mask[DCI_EVENT_MASK_SIZE];
struct mutex dci_log_mask_mutex;
struct mutex dci_event_mask_mutex;
+struct mutex dci_health_mutex;
#define DCI_CHK_CAPACITY(entry, new_data_len) \
((entry->data_len + new_data_len > entry->total_capacity) ? 1 : 0) \
@@ -211,6 +212,7 @@
entry = &(driver->dci_client_tbl[i]);
event_mask_ptr = entry->dci_event_mask +
byte_index;
+ mutex_lock(&dci_health_mutex);
if (*event_mask_ptr & byte_mask) {
/* copy to client buffer */
if (DCI_CHK_CAPACITY(entry,
@@ -218,7 +220,9 @@
pr_err("diag: DCI event drop\n");
driver->dci_client_tbl[i].
dropped_events++;
- return;
+ mutex_unlock(
+ &dci_health_mutex);
+ break;
}
driver->dci_client_tbl[i].
received_events++;
@@ -230,6 +234,7 @@
, total_event_len);
entry->data_len += 4 + total_event_len;
}
+ mutex_unlock(&dci_health_mutex);
}
}
temp_len += 2 + timestamp_len + payload_len_field + payload_len;
@@ -264,6 +269,7 @@
if (!log_mask_ptr)
return;
log_mask_ptr = log_mask_ptr + byte_offset;
+ mutex_lock(&dci_health_mutex);
if (*log_mask_ptr & byte_mask) {
pr_debug("\t log code %x needed by client %d",
log_code, entry->client->tgid);
@@ -273,6 +279,8 @@
pr_err("diag: DCI log drop\n");
driver->dci_client_tbl[i].
dropped_logs++;
+ mutex_unlock(
+ &dci_health_mutex);
return;
}
driver->dci_client_tbl[i].received_logs++;
@@ -282,6 +290,7 @@
buf + 4, *(uint16_t *)(buf + 2));
entry->data_len += 4 + *(uint16_t *)(buf + 2);
}
+ mutex_unlock(&dci_health_mutex);
}
}
}
@@ -1028,6 +1037,8 @@
mutex_init(&driver->dci_mutex);
mutex_init(&dci_log_mask_mutex);
mutex_init(&dci_event_mask_mutex);
+ mutex_init(&dci_health_mutex);
+
for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
success = diag_smd_constructor(&driver->smd_dci[i],
i, SMD_DCI_TYPE);
@@ -1082,5 +1093,118 @@
kfree(driver->req_tracking_tbl);
kfree(driver->dci_client_tbl);
kfree(driver->apps_dci_buf);
+ mutex_destroy(&driver->dci_mutex);
+ mutex_destroy(&dci_log_mask_mutex);
+ mutex_destroy(&dci_event_mask_mutex);
+ mutex_destroy(&dci_health_mutex);
destroy_workqueue(driver->diag_dci_wq);
}
+
+int diag_dci_clear_log_mask()
+{
+ int i, j, k, err = DIAG_DCI_NO_ERROR;
+ uint8_t *log_mask_ptr, *update_ptr;
+
+ i = diag_dci_find_client_index(current->tgid);
+ if (i == DCI_CLIENT_INDEX_INVALID)
+ return DIAG_DCI_TABLE_ERR;
+
+ mutex_lock(&dci_log_mask_mutex);
+ create_dci_log_mask_tbl(
+ driver->dci_client_tbl[i].dci_log_mask);
+ memset(dci_cumulative_log_mask,
+ 0x0, DCI_LOG_MASK_SIZE);
+ for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+ update_ptr = dci_cumulative_log_mask;
+ if (driver->dci_client_tbl[i].client) {
+ log_mask_ptr =
+ driver->dci_client_tbl[i].dci_log_mask;
+ for (j = 0; j < 16; j++) {
+ *update_ptr = j;
+ *(update_ptr + 1) = 1;
+ update_ptr += 2;
+ log_mask_ptr += 2;
+ for (k = 0; k < 513; k++) {
+ *update_ptr |= *log_mask_ptr;
+ update_ptr++;
+ log_mask_ptr++;
+ }
+ }
+ }
+ }
+ mutex_unlock(&dci_log_mask_mutex);
+ err = diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
+ return err;
+}
+
+int diag_dci_clear_event_mask()
+{
+ int i, j, err = DIAG_DCI_NO_ERROR;
+ uint8_t *event_mask_ptr, *update_ptr;
+
+ i = diag_dci_find_client_index(current->tgid);
+ if (i == DCI_CLIENT_INDEX_INVALID)
+ return DIAG_DCI_TABLE_ERR;
+
+ mutex_lock(&dci_event_mask_mutex);
+ memset(driver->dci_client_tbl[i].dci_event_mask,
+ 0x0, DCI_EVENT_MASK_SIZE);
+ memset(dci_cumulative_event_mask,
+ 0x0, DCI_EVENT_MASK_SIZE);
+ update_ptr = dci_cumulative_event_mask;
+ for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+ event_mask_ptr =
+ driver->dci_client_tbl[i].dci_event_mask;
+ for (j = 0; j < DCI_EVENT_MASK_SIZE; j++)
+ *(update_ptr + j) |= *(event_mask_ptr + j);
+ }
+ mutex_unlock(&dci_event_mask_mutex);
+ err = diag_send_dci_event_mask(driver->smd_cntl[MODEM_DATA].ch);
+ return err;
+}
+
+int diag_dci_query_log_mask(uint16_t log_code)
+{
+ uint16_t item_num;
+ uint8_t equip_id, *log_mask_ptr, byte_mask;
+ int i, byte_index, offset;
+
+ equip_id = LOG_GET_EQUIP_ID(log_code);
+ item_num = LOG_GET_ITEM_NUM(log_code);
+ byte_index = item_num/8 + 2;
+ byte_mask = 0x01 << (item_num % 8);
+ offset = equip_id * 514;
+
+ i = diag_dci_find_client_index(current->tgid);
+ if (i != DCI_CLIENT_INDEX_INVALID) {
+ log_mask_ptr = driver->dci_client_tbl[i].dci_log_mask;
+ log_mask_ptr = log_mask_ptr + offset + byte_index;
+ return ((*log_mask_ptr & byte_mask) == byte_mask) ?
+ 1 : 0;
+ }
+ return 0;
+}
+
+
+int diag_dci_query_event_mask(uint16_t event_id)
+{
+ uint8_t *event_mask_ptr, byte_mask;
+ int i, byte_index, bit_index;
+ byte_index = event_id/8;
+ bit_index = event_id % 8;
+ byte_mask = 0x1 << bit_index;
+
+ i = diag_dci_find_client_index(current->tgid);
+ if (i != DCI_CLIENT_INDEX_INVALID) {
+ event_mask_ptr =
+ driver->dci_client_tbl[i].dci_event_mask;
+ event_mask_ptr = event_mask_ptr + byte_index;
+ if ((*event_mask_ptr & byte_mask) == byte_mask)
+ return 1;
+ else
+ return 0;
+ }
+ return 0;
+}
+
+
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 9187516..260cdf3 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -37,6 +37,7 @@
extern unsigned int dci_max_reg;
extern unsigned int dci_max_clients;
+extern struct mutex dci_health_mutex;
struct dci_pkt_req_tracking_tbl {
int pid;
@@ -68,6 +69,13 @@
int reset_status;
};
+/* This is used for querying DCI Log
+ or Event Mask */
+struct diag_log_event_stats {
+ uint16_t code;
+ int is_set;
+};
+
enum {
DIAG_DCI_NO_ERROR = 1001, /* No error */
DIAG_DCI_NO_REG, /* Could not register */
@@ -96,10 +104,14 @@
void clear_client_dci_cumulative_log_mask(int client_index);
int diag_send_dci_log_mask(smd_channel_t *ch);
void extract_dci_log(unsigned char *buf);
+int diag_dci_clear_log_mask(void);
+int diag_dci_query_log_mask(uint16_t log_code);
/* DCI event streaming functions */
void update_dci_cumulative_event_mask(int offset, uint8_t byte_mask);
void clear_client_dci_cumulative_event_mask(int client_index);
int diag_send_dci_event_mask(smd_channel_t *ch);
void extract_dci_events(unsigned char *buf);
void create_dci_event_mask_tbl(unsigned char *tbl_buf);
+int diag_dci_clear_event_mask(void);
+int diag_dci_query_event_mask(uint16_t event_id);
#endif
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index df28dab..532df09 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -30,7 +30,6 @@
#define IN_BUF_SIZE 16384
#define MAX_IN_BUF_SIZE 32768
#define MAX_SYNC_OBJ_NAME_SIZE 32
-#define UINT32_MAX UINT_MAX
/* Size of the buffer used for deframing a packet
reveived from the PC tool*/
#define HDLC_MAX 4096
@@ -86,8 +85,8 @@
#define SMD_DCI_TYPE 2
/* Maximum number of pkt reg supported at initialization*/
-extern unsigned int diag_max_reg;
-extern unsigned int diag_threshold_reg;
+extern int diag_max_reg;
+extern int diag_threshold_reg;
#define APPEND_DEBUG(ch) \
do { \
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 3e3d8fd..c523457 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -66,8 +66,8 @@
static unsigned int max_clients = 15;
static unsigned int threshold_client_limit = 30;
/* This is the maximum number of pkt registrations supported at initialization*/
-unsigned int diag_max_reg = 600;
-unsigned int diag_threshold_reg = 750;
+int diag_max_reg = 600;
+int diag_threshold_reg = 750;
/* Timer variables */
static struct timer_list drain_timer;
@@ -522,143 +522,324 @@
int *pnum_data) { return 0; }
#endif
-long diagchar_ioctl(struct file *filp,
- unsigned int iocmd, unsigned long ioarg)
+int diag_command_reg(unsigned long ioarg)
{
- int i, j, temp, success = -1, status, index = -1;
- unsigned int count_entries = 0, interim_count = 0;
+ int i = 0, success = -EINVAL, j;
void *temp_buf;
- uint16_t support_list = 0;
- struct diag_dci_client_tbl *dci_params;
- struct diag_dci_health_stats stats;
-
- if (iocmd == DIAG_IOCTL_COMMAND_REG) {
- struct bindpkt_params_per_process pkt_params;
- struct bindpkt_params *params;
- struct bindpkt_params *head_params;
- if (copy_from_user(&pkt_params, (void *)ioarg,
- sizeof(struct bindpkt_params_per_process))) {
- return -EFAULT;
- }
- if ((UINT32_MAX/sizeof(struct bindpkt_params)) <
- pkt_params.count) {
- pr_warning("diag: integer overflow while multiply\n");
- return -EFAULT;
- }
- params = kzalloc(pkt_params.count*sizeof(
- struct bindpkt_params), GFP_KERNEL);
- if (!params) {
- pr_err("diag: unable to alloc memory\n");
- return -ENOMEM;
- } else
- head_params = params;
-
- if (copy_from_user(params, pkt_params.params,
- pkt_params.count*sizeof(struct bindpkt_params))) {
- kfree(head_params);
- return -EFAULT;
- }
- mutex_lock(&driver->diagchar_mutex);
- for (i = 0; i < diag_max_reg; i++) {
- if (driver->table[i].process_id == 0) {
- diag_add_reg(i, params, &success,
- &count_entries);
- if (pkt_params.count > count_entries) {
- params++;
- } else {
- mutex_unlock(&driver->diagchar_mutex);
- kfree(head_params);
- return success;
- }
+ unsigned int count_entries = 0, interim_count = 0;
+ struct bindpkt_params_per_process pkt_params;
+ struct bindpkt_params *params;
+ struct bindpkt_params *head_params;
+ if (copy_from_user(&pkt_params, (void *)ioarg,
+ sizeof(struct bindpkt_params_per_process))) {
+ return -EFAULT;
+ }
+ if ((UINT_MAX/sizeof(struct bindpkt_params)) <
+ pkt_params.count) {
+ pr_warn("diag: integer overflow while multiply\n");
+ return -EFAULT;
+ }
+ head_params = kzalloc(pkt_params.count*sizeof(
+ struct bindpkt_params), GFP_KERNEL);
+ if (!head_params) {
+ pr_err("diag: unable to alloc memory\n");
+ return -ENOMEM;
+ } else
+ params = head_params;
+ if (copy_from_user(params, pkt_params.params,
+ pkt_params.count*sizeof(struct bindpkt_params))) {
+ kfree(head_params);
+ return -EFAULT;
+ }
+ mutex_lock(&driver->diagchar_mutex);
+ for (i = 0; i < diag_max_reg; i++) {
+ if (driver->table[i].process_id == 0) {
+ diag_add_reg(i, params, &success,
+ &count_entries);
+ if (pkt_params.count > count_entries) {
+ params++;
+ } else {
+ kfree(head_params);
+ mutex_unlock(&driver->diagchar_mutex);
+ return success;
}
}
- if (i < diag_threshold_reg) {
- /* Increase table size by amount required */
+ }
+ if (i < diag_threshold_reg) {
+ /* Increase table size by amount required */
+ if (pkt_params.count >= count_entries) {
+ interim_count = pkt_params.count -
+ count_entries;
+ } else {
+ pr_warn("diag: error in params count\n");
+ kfree(head_params);
+ mutex_unlock(&driver->diagchar_mutex);
+ return -EFAULT;
+ }
+ if (UINT_MAX - diag_max_reg >=
+ interim_count) {
+ diag_max_reg += interim_count;
+ } else {
+ pr_warn("diag: Integer overflow\n");
+ kfree(head_params);
+ mutex_unlock(&driver->diagchar_mutex);
+ return -EFAULT;
+ }
+ /* Make sure size doesnt go beyond threshold */
+ if (diag_max_reg > diag_threshold_reg) {
+ diag_max_reg = diag_threshold_reg;
+ pr_err("diag: best case memory allocation\n");
+ }
+ if (UINT_MAX/sizeof(struct diag_master_table) <
+ diag_max_reg) {
+ pr_warn("diag: integer overflow\n");
+ kfree(head_params);
+ mutex_unlock(&driver->diagchar_mutex);
+ return -EFAULT;
+ }
+ temp_buf = krealloc(driver->table,
+ diag_max_reg*sizeof(struct
+ diag_master_table), GFP_KERNEL);
+ if (!temp_buf) {
+ pr_err("diag: Insufficient memory for reg.\n");
+
if (pkt_params.count >= count_entries) {
interim_count = pkt_params.count -
count_entries;
} else {
- pr_warning("diag: error in params count\n");
+ pr_warn("diag: params count error\n");
kfree(head_params);
mutex_unlock(&driver->diagchar_mutex);
return -EFAULT;
}
- if (UINT32_MAX - diag_max_reg >=
- interim_count) {
- diag_max_reg += interim_count;
+ if (diag_max_reg >= interim_count) {
+ diag_max_reg -= interim_count;
} else {
- pr_warning("diag: Integer overflow\n");
+ pr_warn("diag: Integer underflow\n");
kfree(head_params);
mutex_unlock(&driver->diagchar_mutex);
return -EFAULT;
}
- /* Make sure size doesnt go beyond threshold */
- if (diag_max_reg > diag_threshold_reg) {
- diag_max_reg = diag_threshold_reg;
- pr_info("diag: best case memory allocation\n");
- }
- if (UINT32_MAX/sizeof(struct diag_master_table) <
- diag_max_reg) {
- pr_warning("diag: integer overflow\n");
- kfree(head_params);
- mutex_unlock(&driver->diagchar_mutex);
- return -EFAULT;
- }
- temp_buf = krealloc(driver->table,
- diag_max_reg*sizeof(struct
- diag_master_table), GFP_KERNEL);
- if (!temp_buf) {
- pr_alert("diag: Insufficient memory for reg.\n");
- mutex_unlock(&driver->diagchar_mutex);
-
- if (pkt_params.count >= count_entries) {
- interim_count = pkt_params.count -
- count_entries;
- } else {
- pr_warning("diag: params count error\n");
- mutex_unlock(&driver->diagchar_mutex);
- kfree(head_params);
- return -EFAULT;
- }
- if (diag_max_reg >= interim_count) {
- diag_max_reg -= interim_count;
- } else {
- pr_warning("diag: Integer underflow\n");
- mutex_unlock(&driver->diagchar_mutex);
- kfree(head_params);
- return -EFAULT;
- }
- kfree(head_params);
- return 0;
- } else {
- driver->table = temp_buf;
- }
- for (j = i; j < diag_max_reg; j++) {
- diag_add_reg(j, params, &success,
- &count_entries);
- if (pkt_params.count > count_entries) {
- params++;
- } else {
- mutex_unlock(&driver->diagchar_mutex);
- kfree(head_params);
- return success;
- }
- }
kfree(head_params);
mutex_unlock(&driver->diagchar_mutex);
+ return 0;
} else {
- mutex_unlock(&driver->diagchar_mutex);
- kfree(head_params);
- pr_err("Max size reached, Pkt Registration failed for"
- " Process %d", current->tgid);
+ driver->table = temp_buf;
}
- success = 0;
- } else if (iocmd == DIAG_IOCTL_GET_DELAYED_RSP_ID) {
- struct diagpkt_delay_params delay_params;
- uint16_t interim_rsp_id;
- int interim_size;
+ for (j = i; j < diag_max_reg; j++) {
+ diag_add_reg(j, params, &success,
+ &count_entries);
+ if (pkt_params.count > count_entries) {
+ params++;
+ } else {
+ kfree(head_params);
+ mutex_unlock(&driver->diagchar_mutex);
+ return success;
+ }
+ }
+ kfree(head_params);
+ mutex_unlock(&driver->diagchar_mutex);
+ } else {
+ kfree(head_params);
+ mutex_unlock(&driver->diagchar_mutex);
+ pr_err("Max size reached, Pkt Registration failed for Process %d",
+ current->tgid);
+ }
+ success = 0;
+ return success;
+}
+
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode)
+{
+ if (old_mode == MEMORY_DEVICE_MODE && new_mode
+ == NO_LOGGING_MODE) {
+ diagfwd_disconnect_bridge(0);
+ diag_clear_hsic_tbl();
+ } else if (old_mode == NO_LOGGING_MODE && new_mode
+ == MEMORY_DEVICE_MODE) {
+ diagfwd_connect_bridge(0);
+ } else if (old_mode == USB_MODE && new_mode
+ == NO_LOGGING_MODE) {
+ diagfwd_disconnect_bridge(0);
+ } else if (old_mode == NO_LOGGING_MODE && new_mode
+ == USB_MODE) {
+ diagfwd_connect_bridge(0);
+ } else if (old_mode == USB_MODE && new_mode
+ == MEMORY_DEVICE_MODE) {
+ diagfwd_cancel_hsic();
+ diagfwd_connect_bridge(0);
+ } else if (old_mode == MEMORY_DEVICE_MODE && new_mode
+ == USB_MODE) {
+ diag_clear_hsic_tbl();
+ diagfwd_cancel_hsic();
+ diagfwd_connect_bridge(0);
+ }
+}
+#else
+void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode)
+{
+
+}
+#endif
+
+#ifdef CONFIG_DIAG_SDIO_PIPE
+void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode)
+{
+ if (old_mode == MEMORY_DEVICE_MODE && new_mode
+ == NO_LOGGING_MODE) {
+ mutex_lock(&driver->diagchar_mutex);
+ driver->in_busy_sdio = 1;
+ mutex_unlock(&driver->diagchar_mutex);
+ } else if (old_mode == NO_LOGGING_MODE && new_mode
+ == MEMORY_DEVICE_MODE) {
+ mutex_lock(&driver->diagchar_mutex);
+ driver->in_busy_sdio = 0;
+ mutex_unlock(&driver->diagchar_mutex);
+ /* Poll SDIO channel to check for data */
+ if (driver->sdio_ch)
+ queue_work(driver->diag_sdio_wq,
+ &(driver->diag_read_sdio_work));
+ } else if (old_mode == USB_MODE && new_mode
+ == MEMORY_DEVICE_MODE) {
+ mutex_lock(&driver->diagchar_mutex);
+ driver->in_busy_sdio = 0;
+ mutex_unlock(&driver->diagchar_mutex);
+ /* Poll SDIO channel to check for data */
+ if (driver->sdio_ch)
+ queue_work(driver->diag_sdio_wq,
+ &(driver->diag_read_sdio_work));
+ }
+}
+#else
+void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode)
+{
+
+}
+#endif
+
+int diag_switch_logging(unsigned long ioarg)
+{
+ int i, temp, success = -EINVAL, status;
+ mutex_lock(&driver->diagchar_mutex);
+ temp = driver->logging_mode;
+ driver->logging_mode = (int)ioarg;
+ if (temp == driver->logging_mode) {
+ mutex_unlock(&driver->diagchar_mutex);
+ pr_err("diag: forbidden logging change requested\n");
+ return 0;
+ }
+
+ if (driver->logging_mode == MEMORY_DEVICE_MODE) {
+ diag_clear_hsic_tbl();
+ driver->mask_check = 1;
+ if (driver->socket_process) {
+ /*
+ * Notify the socket logging process that we
+ * are switching to MEMORY_DEVICE_MODE
+ */
+ status = send_sig(SIGCONT,
+ driver->socket_process, 0);
+ if (status) {
+ pr_err("diag: %s, Error notifying ",
+ __func__);
+ pr_err("socket process, status: %d\n",
+ status);
+ }
+ }
+ } else if (driver->logging_mode == SOCKET_MODE) {
+ driver->socket_process = current;
+ } else if (driver->logging_mode == CALLBACK_MODE) {
+ driver->callback_process = current;
+ }
+
+ if (driver->logging_mode == UART_MODE ||
+ driver->logging_mode == SOCKET_MODE ||
+ driver->logging_mode == CALLBACK_MODE) {
+ diag_clear_hsic_tbl();
+ driver->mask_check = 0;
+ driver->logging_mode = MEMORY_DEVICE_MODE;
+ }
+
+ driver->logging_process_id = current->tgid;
+ mutex_unlock(&driver->diagchar_mutex);
+
+ if (temp == MEMORY_DEVICE_MODE && driver->logging_mode
+ == NO_LOGGING_MODE) {
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ driver->smd_data[i].in_busy_1 = 0;
+ driver->smd_data[i].in_busy_2 = 0;
+ }
+ diag_cmp_logging_modes_sdio_pipe(temp, driver->logging_mode);
+ diag_cmp_logging_modes_diagfwd_bridge(temp,
+ driver->logging_mode);
+ } else if (temp == NO_LOGGING_MODE && driver->logging_mode
+ == MEMORY_DEVICE_MODE) {
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ driver->smd_data[i].in_busy_1 = 0;
+ driver->smd_data[i].in_busy_2 = 0;
+ /* Poll SMD channels to check for data*/
+ if (driver->smd_data[i].ch)
+ queue_work(driver->diag_wq,
+ &(driver->smd_data[i].
+ diag_read_smd_work));
+ }
+ diag_cmp_logging_modes_sdio_pipe(temp,
+ driver->logging_mode);
+ diag_cmp_logging_modes_diagfwd_bridge(temp,
+ driver->logging_mode);
+ } else if (temp == USB_MODE && driver->logging_mode
+ == NO_LOGGING_MODE) {
+ diagfwd_disconnect();
+ diag_cmp_logging_modes_diagfwd_bridge(temp,
+ driver->logging_mode);
+ } else if (temp == NO_LOGGING_MODE && driver->logging_mode
+ == USB_MODE) {
+ diagfwd_connect();
+ diag_cmp_logging_modes_diagfwd_bridge(temp,
+ driver->logging_mode);
+ } else if (temp == USB_MODE && driver->logging_mode
+ == MEMORY_DEVICE_MODE) {
+ diagfwd_disconnect();
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ driver->smd_data[i].in_busy_1 = 0;
+ driver->smd_data[i].in_busy_2 = 0;
+ /* Poll SMD channels to check for data*/
+ if (driver->smd_data[i].ch)
+ queue_work(driver->diag_wq,
+ &(driver->smd_data[i].
+ diag_read_smd_work));
+ }
+ diag_cmp_logging_modes_sdio_pipe(temp, driver->logging_mode);
+ diag_cmp_logging_modes_diagfwd_bridge(temp,
+ driver->logging_mode);
+ } else if (temp == MEMORY_DEVICE_MODE &&
+ driver->logging_mode == USB_MODE) {
+ diagfwd_connect();
+ diag_cmp_logging_modes_diagfwd_bridge(temp,
+ driver->logging_mode);
+ }
+ success = 1;
+ return success;
+}
+
+long diagchar_ioctl(struct file *filp,
+ unsigned int iocmd, unsigned long ioarg)
+{
+ int i, result = -EINVAL, interim_size = 0, client_id = 0;
+ uint16_t support_list = 0, interim_rsp_id, remote_dev;
+ struct diag_dci_client_tbl *dci_params;
+ struct diag_dci_health_stats stats;
+ struct diag_log_event_stats le_stats;
+ struct diagpkt_delay_params delay_params;
+
+ switch (iocmd) {
+ case DIAG_IOCTL_COMMAND_REG:
+ result = diag_command_reg(ioarg);
+ break;
+ case DIAG_IOCTL_GET_DELAYED_RSP_ID:
if (copy_from_user(&delay_params, (void *)ioarg,
- sizeof(struct diagpkt_delay_params)))
+ sizeof(struct diagpkt_delay_params)))
return -EFAULT;
if ((delay_params.rsp_ptr) &&
(delay_params.size == sizeof(delayed_rsp_id)) &&
@@ -672,9 +853,10 @@
if (copy_to_user((void *)delay_params.num_bytes_ptr,
&interim_size, sizeof(int)))
return -EFAULT;
- success = 0;
+ result = 0;
}
- } else if (iocmd == DIAG_IOCTL_DCI_REG) {
+ break;
+ case DIAG_IOCTL_DCI_REG:
if (driver->dci_state == DIAG_DCI_NO_REG)
return DIAG_DCI_NO_REG;
if (driver->num_dci_client >= MAX_DCI_CLIENTS)
@@ -723,49 +905,47 @@
}
kfree(dci_params);
mutex_unlock(&driver->dci_mutex);
- return driver->dci_client_id;
- } else if (iocmd == DIAG_IOCTL_DCI_DEINIT) {
- success = -1;
- /*
- * Clear log/event masks and send updated
- * masks to peripherals
- */
+ result = driver->dci_client_id;
+ break;
+ case DIAG_IOCTL_DCI_DEINIT:
+ result = -EIO;
+ /* Delete this process from DCI table */
mutex_lock(&driver->dci_mutex);
- index = diag_dci_find_client_index(current->tgid);
- if (index != DCI_CLIENT_INDEX_INVALID) {
+ i = diag_dci_find_client_index(current->tgid);
+ if (i == DCI_CLIENT_INDEX_INVALID) {
+ result = DIAG_DCI_NOT_SUPPORTED;
+ } else {
/* clear respective cumulative log masks */
- clear_client_dci_cumulative_log_mask(index);
+ clear_client_dci_cumulative_log_mask(i);
/* send updated log mask to peripherals */
- success =
+ result =
diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
- if (success != DIAG_DCI_NO_ERROR) {
+ if (result != DIAG_DCI_NO_ERROR) {
mutex_unlock(&driver->dci_mutex);
- return success;
+ return result;
}
/* clear respective cumulative event masks */
- clear_client_dci_cumulative_event_mask(index);
+ clear_client_dci_cumulative_event_mask(i);
/* send updated event mask to peripherals */
- success =
+ result =
diag_send_dci_event_mask(
driver->smd_cntl[MODEM_DATA].ch);
- if (success != DIAG_DCI_NO_ERROR) {
+ if (result != DIAG_DCI_NO_ERROR) {
mutex_unlock(&driver->dci_mutex);
- return success;
+ return result;
}
- }
- /* Delete this process from DCI table */
- for (i = 0; i < dci_max_reg; i++)
- if (driver->req_tracking_tbl[i].pid == current->tgid)
- driver->req_tracking_tbl[i].pid = 0;
- if (index != DCI_CLIENT_INDEX_INVALID) {
- driver->dci_client_tbl[index].client = NULL;
- success = index;
- }
- if (success >= 0)
+ result = i;
+ /* Delete this process from DCI table */
+ for (i = 0; i < dci_max_reg; i++)
+ if (driver->req_tracking_tbl[i].pid ==
+ current->tgid)
+ driver->req_tracking_tbl[i].pid = 0;
+ driver->dci_client_tbl[result].client = NULL;
driver->num_dci_client--;
+ }
mutex_unlock(&driver->dci_mutex);
- return success;
- } else if (iocmd == DIAG_IOCTL_DCI_SUPPORT) {
+ break;
+ case DIAG_IOCTL_DCI_SUPPORT:
for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
if (driver->smd_dci[i].ch)
support_list |=
@@ -774,35 +954,69 @@
if (copy_to_user((void *)ioarg, &support_list,
sizeof(uint16_t)))
return -EFAULT;
- return DIAG_DCI_NO_ERROR;
- } else if (iocmd == DIAG_IOCTL_DCI_HEALTH_STATS) {
+ result = DIAG_DCI_NO_ERROR;
+ break;
+ case DIAG_IOCTL_DCI_HEALTH_STATS:
if (copy_from_user(&stats, (void *)ioarg,
sizeof(struct diag_dci_health_stats)))
return -EFAULT;
- for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+ mutex_lock(&dci_health_mutex);
+ i = diag_dci_find_client_index(current->tgid);
+ if (i != DCI_CLIENT_INDEX_INVALID) {
dci_params = &(driver->dci_client_tbl[i]);
- if (dci_params->client &&
- dci_params->client->tgid == current->tgid) {
- stats.dropped_logs = dci_params->dropped_logs;
- stats.dropped_events =
- dci_params->dropped_events;
- stats.received_logs = dci_params->received_logs;
- stats.received_events =
- dci_params->received_events;
- if (stats.reset_status) {
- dci_params->dropped_logs = 0;
- dci_params->dropped_events = 0;
- dci_params->received_logs = 0;
- dci_params->received_events = 0;
- }
- break;
+ stats.dropped_logs = dci_params->dropped_logs;
+ stats.dropped_events =
+ dci_params->dropped_events;
+ stats.received_logs =
+ dci_params->received_logs;
+ stats.received_events =
+ dci_params->received_events;
+ if (stats.reset_status) {
+ dci_params->dropped_logs = 0;
+ dci_params->dropped_events = 0;
+ dci_params->received_logs = 0;
+ dci_params->received_events = 0;
}
}
+ mutex_unlock(&dci_health_mutex);
if (copy_to_user((void *)ioarg, &stats,
sizeof(struct diag_dci_health_stats)))
return -EFAULT;
- return DIAG_DCI_NO_ERROR;
- } else if (iocmd == DIAG_IOCTL_LSM_DEINIT) {
+ result = DIAG_DCI_NO_ERROR;
+ break;
+ case DIAG_IOCTL_DCI_LOG_STATUS:
+ if (copy_from_user(&le_stats, (void *)ioarg,
+ sizeof(struct diag_log_event_stats)))
+ return -EFAULT;
+ le_stats.is_set = diag_dci_query_log_mask(le_stats.code);
+ if (copy_to_user((void *)ioarg, &le_stats,
+ sizeof(struct diag_log_event_stats)))
+ return -EFAULT;
+ result = DIAG_DCI_NO_ERROR;
+ break;
+ case DIAG_IOCTL_DCI_EVENT_STATUS:
+ if (copy_from_user(&le_stats, (void *)ioarg,
+ sizeof(struct diag_log_event_stats)))
+ return -EFAULT;
+ le_stats.is_set = diag_dci_query_event_mask(le_stats.code);
+ if (copy_to_user((void *)ioarg, &le_stats,
+ sizeof(struct diag_log_event_stats)))
+ return -EFAULT;
+ result = DIAG_DCI_NO_ERROR;
+ break;
+ case DIAG_IOCTL_DCI_CLEAR_LOGS:
+ if (copy_from_user((void *)&client_id, (void *)ioarg,
+ sizeof(int)))
+ return -EFAULT;
+ result = diag_dci_clear_log_mask();
+ break;
+ case DIAG_IOCTL_DCI_CLEAR_EVENTS:
+ if (copy_from_user(&client_id, (void *)ioarg,
+ sizeof(int)))
+ return -EFAULT;
+ result = diag_dci_clear_event_mask();
+ break;
+ case DIAG_IOCTL_LSM_DEINIT:
for (i = 0; i < driver->num_clients; i++)
if (driver->client_map[i].pid == current->tgid)
break;
@@ -810,138 +1024,20 @@
return -EINVAL;
driver->data_ready[i] |= DEINIT_TYPE;
wake_up_interruptible(&driver->wait_q);
- success = 1;
- } else if (iocmd == DIAG_IOCTL_SWITCH_LOGGING) {
- mutex_lock(&driver->diagchar_mutex);
- temp = driver->logging_mode;
- driver->logging_mode = (int)ioarg;
- if (temp == driver->logging_mode) {
- mutex_unlock(&driver->diagchar_mutex);
- pr_alert("diag: forbidden logging change requested\n");
- return 0;
- }
- if (driver->logging_mode == MEMORY_DEVICE_MODE) {
- diag_clear_hsic_tbl();
- driver->mask_check = 1;
- if (driver->socket_process) {
- /*
- * Notify the socket logging process that we
- * are switching to MEMORY_DEVICE_MODE
- */
- status = send_sig(SIGCONT,
- driver->socket_process, 0);
- if (status) {
- pr_err("diag: %s, Error notifying ",
- __func__);
- pr_err("socket process, status: %d\n",
- status);
- }
- }
- }
- if (driver->logging_mode == SOCKET_MODE)
- driver->socket_process = current;
- if (driver->logging_mode == CALLBACK_MODE)
- driver->callback_process = current;
- if (driver->logging_mode == UART_MODE ||
- driver->logging_mode == SOCKET_MODE ||
- driver->logging_mode == CALLBACK_MODE) {
- diag_clear_hsic_tbl();
- driver->mask_check = 0;
- driver->logging_mode = MEMORY_DEVICE_MODE;
- }
- driver->logging_process_id = current->tgid;
- mutex_unlock(&driver->diagchar_mutex);
- if (temp == MEMORY_DEVICE_MODE && driver->logging_mode
- == NO_LOGGING_MODE) {
- for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
- driver->smd_data[i].in_busy_1 = 0;
- driver->smd_data[i].in_busy_2 = 0;
- }
-#ifdef CONFIG_DIAG_SDIO_PIPE
- driver->in_busy_sdio = 1;
-#endif
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
- diagfwd_disconnect_bridge(0);
- diag_clear_hsic_tbl();
-#endif
- } else if (temp == NO_LOGGING_MODE && driver->logging_mode
- == MEMORY_DEVICE_MODE) {
- for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
- driver->smd_data[i].in_busy_1 = 0;
- driver->smd_data[i].in_busy_2 = 0;
- /* Poll SMD channels to check for data*/
- if (driver->smd_data[i].ch)
- queue_work(driver->diag_wq,
- &(driver->smd_data[i].
- diag_read_smd_work));
- }
-#ifdef CONFIG_DIAG_SDIO_PIPE
- driver->in_busy_sdio = 0;
- /* Poll SDIO channel to check for data */
- if (driver->sdio_ch)
- queue_work(driver->diag_sdio_wq,
- &(driver->diag_read_sdio_work));
-#endif
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
- diagfwd_connect_bridge(0);
-#endif
- }
-#ifdef CONFIG_DIAG_OVER_USB
- else if (temp == USB_MODE && driver->logging_mode
- == NO_LOGGING_MODE) {
- diagfwd_disconnect();
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
- diagfwd_disconnect_bridge(0);
-#endif
- } else if (temp == NO_LOGGING_MODE && driver->logging_mode
- == USB_MODE) {
- diagfwd_connect();
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
- diagfwd_connect_bridge(0);
-#endif
- } else if (temp == USB_MODE && driver->logging_mode
- == MEMORY_DEVICE_MODE) {
- diagfwd_disconnect();
- for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
- driver->smd_data[i].in_busy_1 = 0;
- driver->smd_data[i].in_busy_2 = 0;
- /* Poll SMD channels to check for data*/
- if (driver->smd_data[i].ch)
- queue_work(driver->diag_wq,
- &(driver->smd_data[i].
- diag_read_smd_work));
- }
-#ifdef CONFIG_DIAG_SDIO_PIPE
- driver->in_busy_sdio = 0;
- /* Poll SDIO channel to check for data */
- if (driver->sdio_ch)
- queue_work(driver->diag_sdio_wq,
- &(driver->diag_read_sdio_work));
-#endif
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
- diagfwd_cancel_hsic();
- diagfwd_connect_bridge(0);
-#endif
- } else if (temp == MEMORY_DEVICE_MODE &&
- driver->logging_mode == USB_MODE) {
- diagfwd_connect();
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
- diag_clear_hsic_tbl();
- diagfwd_cancel_hsic();
- diagfwd_connect_bridge(0);
-#endif
- }
-#endif /* DIAG over USB */
- success = 1;
- } else if (iocmd == DIAG_IOCTL_REMOTE_DEV) {
- uint16_t remote_dev = diag_get_remote_device_mask();
+ result = 1;
+ break;
+ case DIAG_IOCTL_SWITCH_LOGGING:
+ result = diag_switch_logging(ioarg);
+ break;
+ case DIAG_IOCTL_REMOTE_DEV:
+ remote_dev = diag_get_remote_device_mask();
if (copy_to_user((void *)ioarg, &remote_dev, sizeof(uint16_t)))
- success = -EFAULT;
+ result = -EFAULT;
else
- success = 1;
+ result = 1;
+ break;
}
-
- return success;
+ return result;
}
static int diagchar_read(struct file *file, char __user *buf, size_t count,
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 5a67b0c..afbe4be 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2013, 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
@@ -39,6 +39,10 @@
int diag_smd_constructor(struct diag_smd_info *smd_info, int peripheral,
int type);
void diag_smd_destructor(struct diag_smd_info *smd_info);
+int diag_switch_logging(unsigned long);
+int diag_command_reg(unsigned long);
+void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode);
+void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode);
/* State for diag forwarding */
#ifdef CONFIG_DIAG_OVER_USB
int diagfwd_connect(void);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 522136d..2cfafc3 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -59,7 +59,7 @@
/*
* Assigned numbers, used for dynamic minors
*/
-#define DYNAMIC_MINORS 64 /* like dynamic majors */
+#define DYNAMIC_MINORS 96 /* like dynamic majors */
static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS);
#ifdef CONFIG_PROC_FS
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index c113cf1..f5ca5b6 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -1,6 +1,7 @@
#
# Makefile for the kernel tpm device drivers.
#
+
obj-$(CONFIG_TCG_TPM) += tpm.o
ifdef CONFIG_ACPI
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
deleted file mode 100644
index 94bb440..0000000
--- a/drivers/char/tty_io.c
+++ /dev/null
@@ -1,3154 +0,0 @@
-/*
- * linux/drivers/char/tty_io.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
-
-/*
- * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
- * or rs-channels. It also implements echoing, cooked mode etc.
- *
- * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
- *
- * Modified by Theodore Ts'o, 9/14/92, to dynamically allocate the
- * tty_struct and tty_queue structures. Previously there was an array
- * of 256 tty_struct's which was statically allocated, and the
- * tty_queue structures were allocated at boot time. Both are now
- * dynamically allocated only when the tty is open.
- *
- * Also restructured routines so that there is more of a separation
- * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
- * the low-level tty routines (serial.c, pty.c, console.c). This
- * makes for cleaner and more compact code. -TYT, 9/17/92
- *
- * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
- * which can be dynamically activated and de-activated by the line
- * discipline handling modules (like SLIP).
- *
- * NOTE: pay no attention to the line discipline code (yet); its
- * interface is still subject to change in this version...
- * -- TYT, 1/31/92
- *
- * Added functionality to the OPOST tty handling. No delays, but all
- * other bits should be there.
- * -- Nick Holloway <alfie@dcs.warwick.ac.uk>, 27th May 1993.
- *
- * Rewrote canonical mode and added more termios flags.
- * -- julian@uhunix.uhcc.hawaii.edu (J. Cowley), 13Jan94
- *
- * Reorganized FASYNC support so mouse code can share it.
- * -- ctm@ardi.com, 9Sep95
- *
- * New TIOCLINUX variants added.
- * -- mj@k332.feld.cvut.cz, 19-Nov-95
- *
- * Restrict vt switching via ioctl()
- * -- grif@cs.ucr.edu, 5-Dec-95
- *
- * Move console and virtual terminal code to more appropriate files,
- * implement CONFIG_VT and generalize console device interface.
- * -- Marko Kohtala <Marko.Kohtala@hut.fi>, March 97
- *
- * Rewrote tty_init_dev and tty_release_dev to eliminate races.
- * -- Bill Hawes <whawes@star.net>, June 97
- *
- * Added devfs support.
- * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 13-Jan-1998
- *
- * Added support for a Unix98-style ptmx device.
- * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
- *
- * Reduced memory usage for older ARM systems
- * -- Russell King <rmk@arm.linux.org.uk>
- *
- * Move do_SAK() into process context. Less stack use in devfs functions.
- * alloc_tty_struct() always uses kmalloc()
- * -- Andrew Morton <andrewm@uow.edu.eu> 17Mar01
- */
-
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/devpts_fs.h>
-#include <linux/file.h>
-#include <linux/fdtable.h>
-#include <linux/console.h>
-#include <linux/timer.h>
-#include <linux/ctype.h>
-#include <linux/kd.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/smp_lock.h>
-#include <linux/device.h>
-#include <linux/wait.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-
-#include <linux/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/kbd_kern.h>
-#include <linux/vt_kern.h>
-#include <linux/selection.h>
-
-#include <linux/kmod.h>
-#include <linux/nsproxy.h>
-
-#undef TTY_DEBUG_HANGUP
-
-#define TTY_PARANOIA_CHECK 1
-#define CHECK_TTY_COUNT 1
-
-struct ktermios tty_std_termios = { /* for the benefit of tty drivers */
- .c_iflag = ICRNL | IXON,
- .c_oflag = OPOST | ONLCR,
- .c_cflag = B38400 | CS8 | CREAD | HUPCL,
- .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
- ECHOCTL | ECHOKE | IEXTEN,
- .c_cc = INIT_C_CC,
- .c_ispeed = 38400,
- .c_ospeed = 38400
-};
-
-EXPORT_SYMBOL(tty_std_termios);
-
-/* This list gets poked at by procfs and various bits of boot up code. This
- could do with some rationalisation such as pulling the tty proc function
- into this file */
-
-LIST_HEAD(tty_drivers); /* linked list of tty drivers */
-
-/* Mutex to protect creating and releasing a tty. This is shared with
- vt.c for deeply disgusting hack reasons */
-DEFINE_MUTEX(tty_mutex);
-EXPORT_SYMBOL(tty_mutex);
-
-static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
-static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
-ssize_t redirected_tty_write(struct file *, const char __user *,
- size_t, loff_t *);
-static unsigned int tty_poll(struct file *, poll_table *);
-static int tty_open(struct inode *, struct file *);
-long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-#ifdef CONFIG_COMPAT
-static long tty_compat_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg);
-#else
-#define tty_compat_ioctl NULL
-#endif
-static int tty_fasync(int fd, struct file *filp, int on);
-static void release_tty(struct tty_struct *tty, int idx);
-static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
-static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
-
-/**
- * alloc_tty_struct - allocate a tty object
- *
- * Return a new empty tty structure. The data fields have not
- * been initialized in any way but has been zeroed
- *
- * Locking: none
- */
-
-struct tty_struct *alloc_tty_struct(void)
-{
- return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
-}
-
-/**
- * free_tty_struct - free a disused tty
- * @tty: tty struct to free
- *
- * Free the write buffers, tty queue and tty memory itself.
- *
- * Locking: none. Must be called after tty is definitely unused
- */
-
-void free_tty_struct(struct tty_struct *tty)
-{
- kfree(tty->write_buf);
- tty_buffer_free_all(tty);
- kfree(tty);
-}
-
-#define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base)
-
-/**
- * tty_name - return tty naming
- * @tty: tty structure
- * @buf: buffer for output
- *
- * Convert a tty structure into a name. The name reflects the kernel
- * naming policy and if udev is in use may not reflect user space
- *
- * Locking: none
- */
-
-char *tty_name(struct tty_struct *tty, char *buf)
-{
- if (!tty) /* Hmm. NULL pointer. That's fun. */
- strcpy(buf, "NULL tty");
- else
- strcpy(buf, tty->name);
- return buf;
-}
-
-EXPORT_SYMBOL(tty_name);
-
-int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
- const char *routine)
-{
-#ifdef TTY_PARANOIA_CHECK
- if (!tty) {
- printk(KERN_WARNING
- "null TTY for (%d:%d) in %s\n",
- imajor(inode), iminor(inode), routine);
- return 1;
- }
- if (tty->magic != TTY_MAGIC) {
- printk(KERN_WARNING
- "bad magic number for tty struct (%d:%d) in %s\n",
- imajor(inode), iminor(inode), routine);
- return 1;
- }
-#endif
- return 0;
-}
-
-static int check_tty_count(struct tty_struct *tty, const char *routine)
-{
-#ifdef CHECK_TTY_COUNT
- struct list_head *p;
- int count = 0;
-
- file_list_lock();
- list_for_each(p, &tty->tty_files) {
- count++;
- }
- file_list_unlock();
- if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
- tty->driver->subtype == PTY_TYPE_SLAVE &&
- tty->link && tty->link->count)
- count++;
- if (tty->count != count) {
- printk(KERN_WARNING "Warning: dev (%s) tty->count(%d) "
- "!= #fd's(%d) in %s\n",
- tty->name, tty->count, count, routine);
- return count;
- }
-#endif
- return 0;
-}
-
-/**
- * get_tty_driver - find device of a tty
- * @dev_t: device identifier
- * @index: returns the index of the tty
- *
- * This routine returns a tty driver structure, given a device number
- * and also passes back the index number.
- *
- * Locking: caller must hold tty_mutex
- */
-
-static struct tty_driver *get_tty_driver(dev_t device, int *index)
-{
- struct tty_driver *p;
-
- list_for_each_entry(p, &tty_drivers, tty_drivers) {
- dev_t base = MKDEV(p->major, p->minor_start);
- if (device < base || device >= base + p->num)
- continue;
- *index = device - base;
- return tty_driver_kref_get(p);
- }
- return NULL;
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-
-/**
- * tty_find_polling_driver - find device of a polled tty
- * @name: name string to match
- * @line: pointer to resulting tty line nr
- *
- * This routine returns a tty driver structure, given a name
- * and the condition that the tty driver is capable of polled
- * operation.
- */
-struct tty_driver *tty_find_polling_driver(char *name, int *line)
-{
- struct tty_driver *p, *res = NULL;
- int tty_line = 0;
- int len;
- char *str, *stp;
-
- for (str = name; *str; str++)
- if ((*str >= '0' && *str <= '9') || *str == ',')
- break;
- if (!*str)
- return NULL;
-
- len = str - name;
- tty_line = simple_strtoul(str, &str, 10);
-
- mutex_lock(&tty_mutex);
- /* Search through the tty devices to look for a match */
- list_for_each_entry(p, &tty_drivers, tty_drivers) {
- if (strncmp(name, p->name, len) != 0)
- continue;
- stp = str;
- if (*stp == ',')
- stp++;
- if (*stp == '\0')
- stp = NULL;
-
- if (tty_line >= 0 && tty_line <= p->num && p->ops &&
- p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) {
- res = tty_driver_kref_get(p);
- *line = tty_line;
- break;
- }
- }
- mutex_unlock(&tty_mutex);
-
- return res;
-}
-EXPORT_SYMBOL_GPL(tty_find_polling_driver);
-#endif
-
-/**
- * tty_check_change - check for POSIX terminal changes
- * @tty: tty to check
- *
- * If we try to write to, or set the state of, a terminal and we're
- * not in the foreground, send a SIGTTOU. If the signal is blocked or
- * ignored, go ahead and perform the operation. (POSIX 7.2)
- *
- * Locking: ctrl_lock
- */
-
-int tty_check_change(struct tty_struct *tty)
-{
- unsigned long flags;
- int ret = 0;
-
- if (current->signal->tty != tty)
- return 0;
-
- spin_lock_irqsave(&tty->ctrl_lock, flags);
-
- if (!tty->pgrp) {
- printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
- goto out_unlock;
- }
- if (task_pgrp(current) == tty->pgrp)
- goto out_unlock;
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- if (is_ignored(SIGTTOU))
- goto out;
- if (is_current_pgrp_orphaned()) {
- ret = -EIO;
- goto out;
- }
- kill_pgrp(task_pgrp(current), SIGTTOU, 1);
- set_thread_flag(TIF_SIGPENDING);
- ret = -ERESTARTSYS;
-out:
- return ret;
-out_unlock:
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- return ret;
-}
-
-EXPORT_SYMBOL(tty_check_change);
-
-static ssize_t hung_up_tty_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- return 0;
-}
-
-static ssize_t hung_up_tty_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- return -EIO;
-}
-
-/* No kernel lock held - none needed ;) */
-static unsigned int hung_up_tty_poll(struct file *filp, poll_table *wait)
-{
- return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
-}
-
-static long hung_up_tty_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
-}
-
-static long hung_up_tty_compat_ioctl(struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
-}
-
-static const struct file_operations tty_fops = {
- .llseek = no_llseek,
- .read = tty_read,
- .write = tty_write,
- .poll = tty_poll,
- .unlocked_ioctl = tty_ioctl,
- .compat_ioctl = tty_compat_ioctl,
- .open = tty_open,
- .release = tty_release,
- .fasync = tty_fasync,
-};
-
-static const struct file_operations console_fops = {
- .llseek = no_llseek,
- .read = tty_read,
- .write = redirected_tty_write,
- .poll = tty_poll,
- .unlocked_ioctl = tty_ioctl,
- .compat_ioctl = tty_compat_ioctl,
- .open = tty_open,
- .release = tty_release,
- .fasync = tty_fasync,
-};
-
-static const struct file_operations hung_up_tty_fops = {
- .llseek = no_llseek,
- .read = hung_up_tty_read,
- .write = hung_up_tty_write,
- .poll = hung_up_tty_poll,
- .unlocked_ioctl = hung_up_tty_ioctl,
- .compat_ioctl = hung_up_tty_compat_ioctl,
- .release = tty_release,
-};
-
-static DEFINE_SPINLOCK(redirect_lock);
-static struct file *redirect;
-
-/**
- * tty_wakeup - request more data
- * @tty: terminal
- *
- * Internal and external helper for wakeups of tty. This function
- * informs the line discipline if present that the driver is ready
- * to receive more output data.
- */
-
-void tty_wakeup(struct tty_struct *tty)
-{
- struct tty_ldisc *ld;
-
- if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) {
- ld = tty_ldisc_ref(tty);
- if (ld) {
- if (ld->ops->write_wakeup)
- ld->ops->write_wakeup(tty);
- tty_ldisc_deref(ld);
- }
- }
- wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
-}
-
-EXPORT_SYMBOL_GPL(tty_wakeup);
-
-/**
- * do_tty_hangup - actual handler for hangup events
- * @work: tty device
- *
- * This can be called by the "eventd" kernel thread. That is process
- * synchronous but doesn't hold any locks, so we need to make sure we
- * have the appropriate locks for what we're doing.
- *
- * The hangup event clears any pending redirections onto the hung up
- * device. It ensures future writes will error and it does the needed
- * line discipline hangup and signal delivery. The tty object itself
- * remains intact.
- *
- * Locking:
- * BKL
- * redirect lock for undoing redirection
- * file list lock for manipulating list of ttys
- * tty_ldisc_lock from called functions
- * termios_mutex resetting termios data
- * tasklist_lock to walk task list for hangup event
- * ->siglock to protect ->signal/->sighand
- */
-static void do_tty_hangup(struct work_struct *work)
-{
- struct tty_struct *tty =
- container_of(work, struct tty_struct, hangup_work);
- struct file *cons_filp = NULL;
- struct file *filp, *f = NULL;
- struct task_struct *p;
- int closecount = 0, n;
- unsigned long flags;
- int refs = 0;
-
- if (!tty)
- return;
-
-
- spin_lock(&redirect_lock);
- if (redirect && redirect->private_data == tty) {
- f = redirect;
- redirect = NULL;
- }
- spin_unlock(&redirect_lock);
-
- /* inuse_filps is protected by the single kernel lock */
- lock_kernel();
- check_tty_count(tty, "do_tty_hangup");
-
- file_list_lock();
- /* This breaks for file handles being sent over AF_UNIX sockets ? */
- list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
- if (filp->f_op->write == redirected_tty_write)
- cons_filp = filp;
- if (filp->f_op->write != tty_write)
- continue;
- closecount++;
- tty_fasync(-1, filp, 0); /* can't block */
- filp->f_op = &hung_up_tty_fops;
- }
- file_list_unlock();
-
- tty_ldisc_hangup(tty);
-
- read_lock(&tasklist_lock);
- if (tty->session) {
- do_each_pid_task(tty->session, PIDTYPE_SID, p) {
- spin_lock_irq(&p->sighand->siglock);
- if (p->signal->tty == tty) {
- p->signal->tty = NULL;
- /* We defer the dereferences outside fo
- the tasklist lock */
- refs++;
- }
- if (!p->signal->leader) {
- spin_unlock_irq(&p->sighand->siglock);
- continue;
- }
- __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
- __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
- put_pid(p->signal->tty_old_pgrp); /* A noop */
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- if (tty->pgrp)
- p->signal->tty_old_pgrp = get_pid(tty->pgrp);
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- spin_unlock_irq(&p->sighand->siglock);
- } while_each_pid_task(tty->session, PIDTYPE_SID, p);
- }
- read_unlock(&tasklist_lock);
-
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- clear_bit(TTY_THROTTLED, &tty->flags);
- clear_bit(TTY_PUSH, &tty->flags);
- clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- put_pid(tty->session);
- put_pid(tty->pgrp);
- tty->session = NULL;
- tty->pgrp = NULL;
- tty->ctrl_status = 0;
- set_bit(TTY_HUPPED, &tty->flags);
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-
- /* Account for the p->signal references we killed */
- while (refs--)
- tty_kref_put(tty);
-
- /*
- * If one of the devices matches a console pointer, we
- * cannot just call hangup() because that will cause
- * tty->count and state->count to go out of sync.
- * So we just call close() the right number of times.
- */
- if (cons_filp) {
- if (tty->ops->close)
- for (n = 0; n < closecount; n++)
- tty->ops->close(tty, cons_filp);
- } else if (tty->ops->hangup)
- (tty->ops->hangup)(tty);
- /*
- * We don't want to have driver/ldisc interactions beyond
- * the ones we did here. The driver layer expects no
- * calls after ->hangup() from the ldisc side. However we
- * can't yet guarantee all that.
- */
- set_bit(TTY_HUPPED, &tty->flags);
- tty_ldisc_enable(tty);
- unlock_kernel();
- if (f)
- fput(f);
-}
-
-/**
- * tty_hangup - trigger a hangup event
- * @tty: tty to hangup
- *
- * A carrier loss (virtual or otherwise) has occurred on this like
- * schedule a hangup sequence to run after this event.
- */
-
-void tty_hangup(struct tty_struct *tty)
-{
-#ifdef TTY_DEBUG_HANGUP
- char buf[64];
- printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
-#endif
- schedule_work(&tty->hangup_work);
-}
-
-EXPORT_SYMBOL(tty_hangup);
-
-/**
- * tty_vhangup - process vhangup
- * @tty: tty to hangup
- *
- * The user has asked via system call for the terminal to be hung up.
- * We do this synchronously so that when the syscall returns the process
- * is complete. That guarantee is necessary for security reasons.
- */
-
-void tty_vhangup(struct tty_struct *tty)
-{
-#ifdef TTY_DEBUG_HANGUP
- char buf[64];
-
- printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
-#endif
- do_tty_hangup(&tty->hangup_work);
-}
-
-EXPORT_SYMBOL(tty_vhangup);
-
-/**
- * tty_vhangup_self - process vhangup for own ctty
- *
- * Perform a vhangup on the current controlling tty
- */
-
-void tty_vhangup_self(void)
-{
- struct tty_struct *tty;
-
- tty = get_current_tty();
- if (tty) {
- tty_vhangup(tty);
- tty_kref_put(tty);
- }
-}
-
-/**
- * tty_hung_up_p - was tty hung up
- * @filp: file pointer of tty
- *
- * Return true if the tty has been subject to a vhangup or a carrier
- * loss
- */
-
-int tty_hung_up_p(struct file *filp)
-{
- return (filp->f_op == &hung_up_tty_fops);
-}
-
-EXPORT_SYMBOL(tty_hung_up_p);
-
-static void session_clear_tty(struct pid *session)
-{
- struct task_struct *p;
- do_each_pid_task(session, PIDTYPE_SID, p) {
- proc_clear_tty(p);
- } while_each_pid_task(session, PIDTYPE_SID, p);
-}
-
-/**
- * disassociate_ctty - disconnect controlling tty
- * @on_exit: true if exiting so need to "hang up" the session
- *
- * This function is typically called only by the session leader, when
- * it wants to disassociate itself from its controlling tty.
- *
- * It performs the following functions:
- * (1) Sends a SIGHUP and SIGCONT to the foreground process group
- * (2) Clears the tty from being controlling the session
- * (3) Clears the controlling tty for all processes in the
- * session group.
- *
- * The argument on_exit is set to 1 if called when a process is
- * exiting; it is 0 if called by the ioctl TIOCNOTTY.
- *
- * Locking:
- * BKL is taken for hysterical raisins
- * tty_mutex is taken to protect tty
- * ->siglock is taken to protect ->signal/->sighand
- * tasklist_lock is taken to walk process list for sessions
- * ->siglock is taken to protect ->signal/->sighand
- */
-
-void disassociate_ctty(int on_exit)
-{
- struct tty_struct *tty;
- struct pid *tty_pgrp = NULL;
-
- if (!current->signal->leader)
- return;
-
- tty = get_current_tty();
- if (tty) {
- tty_pgrp = get_pid(tty->pgrp);
- lock_kernel();
- if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
- tty_vhangup(tty);
- unlock_kernel();
- tty_kref_put(tty);
- } else if (on_exit) {
- struct pid *old_pgrp;
- spin_lock_irq(¤t->sighand->siglock);
- old_pgrp = current->signal->tty_old_pgrp;
- current->signal->tty_old_pgrp = NULL;
- spin_unlock_irq(¤t->sighand->siglock);
- if (old_pgrp) {
- kill_pgrp(old_pgrp, SIGHUP, on_exit);
- kill_pgrp(old_pgrp, SIGCONT, on_exit);
- put_pid(old_pgrp);
- }
- return;
- }
- if (tty_pgrp) {
- kill_pgrp(tty_pgrp, SIGHUP, on_exit);
- if (!on_exit)
- kill_pgrp(tty_pgrp, SIGCONT, on_exit);
- put_pid(tty_pgrp);
- }
-
- spin_lock_irq(¤t->sighand->siglock);
- put_pid(current->signal->tty_old_pgrp);
- current->signal->tty_old_pgrp = NULL;
- spin_unlock_irq(¤t->sighand->siglock);
-
- tty = get_current_tty();
- if (tty) {
- unsigned long flags;
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- put_pid(tty->session);
- put_pid(tty->pgrp);
- tty->session = NULL;
- tty->pgrp = NULL;
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- tty_kref_put(tty);
- } else {
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
- " = NULL", tty);
-#endif
- }
-
- /* Now clear signal->tty under the lock */
- read_lock(&tasklist_lock);
- session_clear_tty(task_session(current));
- read_unlock(&tasklist_lock);
-}
-
-/**
- *
- * no_tty - Ensure the current process does not have a controlling tty
- */
-void no_tty(void)
-{
- struct task_struct *tsk = current;
- lock_kernel();
- disassociate_ctty(0);
- unlock_kernel();
- proc_clear_tty(tsk);
-}
-
-
-/**
- * stop_tty - propagate flow control
- * @tty: tty to stop
- *
- * Perform flow control to the driver. For PTY/TTY pairs we
- * must also propagate the TIOCKPKT status. May be called
- * on an already stopped device and will not re-call the driver
- * method.
- *
- * This functionality is used by both the line disciplines for
- * halting incoming flow and by the driver. It may therefore be
- * called from any context, may be under the tty atomic_write_lock
- * but not always.
- *
- * Locking:
- * Uses the tty control lock internally
- */
-
-void stop_tty(struct tty_struct *tty)
-{
- unsigned long flags;
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- if (tty->stopped) {
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- return;
- }
- tty->stopped = 1;
- if (tty->link && tty->link->packet) {
- tty->ctrl_status &= ~TIOCPKT_START;
- tty->ctrl_status |= TIOCPKT_STOP;
- wake_up_interruptible_poll(&tty->link->read_wait, POLLIN);
- }
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- if (tty->ops->stop)
- (tty->ops->stop)(tty);
-}
-
-EXPORT_SYMBOL(stop_tty);
-
-/**
- * start_tty - propagate flow control
- * @tty: tty to start
- *
- * Start a tty that has been stopped if at all possible. Perform
- * any necessary wakeups and propagate the TIOCPKT status. If this
- * is the tty was previous stopped and is being started then the
- * driver start method is invoked and the line discipline woken.
- *
- * Locking:
- * ctrl_lock
- */
-
-void start_tty(struct tty_struct *tty)
-{
- unsigned long flags;
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- if (!tty->stopped || tty->flow_stopped) {
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- return;
- }
- tty->stopped = 0;
- if (tty->link && tty->link->packet) {
- tty->ctrl_status &= ~TIOCPKT_STOP;
- tty->ctrl_status |= TIOCPKT_START;
- wake_up_interruptible_poll(&tty->link->read_wait, POLLIN);
- }
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- if (tty->ops->start)
- (tty->ops->start)(tty);
- /* If we have a running line discipline it may need kicking */
- tty_wakeup(tty);
-}
-
-EXPORT_SYMBOL(start_tty);
-
-/**
- * tty_read - read method for tty device files
- * @file: pointer to tty file
- * @buf: user buffer
- * @count: size of user buffer
- * @ppos: unused
- *
- * Perform the read system call function on this terminal device. Checks
- * for hung up devices before calling the line discipline method.
- *
- * Locking:
- * Locks the line discipline internally while needed. Multiple
- * read calls may be outstanding in parallel.
- */
-
-static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- int i;
- struct tty_struct *tty;
- struct inode *inode;
- struct tty_ldisc *ld;
-
- tty = (struct tty_struct *)file->private_data;
- inode = file->f_path.dentry->d_inode;
- if (tty_paranoia_check(tty, inode, "tty_read"))
- return -EIO;
- if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
- return -EIO;
-
- /* We want to wait for the line discipline to sort out in this
- situation */
- ld = tty_ldisc_ref_wait(tty);
- if (ld->ops->read)
- i = (ld->ops->read)(tty, file, buf, count);
- else
- i = -EIO;
- tty_ldisc_deref(ld);
- if (i > 0)
- inode->i_atime = current_fs_time(inode->i_sb);
- return i;
-}
-
-void tty_write_unlock(struct tty_struct *tty)
-{
- mutex_unlock(&tty->atomic_write_lock);
- wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
-}
-
-int tty_write_lock(struct tty_struct *tty, int ndelay)
-{
- if (!mutex_trylock(&tty->atomic_write_lock)) {
- if (ndelay)
- return -EAGAIN;
- if (mutex_lock_interruptible(&tty->atomic_write_lock))
- return -ERESTARTSYS;
- }
- return 0;
-}
-
-/*
- * Split writes up in sane blocksizes to avoid
- * denial-of-service type attacks
- */
-static inline ssize_t do_tty_write(
- ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t),
- struct tty_struct *tty,
- struct file *file,
- const char __user *buf,
- size_t count)
-{
- ssize_t ret, written = 0;
- unsigned int chunk;
-
- ret = tty_write_lock(tty, file->f_flags & O_NDELAY);
- if (ret < 0)
- return ret;
-
- /*
- * We chunk up writes into a temporary buffer. This
- * simplifies low-level drivers immensely, since they
- * don't have locking issues and user mode accesses.
- *
- * But if TTY_NO_WRITE_SPLIT is set, we should use a
- * big chunk-size..
- *
- * The default chunk-size is 2kB, because the NTTY
- * layer has problems with bigger chunks. It will
- * claim to be able to handle more characters than
- * it actually does.
- *
- * FIXME: This can probably go away now except that 64K chunks
- * are too likely to fail unless switched to vmalloc...
- */
- chunk = 2048;
- if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags))
- chunk = 65536;
- if (count < chunk)
- chunk = count;
-
- /* write_buf/write_cnt is protected by the atomic_write_lock mutex */
- if (tty->write_cnt < chunk) {
- unsigned char *buf_chunk;
-
- if (chunk < 1024)
- chunk = 1024;
-
- buf_chunk = kmalloc(chunk, GFP_KERNEL);
- if (!buf_chunk) {
- ret = -ENOMEM;
- goto out;
- }
- kfree(tty->write_buf);
- tty->write_cnt = chunk;
- tty->write_buf = buf_chunk;
- }
-
- /* Do the write .. */
- for (;;) {
- size_t size = count;
- if (size > chunk)
- size = chunk;
- ret = -EFAULT;
- if (copy_from_user(tty->write_buf, buf, size))
- break;
- ret = write(tty, file, tty->write_buf, size);
- if (ret <= 0)
- break;
- written += ret;
- buf += ret;
- count -= ret;
- if (!count)
- break;
- ret = -ERESTARTSYS;
- if (signal_pending(current))
- break;
- cond_resched();
- }
- if (written) {
- struct inode *inode = file->f_path.dentry->d_inode;
- inode->i_mtime = current_fs_time(inode->i_sb);
- ret = written;
- }
-out:
- tty_write_unlock(tty);
- return ret;
-}
-
-/**
- * tty_write_message - write a message to a certain tty, not just the console.
- * @tty: the destination tty_struct
- * @msg: the message to write
- *
- * This is used for messages that need to be redirected to a specific tty.
- * We don't put it into the syslog queue right now maybe in the future if
- * really needed.
- *
- * We must still hold the BKL and test the CLOSING flag for the moment.
- */
-
-void tty_write_message(struct tty_struct *tty, char *msg)
-{
- if (tty) {
- mutex_lock(&tty->atomic_write_lock);
- lock_kernel();
- if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
- unlock_kernel();
- tty->ops->write(tty, msg, strlen(msg));
- } else
- unlock_kernel();
- tty_write_unlock(tty);
- }
- return;
-}
-
-
-/**
- * tty_write - write method for tty device file
- * @file: tty file pointer
- * @buf: user data to write
- * @count: bytes to write
- * @ppos: unused
- *
- * Write data to a tty device via the line discipline.
- *
- * Locking:
- * Locks the line discipline as required
- * Writes to the tty driver are serialized by the atomic_write_lock
- * and are then processed in chunks to the device. The line discipline
- * write method will not be invoked in parallel for each device.
- */
-
-static ssize_t tty_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct tty_struct *tty;
- struct inode *inode = file->f_path.dentry->d_inode;
- ssize_t ret;
- struct tty_ldisc *ld;
-
- tty = (struct tty_struct *)file->private_data;
- if (tty_paranoia_check(tty, inode, "tty_write"))
- return -EIO;
- if (!tty || !tty->ops->write ||
- (test_bit(TTY_IO_ERROR, &tty->flags)))
- return -EIO;
- /* Short term debug to catch buggy drivers */
- if (tty->ops->write_room == NULL)
- printk(KERN_ERR "tty driver %s lacks a write_room method.\n",
- tty->driver->name);
- ld = tty_ldisc_ref_wait(tty);
- if (!ld->ops->write)
- ret = -EIO;
- else
- ret = do_tty_write(ld->ops->write, tty, file, buf, count);
- tty_ldisc_deref(ld);
- return ret;
-}
-
-ssize_t redirected_tty_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct file *p = NULL;
-
- spin_lock(&redirect_lock);
- if (redirect) {
- get_file(redirect);
- p = redirect;
- }
- spin_unlock(&redirect_lock);
-
- if (p) {
- ssize_t res;
- res = vfs_write(p, buf, count, &p->f_pos);
- fput(p);
- return res;
- }
- return tty_write(file, buf, count, ppos);
-}
-
-static char ptychar[] = "pqrstuvwxyzabcde";
-
-/**
- * pty_line_name - generate name for a pty
- * @driver: the tty driver in use
- * @index: the minor number
- * @p: output buffer of at least 6 bytes
- *
- * Generate a name from a driver reference and write it to the output
- * buffer.
- *
- * Locking: None
- */
-static void pty_line_name(struct tty_driver *driver, int index, char *p)
-{
- int i = index + driver->name_base;
- /* ->name is initialized to "ttyp", but "tty" is expected */
- sprintf(p, "%s%c%x",
- driver->subtype == PTY_TYPE_SLAVE ? "tty" : driver->name,
- ptychar[i >> 4 & 0xf], i & 0xf);
-}
-
-/**
- * tty_line_name - generate name for a tty
- * @driver: the tty driver in use
- * @index: the minor number
- * @p: output buffer of at least 7 bytes
- *
- * Generate a name from a driver reference and write it to the output
- * buffer.
- *
- * Locking: None
- */
-static void tty_line_name(struct tty_driver *driver, int index, char *p)
-{
- sprintf(p, "%s%d", driver->name, index + driver->name_base);
-}
-
-/**
- * tty_driver_lookup_tty() - find an existing tty, if any
- * @driver: the driver for the tty
- * @idx: the minor number
- *
- * Return the tty, if found or ERR_PTR() otherwise.
- *
- * Locking: tty_mutex must be held. If tty is found, the mutex must
- * be held until the 'fast-open' is also done. Will change once we
- * have refcounting in the driver and per driver locking
- */
-static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
- struct inode *inode, int idx)
-{
- struct tty_struct *tty;
-
- if (driver->ops->lookup)
- return driver->ops->lookup(driver, inode, idx);
-
- tty = driver->ttys[idx];
- return tty;
-}
-
-/**
- * tty_init_termios - helper for termios setup
- * @tty: the tty to set up
- *
- * Initialise the termios structures for this tty. Thus runs under
- * the tty_mutex currently so we can be relaxed about ordering.
- */
-
-int tty_init_termios(struct tty_struct *tty)
-{
- struct ktermios *tp;
- int idx = tty->index;
-
- tp = tty->driver->termios[idx];
- if (tp == NULL) {
- tp = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
- if (tp == NULL)
- return -ENOMEM;
- memcpy(tp, &tty->driver->init_termios,
- sizeof(struct ktermios));
- tty->driver->termios[idx] = tp;
- }
- tty->termios = tp;
- tty->termios_locked = tp + 1;
-
- /* Compatibility until drivers always set this */
- tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
- tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
- return 0;
-}
-EXPORT_SYMBOL_GPL(tty_init_termios);
-
-/**
- * tty_driver_install_tty() - install a tty entry in the driver
- * @driver: the driver for the tty
- * @tty: the tty
- *
- * Install a tty object into the driver tables. The tty->index field
- * will be set by the time this is called. This method is responsible
- * for ensuring any need additional structures are allocated and
- * configured.
- *
- * Locking: tty_mutex for now
- */
-static int tty_driver_install_tty(struct tty_driver *driver,
- struct tty_struct *tty)
-{
- int idx = tty->index;
- int ret;
-
- if (driver->ops->install) {
- lock_kernel();
- ret = driver->ops->install(driver, tty);
- unlock_kernel();
- return ret;
- }
-
- if (tty_init_termios(tty) == 0) {
- lock_kernel();
- tty_driver_kref_get(driver);
- tty->count++;
- driver->ttys[idx] = tty;
- unlock_kernel();
- return 0;
- }
- return -ENOMEM;
-}
-
-/**
- * tty_driver_remove_tty() - remove a tty from the driver tables
- * @driver: the driver for the tty
- * @idx: the minor number
- *
- * Remvoe a tty object from the driver tables. The tty->index field
- * will be set by the time this is called.
- *
- * Locking: tty_mutex for now
- */
-static void tty_driver_remove_tty(struct tty_driver *driver,
- struct tty_struct *tty)
-{
- if (driver->ops->remove)
- driver->ops->remove(driver, tty);
- else
- driver->ttys[tty->index] = NULL;
-}
-
-/*
- * tty_reopen() - fast re-open of an open tty
- * @tty - the tty to open
- *
- * Return 0 on success, -errno on error.
- *
- * Locking: tty_mutex must be held from the time the tty was found
- * till this open completes.
- */
-static int tty_reopen(struct tty_struct *tty)
-{
- struct tty_driver *driver = tty->driver;
-
- if (test_bit(TTY_CLOSING, &tty->flags))
- return -EIO;
-
- if (driver->type == TTY_DRIVER_TYPE_PTY &&
- driver->subtype == PTY_TYPE_MASTER) {
- /*
- * special case for PTY masters: only one open permitted,
- * and the slave side open count is incremented as well.
- */
- if (tty->count)
- return -EIO;
-
- tty->link->count++;
- }
- tty->count++;
- tty->driver = driver; /* N.B. why do this every time?? */
-
- mutex_lock(&tty->ldisc_mutex);
- WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
- mutex_unlock(&tty->ldisc_mutex);
-
- return 0;
-}
-
-/**
- * tty_init_dev - initialise a tty device
- * @driver: tty driver we are opening a device on
- * @idx: device index
- * @ret_tty: returned tty structure
- * @first_ok: ok to open a new device (used by ptmx)
- *
- * Prepare a tty device. This may not be a "new" clean device but
- * could also be an active device. The pty drivers require special
- * handling because of this.
- *
- * Locking:
- * The function is called under the tty_mutex, which
- * protects us from the tty struct or driver itself going away.
- *
- * On exit the tty device has the line discipline attached and
- * a reference count of 1. If a pair was created for pty/tty use
- * and the other was a pty master then it too has a reference count of 1.
- *
- * WSH 06/09/97: Rewritten to remove races and properly clean up after a
- * failed open. The new code protects the open with a mutex, so it's
- * really quite straightforward. The mutex locking can probably be
- * relaxed for the (most common) case of reopening a tty.
- */
-
-struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
- int first_ok)
-{
- struct tty_struct *tty;
- int retval;
-
- lock_kernel();
- /* Check if pty master is being opened multiple times */
- if (driver->subtype == PTY_TYPE_MASTER &&
- (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) {
- unlock_kernel();
- return ERR_PTR(-EIO);
- }
- unlock_kernel();
-
- /*
- * First time open is complex, especially for PTY devices.
- * This code guarantees that either everything succeeds and the
- * TTY is ready for operation, or else the table slots are vacated
- * and the allocated memory released. (Except that the termios
- * and locked termios may be retained.)
- */
-
- if (!try_module_get(driver->owner))
- return ERR_PTR(-ENODEV);
-
- tty = alloc_tty_struct();
- if (!tty)
- goto fail_no_mem;
- initialize_tty_struct(tty, driver, idx);
-
- retval = tty_driver_install_tty(driver, tty);
- if (retval < 0) {
- free_tty_struct(tty);
- module_put(driver->owner);
- return ERR_PTR(retval);
- }
-
- /*
- * Structures all installed ... call the ldisc open routines.
- * If we fail here just call release_tty to clean up. No need
- * to decrement the use counts, as release_tty doesn't care.
- */
- retval = tty_ldisc_setup(tty, tty->link);
- if (retval)
- goto release_mem_out;
- return tty;
-
-fail_no_mem:
- module_put(driver->owner);
- return ERR_PTR(-ENOMEM);
-
- /* call the tty release_tty routine to clean out this slot */
-release_mem_out:
- if (printk_ratelimit())
- printk(KERN_INFO "tty_init_dev: ldisc open failed, "
- "clearing slot %d\n", idx);
- lock_kernel();
- release_tty(tty, idx);
- unlock_kernel();
- return ERR_PTR(retval);
-}
-
-void tty_free_termios(struct tty_struct *tty)
-{
- struct ktermios *tp;
- int idx = tty->index;
- /* Kill this flag and push into drivers for locking etc */
- if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
- /* FIXME: Locking on ->termios array */
- tp = tty->termios;
- tty->driver->termios[idx] = NULL;
- kfree(tp);
- }
-}
-EXPORT_SYMBOL(tty_free_termios);
-
-void tty_shutdown(struct tty_struct *tty)
-{
- tty_driver_remove_tty(tty->driver, tty);
- tty_free_termios(tty);
-}
-EXPORT_SYMBOL(tty_shutdown);
-
-/**
- * release_one_tty - release tty structure memory
- * @kref: kref of tty we are obliterating
- *
- * Releases memory associated with a tty structure, and clears out the
- * driver table slots. This function is called when a device is no longer
- * in use. It also gets called when setup of a device fails.
- *
- * Locking:
- * tty_mutex - sometimes only
- * takes the file list lock internally when working on the list
- * of ttys that the driver keeps.
- *
- * This method gets called from a work queue so that the driver private
- * cleanup ops can sleep (needed for USB at least)
- */
-static void release_one_tty(struct work_struct *work)
-{
- struct tty_struct *tty =
- container_of(work, struct tty_struct, hangup_work);
- struct tty_driver *driver = tty->driver;
-
- if (tty->ops->cleanup)
- tty->ops->cleanup(tty);
-
- tty->magic = 0;
- tty_driver_kref_put(driver);
- module_put(driver->owner);
-
- file_list_lock();
- list_del_init(&tty->tty_files);
- file_list_unlock();
-
- put_pid(tty->pgrp);
- put_pid(tty->session);
- free_tty_struct(tty);
-}
-
-static void queue_release_one_tty(struct kref *kref)
-{
- struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
-
- if (tty->ops->shutdown)
- tty->ops->shutdown(tty);
- else
- tty_shutdown(tty);
-
- /* The hangup queue is now free so we can reuse it rather than
- waste a chunk of memory for each port */
- INIT_WORK(&tty->hangup_work, release_one_tty);
- schedule_work(&tty->hangup_work);
-}
-
-/**
- * tty_kref_put - release a tty kref
- * @tty: tty device
- *
- * Release a reference to a tty device and if need be let the kref
- * layer destruct the object for us
- */
-
-void tty_kref_put(struct tty_struct *tty)
-{
- if (tty)
- kref_put(&tty->kref, queue_release_one_tty);
-}
-EXPORT_SYMBOL(tty_kref_put);
-
-/**
- * release_tty - release tty structure memory
- *
- * Release both @tty and a possible linked partner (think pty pair),
- * and decrement the refcount of the backing module.
- *
- * Locking:
- * tty_mutex - sometimes only
- * takes the file list lock internally when working on the list
- * of ttys that the driver keeps.
- * FIXME: should we require tty_mutex is held here ??
- *
- */
-static void release_tty(struct tty_struct *tty, int idx)
-{
- /* This should always be true but check for the moment */
- WARN_ON(tty->index != idx);
-
- if (tty->link)
- tty_kref_put(tty->link);
- tty_kref_put(tty);
-}
-
-/**
- * tty_release - vfs callback for close
- * @inode: inode of tty
- * @filp: file pointer for handle to tty
- *
- * Called the last time each file handle is closed that references
- * this tty. There may however be several such references.
- *
- * Locking:
- * Takes bkl. See tty_release_dev
- *
- * Even releasing the tty structures is a tricky business.. We have
- * to be very careful that the structures are all released at the
- * same time, as interrupts might otherwise get the wrong pointers.
- *
- * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
- * lead to double frees or releasing memory still in use.
- */
-
-int tty_release(struct inode *inode, struct file *filp)
-{
- struct tty_struct *tty, *o_tty;
- int pty_master, tty_closing, o_tty_closing, do_sleep;
- int devpts;
- int idx;
- char buf[64];
-
- tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, inode, "tty_release_dev"))
- return 0;
-
- lock_kernel();
- check_tty_count(tty, "tty_release_dev");
-
- tty_fasync(-1, filp, 0);
-
- idx = tty->index;
- pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
- tty->driver->subtype == PTY_TYPE_MASTER);
- devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
- o_tty = tty->link;
-
-#ifdef TTY_PARANOIA_CHECK
- if (idx < 0 || idx >= tty->driver->num) {
- printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
- "free (%s)\n", tty->name);
- unlock_kernel();
- return 0;
- }
- if (!devpts) {
- if (tty != tty->driver->ttys[idx]) {
- unlock_kernel();
- printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
- "for (%s)\n", idx, tty->name);
- return 0;
- }
- if (tty->termios != tty->driver->termios[idx]) {
- unlock_kernel();
- printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
- "for (%s)\n",
- idx, tty->name);
- return 0;
- }
- }
-#endif
-
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "tty_release_dev of %s (tty count=%d)...",
- tty_name(tty, buf), tty->count);
-#endif
-
-#ifdef TTY_PARANOIA_CHECK
- if (tty->driver->other &&
- !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
- if (o_tty != tty->driver->other->ttys[idx]) {
- unlock_kernel();
- printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
- "not o_tty for (%s)\n",
- idx, tty->name);
- return 0 ;
- }
- if (o_tty->termios != tty->driver->other->termios[idx]) {
- unlock_kernel();
- printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
- "not o_termios for (%s)\n",
- idx, tty->name);
- return 0;
- }
- if (o_tty->link != tty) {
- unlock_kernel();
- printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
- return 0;
- }
- }
-#endif
- if (tty->ops->close)
- tty->ops->close(tty, filp);
-
- unlock_kernel();
- /*
- * Sanity check: if tty->count is going to zero, there shouldn't be
- * any waiters on tty->read_wait or tty->write_wait. We test the
- * wait queues and kick everyone out _before_ actually starting to
- * close. This ensures that we won't block while releasing the tty
- * structure.
- *
- * The test for the o_tty closing is necessary, since the master and
- * slave sides may close in any order. If the slave side closes out
- * first, its count will be one, since the master side holds an open.
- * Thus this test wouldn't be triggered at the time the slave closes,
- * so we do it now.
- *
- * Note that it's possible for the tty to be opened again while we're
- * flushing out waiters. By recalculating the closing flags before
- * each iteration we avoid any problems.
- */
- while (1) {
- /* Guard against races with tty->count changes elsewhere and
- opens on /dev/tty */
-
- mutex_lock(&tty_mutex);
- lock_kernel();
- tty_closing = tty->count <= 1;
- o_tty_closing = o_tty &&
- (o_tty->count <= (pty_master ? 1 : 0));
- do_sleep = 0;
-
- if (tty_closing) {
- if (waitqueue_active(&tty->read_wait)) {
- wake_up_poll(&tty->read_wait, POLLIN);
- do_sleep++;
- }
- if (waitqueue_active(&tty->write_wait)) {
- wake_up_poll(&tty->write_wait, POLLOUT);
- do_sleep++;
- }
- }
- if (o_tty_closing) {
- if (waitqueue_active(&o_tty->read_wait)) {
- wake_up_poll(&o_tty->read_wait, POLLIN);
- do_sleep++;
- }
- if (waitqueue_active(&o_tty->write_wait)) {
- wake_up_poll(&o_tty->write_wait, POLLOUT);
- do_sleep++;
- }
- }
- if (!do_sleep)
- break;
-
- printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue "
- "active!\n", tty_name(tty, buf));
- unlock_kernel();
- mutex_unlock(&tty_mutex);
- schedule();
- }
-
- /*
- * The closing flags are now consistent with the open counts on
- * both sides, and we've completed the last operation that could
- * block, so it's safe to proceed with closing.
- */
- if (pty_master) {
- if (--o_tty->count < 0) {
- printk(KERN_WARNING "tty_release_dev: bad pty slave count "
- "(%d) for %s\n",
- o_tty->count, tty_name(o_tty, buf));
- o_tty->count = 0;
- }
- }
- if (--tty->count < 0) {
- printk(KERN_WARNING "tty_release_dev: bad tty->count (%d) for %s\n",
- tty->count, tty_name(tty, buf));
- tty->count = 0;
- }
-
- /*
- * We've decremented tty->count, so we need to remove this file
- * descriptor off the tty->tty_files list; this serves two
- * purposes:
- * - check_tty_count sees the correct number of file descriptors
- * associated with this tty.
- * - do_tty_hangup no longer sees this file descriptor as
- * something that needs to be handled for hangups.
- */
- file_kill(filp);
- filp->private_data = NULL;
-
- /*
- * Perform some housekeeping before deciding whether to return.
- *
- * Set the TTY_CLOSING flag if this was the last open. In the
- * case of a pty we may have to wait around for the other side
- * to close, and TTY_CLOSING makes sure we can't be reopened.
- */
- if (tty_closing)
- set_bit(TTY_CLOSING, &tty->flags);
- if (o_tty_closing)
- set_bit(TTY_CLOSING, &o_tty->flags);
-
- /*
- * If _either_ side is closing, make sure there aren't any
- * processes that still think tty or o_tty is their controlling
- * tty.
- */
- if (tty_closing || o_tty_closing) {
- read_lock(&tasklist_lock);
- session_clear_tty(tty->session);
- if (o_tty)
- session_clear_tty(o_tty->session);
- read_unlock(&tasklist_lock);
- }
-
- mutex_unlock(&tty_mutex);
-
- /* check whether both sides are closing ... */
- if (!tty_closing || (o_tty && !o_tty_closing)) {
- unlock_kernel();
- return 0;
- }
-
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "freeing tty structure...");
-#endif
- /*
- * Ask the line discipline code to release its structures
- */
- tty_ldisc_release(tty, o_tty);
- /*
- * The release_tty function takes care of the details of clearing
- * the slots and preserving the termios structure.
- */
- release_tty(tty, idx);
-
- /* Make this pty number available for reallocation */
- if (devpts)
- devpts_kill_index(inode, idx);
- unlock_kernel();
- return 0;
-}
-
-/**
- * tty_open - open a tty device
- * @inode: inode of device file
- * @filp: file pointer to tty
- *
- * tty_open and tty_release keep up the tty count that contains the
- * number of opens done on a tty. We cannot use the inode-count, as
- * different inodes might point to the same tty.
- *
- * Open-counting is needed for pty masters, as well as for keeping
- * track of serial lines: DTR is dropped when the last close happens.
- * (This is not done solely through tty->count, now. - Ted 1/27/92)
- *
- * The termios state of a pty is reset on first open so that
- * settings don't persist across reuse.
- *
- * Locking: tty_mutex protects tty, get_tty_driver and tty_init_dev work.
- * tty->count should protect the rest.
- * ->siglock protects ->signal/->sighand
- */
-
-static int tty_open(struct inode *inode, struct file *filp)
-{
- struct tty_struct *tty = NULL;
- int noctty, retval;
- struct tty_driver *driver;
- int index;
- dev_t device = inode->i_rdev;
- unsigned saved_flags = filp->f_flags;
-
- nonseekable_open(inode, filp);
-
-retry_open:
- noctty = filp->f_flags & O_NOCTTY;
- index = -1;
- retval = 0;
-
- mutex_lock(&tty_mutex);
- lock_kernel();
-
- if (device == MKDEV(TTYAUX_MAJOR, 0)) {
- tty = get_current_tty();
- if (!tty) {
- unlock_kernel();
- mutex_unlock(&tty_mutex);
- return -ENXIO;
- }
- driver = tty_driver_kref_get(tty->driver);
- index = tty->index;
- filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
- /* noctty = 1; */
- /* FIXME: Should we take a driver reference ? */
- tty_kref_put(tty);
- goto got_driver;
- }
-#ifdef CONFIG_VT
- if (device == MKDEV(TTY_MAJOR, 0)) {
- extern struct tty_driver *console_driver;
- driver = tty_driver_kref_get(console_driver);
- index = fg_console;
- noctty = 1;
- goto got_driver;
- }
-#endif
- if (device == MKDEV(TTYAUX_MAJOR, 1)) {
- struct tty_driver *console_driver = console_device(&index);
- if (console_driver) {
- driver = tty_driver_kref_get(console_driver);
- if (driver) {
- /* Don't let /dev/console block */
- filp->f_flags |= O_NONBLOCK;
- noctty = 1;
- goto got_driver;
- }
- }
- unlock_kernel();
- mutex_unlock(&tty_mutex);
- return -ENODEV;
- }
-
- driver = get_tty_driver(device, &index);
- if (!driver) {
- unlock_kernel();
- mutex_unlock(&tty_mutex);
- return -ENODEV;
- }
-got_driver:
- if (!tty) {
- /* check whether we're reopening an existing tty */
- tty = tty_driver_lookup_tty(driver, inode, index);
-
- if (IS_ERR(tty)) {
- unlock_kernel();
- mutex_unlock(&tty_mutex);
- return PTR_ERR(tty);
- }
- }
-
- if (tty) {
- retval = tty_reopen(tty);
- if (retval)
- tty = ERR_PTR(retval);
- } else
- tty = tty_init_dev(driver, index, 0);
-
- mutex_unlock(&tty_mutex);
- tty_driver_kref_put(driver);
- if (IS_ERR(tty)) {
- unlock_kernel();
- return PTR_ERR(tty);
- }
-
- filp->private_data = tty;
- file_move(filp, &tty->tty_files);
- check_tty_count(tty, "tty_open");
- if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
- tty->driver->subtype == PTY_TYPE_MASTER)
- noctty = 1;
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "opening %s...", tty->name);
-#endif
- if (!retval) {
- if (tty->ops->open)
- retval = tty->ops->open(tty, filp);
- else
- retval = -ENODEV;
- }
- filp->f_flags = saved_flags;
-
- if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) &&
- !capable(CAP_SYS_ADMIN))
- retval = -EBUSY;
-
- if (retval) {
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "error %d in opening %s...", retval,
- tty->name);
-#endif
- tty_release(inode, filp);
- if (retval != -ERESTARTSYS) {
- unlock_kernel();
- return retval;
- }
- if (signal_pending(current)) {
- unlock_kernel();
- return retval;
- }
- schedule();
- /*
- * Need to reset f_op in case a hangup happened.
- */
- if (filp->f_op == &hung_up_tty_fops)
- filp->f_op = &tty_fops;
- unlock_kernel();
- goto retry_open;
- }
- unlock_kernel();
-
-
- mutex_lock(&tty_mutex);
- lock_kernel();
- spin_lock_irq(¤t->sighand->siglock);
- if (!noctty &&
- current->signal->leader &&
- !current->signal->tty &&
- tty->session == NULL)
- __proc_set_tty(current, tty);
- spin_unlock_irq(¤t->sighand->siglock);
- unlock_kernel();
- mutex_unlock(&tty_mutex);
- return 0;
-}
-
-
-
-/**
- * tty_poll - check tty status
- * @filp: file being polled
- * @wait: poll wait structures to update
- *
- * Call the line discipline polling method to obtain the poll
- * status of the device.
- *
- * Locking: locks called line discipline but ldisc poll method
- * may be re-entered freely by other callers.
- */
-
-static unsigned int tty_poll(struct file *filp, poll_table *wait)
-{
- struct tty_struct *tty;
- struct tty_ldisc *ld;
- int ret = 0;
-
- tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
- return 0;
-
- ld = tty_ldisc_ref_wait(tty);
- if (ld->ops->poll)
- ret = (ld->ops->poll)(tty, filp, wait);
- tty_ldisc_deref(ld);
- return ret;
-}
-
-static int tty_fasync(int fd, struct file *filp, int on)
-{
- struct tty_struct *tty;
- unsigned long flags;
- int retval = 0;
-
- lock_kernel();
- tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
- goto out;
-
- retval = fasync_helper(fd, filp, on, &tty->fasync);
- if (retval <= 0)
- goto out;
-
- if (on) {
- enum pid_type type;
- struct pid *pid;
- if (!waitqueue_active(&tty->read_wait))
- tty->minimum_to_wake = 1;
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- if (tty->pgrp) {
- pid = tty->pgrp;
- type = PIDTYPE_PGID;
- } else {
- pid = task_pid(current);
- type = PIDTYPE_PID;
- }
- get_pid(pid);
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- retval = __f_setown(filp, pid, type, 0);
- put_pid(pid);
- if (retval)
- goto out;
- } else {
- if (!tty->fasync && !waitqueue_active(&tty->read_wait))
- tty->minimum_to_wake = N_TTY_BUF_SIZE;
- }
- retval = 0;
-out:
- unlock_kernel();
- return retval;
-}
-
-/**
- * tiocsti - fake input character
- * @tty: tty to fake input into
- * @p: pointer to character
- *
- * Fake input to a tty device. Does the necessary locking and
- * input management.
- *
- * FIXME: does not honour flow control ??
- *
- * Locking:
- * Called functions take tty_ldisc_lock
- * current->signal->tty check is safe without locks
- *
- * FIXME: may race normal receive processing
- */
-
-static int tiocsti(struct tty_struct *tty, char __user *p)
-{
- char ch, mbz = 0;
- struct tty_ldisc *ld;
-
- if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (get_user(ch, p))
- return -EFAULT;
- tty_audit_tiocsti(tty, ch);
- ld = tty_ldisc_ref_wait(tty);
- ld->ops->receive_buf(tty, &ch, &mbz, 1);
- tty_ldisc_deref(ld);
- return 0;
-}
-
-/**
- * tiocgwinsz - implement window query ioctl
- * @tty; tty
- * @arg: user buffer for result
- *
- * Copies the kernel idea of the window size into the user buffer.
- *
- * Locking: tty->termios_mutex is taken to ensure the winsize data
- * is consistent.
- */
-
-static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
-{
- int err;
-
- mutex_lock(&tty->termios_mutex);
- err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
- mutex_unlock(&tty->termios_mutex);
-
- return err ? -EFAULT: 0;
-}
-
-/**
- * tty_do_resize - resize event
- * @tty: tty being resized
- * @rows: rows (character)
- * @cols: cols (character)
- *
- * Update the termios variables and send the necessary signals to
- * peform a terminal resize correctly
- */
-
-int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
-{
- struct pid *pgrp;
- unsigned long flags;
-
- /* Lock the tty */
- mutex_lock(&tty->termios_mutex);
- if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
- goto done;
- /* Get the PID values and reference them so we can
- avoid holding the tty ctrl lock while sending signals */
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- pgrp = get_pid(tty->pgrp);
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-
- if (pgrp)
- kill_pgrp(pgrp, SIGWINCH, 1);
- put_pid(pgrp);
-
- tty->winsize = *ws;
-done:
- mutex_unlock(&tty->termios_mutex);
- return 0;
-}
-
-/**
- * tiocswinsz - implement window size set ioctl
- * @tty; tty side of tty
- * @arg: user buffer for result
- *
- * Copies the user idea of the window size to the kernel. Traditionally
- * this is just advisory information but for the Linux console it
- * actually has driver level meaning and triggers a VC resize.
- *
- * Locking:
- * Driver dependant. The default do_resize method takes the
- * tty termios mutex and ctrl_lock. The console takes its own lock
- * then calls into the default method.
- */
-
-static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg)
-{
- struct winsize tmp_ws;
- if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
- return -EFAULT;
-
- if (tty->ops->resize)
- return tty->ops->resize(tty, &tmp_ws);
- else
- return tty_do_resize(tty, &tmp_ws);
-}
-
-/**
- * tioccons - allow admin to move logical console
- * @file: the file to become console
- *
- * Allow the adminstrator to move the redirected console device
- *
- * Locking: uses redirect_lock to guard the redirect information
- */
-
-static int tioccons(struct file *file)
-{
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (file->f_op->write == redirected_tty_write) {
- struct file *f;
- spin_lock(&redirect_lock);
- f = redirect;
- redirect = NULL;
- spin_unlock(&redirect_lock);
- if (f)
- fput(f);
- return 0;
- }
- spin_lock(&redirect_lock);
- if (redirect) {
- spin_unlock(&redirect_lock);
- return -EBUSY;
- }
- get_file(file);
- redirect = file;
- spin_unlock(&redirect_lock);
- return 0;
-}
-
-/**
- * fionbio - non blocking ioctl
- * @file: file to set blocking value
- * @p: user parameter
- *
- * Historical tty interfaces had a blocking control ioctl before
- * the generic functionality existed. This piece of history is preserved
- * in the expected tty API of posix OS's.
- *
- * Locking: none, the open file handle ensures it won't go away.
- */
-
-static int fionbio(struct file *file, int __user *p)
-{
- int nonblock;
-
- if (get_user(nonblock, p))
- return -EFAULT;
-
- spin_lock(&file->f_lock);
- if (nonblock)
- file->f_flags |= O_NONBLOCK;
- else
- file->f_flags &= ~O_NONBLOCK;
- spin_unlock(&file->f_lock);
- return 0;
-}
-
-/**
- * tiocsctty - set controlling tty
- * @tty: tty structure
- * @arg: user argument
- *
- * This ioctl is used to manage job control. It permits a session
- * leader to set this tty as the controlling tty for the session.
- *
- * Locking:
- * Takes tty_mutex() to protect tty instance
- * Takes tasklist_lock internally to walk sessions
- * Takes ->siglock() when updating signal->tty
- */
-
-static int tiocsctty(struct tty_struct *tty, int arg)
-{
- int ret = 0;
- if (current->signal->leader && (task_session(current) == tty->session))
- return ret;
-
- mutex_lock(&tty_mutex);
- /*
- * The process must be a session leader and
- * not have a controlling tty already.
- */
- if (!current->signal->leader || current->signal->tty) {
- ret = -EPERM;
- goto unlock;
- }
-
- if (tty->session) {
- /*
- * This tty is already the controlling
- * tty for another session group!
- */
- if (arg == 1 && capable(CAP_SYS_ADMIN)) {
- /*
- * Steal it away
- */
- read_lock(&tasklist_lock);
- session_clear_tty(tty->session);
- read_unlock(&tasklist_lock);
- } else {
- ret = -EPERM;
- goto unlock;
- }
- }
- proc_set_tty(current, tty);
-unlock:
- mutex_unlock(&tty_mutex);
- return ret;
-}
-
-/**
- * tty_get_pgrp - return a ref counted pgrp pid
- * @tty: tty to read
- *
- * Returns a refcounted instance of the pid struct for the process
- * group controlling the tty.
- */
-
-struct pid *tty_get_pgrp(struct tty_struct *tty)
-{
- unsigned long flags;
- struct pid *pgrp;
-
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- pgrp = get_pid(tty->pgrp);
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-
- return pgrp;
-}
-EXPORT_SYMBOL_GPL(tty_get_pgrp);
-
-/**
- * tiocgpgrp - get process group
- * @tty: tty passed by user
- * @real_tty: tty side of the tty pased by the user if a pty else the tty
- * @p: returned pid
- *
- * Obtain the process group of the tty. If there is no process group
- * return an error.
- *
- * Locking: none. Reference to current->signal->tty is safe.
- */
-
-static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
-{
- struct pid *pid;
- int ret;
- /*
- * (tty == real_tty) is a cheap way of
- * testing if the tty is NOT a master pty.
- */
- if (tty == real_tty && current->signal->tty != real_tty)
- return -ENOTTY;
- pid = tty_get_pgrp(real_tty);
- ret = put_user(pid_vnr(pid), p);
- put_pid(pid);
- return ret;
-}
-
-/**
- * tiocspgrp - attempt to set process group
- * @tty: tty passed by user
- * @real_tty: tty side device matching tty passed by user
- * @p: pid pointer
- *
- * Set the process group of the tty to the session passed. Only
- * permitted where the tty session is our session.
- *
- * Locking: RCU, ctrl lock
- */
-
-static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
-{
- struct pid *pgrp;
- pid_t pgrp_nr;
- int retval = tty_check_change(real_tty);
- unsigned long flags;
-
- if (retval == -EIO)
- return -ENOTTY;
- if (retval)
- return retval;
- if (!current->signal->tty ||
- (current->signal->tty != real_tty) ||
- (real_tty->session != task_session(current)))
- return -ENOTTY;
- if (get_user(pgrp_nr, p))
- return -EFAULT;
- if (pgrp_nr < 0)
- return -EINVAL;
- rcu_read_lock();
- pgrp = find_vpid(pgrp_nr);
- retval = -ESRCH;
- if (!pgrp)
- goto out_unlock;
- retval = -EPERM;
- if (session_of_pgrp(pgrp) != task_session(current))
- goto out_unlock;
- retval = 0;
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- put_pid(real_tty->pgrp);
- real_tty->pgrp = get_pid(pgrp);
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-out_unlock:
- rcu_read_unlock();
- return retval;
-}
-
-/**
- * tiocgsid - get session id
- * @tty: tty passed by user
- * @real_tty: tty side of the tty pased by the user if a pty else the tty
- * @p: pointer to returned session id
- *
- * Obtain the session id of the tty. If there is no session
- * return an error.
- *
- * Locking: none. Reference to current->signal->tty is safe.
- */
-
-static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
-{
- /*
- * (tty == real_tty) is a cheap way of
- * testing if the tty is NOT a master pty.
- */
- if (tty == real_tty && current->signal->tty != real_tty)
- return -ENOTTY;
- if (!real_tty->session)
- return -ENOTTY;
- return put_user(pid_vnr(real_tty->session), p);
-}
-
-/**
- * tiocsetd - set line discipline
- * @tty: tty device
- * @p: pointer to user data
- *
- * Set the line discipline according to user request.
- *
- * Locking: see tty_set_ldisc, this function is just a helper
- */
-
-static int tiocsetd(struct tty_struct *tty, int __user *p)
-{
- int ldisc;
- int ret;
-
- if (get_user(ldisc, p))
- return -EFAULT;
-
- ret = tty_set_ldisc(tty, ldisc);
-
- return ret;
-}
-
-/**
- * send_break - performed time break
- * @tty: device to break on
- * @duration: timeout in mS
- *
- * Perform a timed break on hardware that lacks its own driver level
- * timed break functionality.
- *
- * Locking:
- * atomic_write_lock serializes
- *
- */
-
-static int send_break(struct tty_struct *tty, unsigned int duration)
-{
- int retval;
-
- if (tty->ops->break_ctl == NULL)
- return 0;
-
- if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK)
- retval = tty->ops->break_ctl(tty, duration);
- else {
- /* Do the work ourselves */
- if (tty_write_lock(tty, 0) < 0)
- return -EINTR;
- retval = tty->ops->break_ctl(tty, -1);
- if (retval)
- goto out;
- if (!signal_pending(current))
- msleep_interruptible(duration);
- retval = tty->ops->break_ctl(tty, 0);
-out:
- tty_write_unlock(tty);
- if (signal_pending(current))
- retval = -EINTR;
- }
- return retval;
-}
-
-/**
- * tty_tiocmget - get modem status
- * @tty: tty device
- * @file: user file pointer
- * @p: pointer to result
- *
- * Obtain the modem status bits from the tty driver if the feature
- * is supported. Return -EINVAL if it is not available.
- *
- * Locking: none (up to the driver)
- */
-
-static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
-{
- int retval = -EINVAL;
-
- if (tty->ops->tiocmget) {
- retval = tty->ops->tiocmget(tty, file);
-
- if (retval >= 0)
- retval = put_user(retval, p);
- }
- return retval;
-}
-
-/**
- * tty_tiocmset - set modem status
- * @tty: tty device
- * @file: user file pointer
- * @cmd: command - clear bits, set bits or set all
- * @p: pointer to desired bits
- *
- * Set the modem status bits from the tty driver if the feature
- * is supported. Return -EINVAL if it is not available.
- *
- * Locking: none (up to the driver)
- */
-
-static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
- unsigned __user *p)
-{
- int retval;
- unsigned int set, clear, val;
-
- if (tty->ops->tiocmset == NULL)
- return -EINVAL;
-
- retval = get_user(val, p);
- if (retval)
- return retval;
- set = clear = 0;
- switch (cmd) {
- case TIOCMBIS:
- set = val;
- break;
- case TIOCMBIC:
- clear = val;
- break;
- case TIOCMSET:
- set = val;
- clear = ~val;
- break;
- }
- set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP|TIOCM_CD|
- TIOCM_RI|TIOCM_DSR|TIOCM_CTS;
- clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP|TIOCM_CD|
- TIOCM_RI|TIOCM_DSR|TIOCM_CTS;
- return tty->ops->tiocmset(tty, file, set, clear);
-}
-
-struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
-{
- if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
- tty->driver->subtype == PTY_TYPE_MASTER)
- tty = tty->link;
- return tty;
-}
-EXPORT_SYMBOL(tty_pair_get_tty);
-
-struct tty_struct *tty_pair_get_pty(struct tty_struct *tty)
-{
- if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
- tty->driver->subtype == PTY_TYPE_MASTER)
- return tty;
- return tty->link;
-}
-EXPORT_SYMBOL(tty_pair_get_pty);
-
-/*
- * Split this up, as gcc can choke on it otherwise..
- */
-long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct tty_struct *tty, *real_tty;
- void __user *p = (void __user *)arg;
- int retval;
- struct tty_ldisc *ld;
- struct inode *inode = file->f_dentry->d_inode;
-
- tty = (struct tty_struct *)file->private_data;
- if (tty_paranoia_check(tty, inode, "tty_ioctl"))
- return -EINVAL;
-
- real_tty = tty_pair_get_tty(tty);
-
- /*
- * Factor out some common prep work
- */
- switch (cmd) {
- case TIOCSETD:
- case TIOCSBRK:
- case TIOCCBRK:
- case TCSBRK:
- case TCSBRKP:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- if (cmd != TIOCCBRK) {
- tty_wait_until_sent(tty, 0);
- if (signal_pending(current))
- return -EINTR;
- }
- break;
- }
-
- /*
- * Now do the stuff.
- */
- switch (cmd) {
- case TIOCSTI:
- return tiocsti(tty, p);
- case TIOCGWINSZ:
- return tiocgwinsz(real_tty, p);
- case TIOCSWINSZ:
- return tiocswinsz(real_tty, p);
- case TIOCCONS:
- return real_tty != tty ? -EINVAL : tioccons(file);
- case FIONBIO:
- return fionbio(file, p);
- case TIOCEXCL:
- set_bit(TTY_EXCLUSIVE, &tty->flags);
- return 0;
- case TIOCNXCL:
- clear_bit(TTY_EXCLUSIVE, &tty->flags);
- return 0;
- case TIOCNOTTY:
- if (current->signal->tty != tty)
- return -ENOTTY;
- no_tty();
- return 0;
- case TIOCSCTTY:
- return tiocsctty(tty, arg);
- case TIOCGPGRP:
- return tiocgpgrp(tty, real_tty, p);
- case TIOCSPGRP:
- return tiocspgrp(tty, real_tty, p);
- case TIOCGSID:
- return tiocgsid(tty, real_tty, p);
- case TIOCGETD:
- return put_user(tty->ldisc->ops->num, (int __user *)p);
- case TIOCSETD:
- return tiocsetd(tty, p);
- /*
- * Break handling
- */
- case TIOCSBRK: /* Turn break on, unconditionally */
- if (tty->ops->break_ctl)
- return tty->ops->break_ctl(tty, -1);
- return 0;
- case TIOCCBRK: /* Turn break off, unconditionally */
- if (tty->ops->break_ctl)
- return tty->ops->break_ctl(tty, 0);
- return 0;
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- /* non-zero arg means wait for all output data
- * to be sent (performed above) but don't send break.
- * This is used by the tcdrain() termios function.
- */
- if (!arg)
- return send_break(tty, 250);
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- return send_break(tty, arg ? arg*100 : 250);
-
- case TIOCMGET:
- return tty_tiocmget(tty, file, p);
- case TIOCMSET:
- case TIOCMBIC:
- case TIOCMBIS:
- return tty_tiocmset(tty, file, cmd, p);
- case TCFLSH:
- switch (arg) {
- case TCIFLUSH:
- case TCIOFLUSH:
- /* flush tty buffer and allow ldisc to process ioctl */
- tty_buffer_flush(tty);
- break;
- }
- break;
- }
- if (tty->ops->ioctl) {
- retval = (tty->ops->ioctl)(tty, file, cmd, arg);
- if (retval != -ENOIOCTLCMD)
- return retval;
- }
- ld = tty_ldisc_ref_wait(tty);
- retval = -EINVAL;
- if (ld->ops->ioctl) {
- retval = ld->ops->ioctl(tty, file, cmd, arg);
- if (retval == -ENOIOCTLCMD)
- retval = -EINVAL;
- }
- tty_ldisc_deref(ld);
- return retval;
-}
-
-#ifdef CONFIG_COMPAT
-static long tty_compat_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct inode *inode = file->f_dentry->d_inode;
- struct tty_struct *tty = file->private_data;
- struct tty_ldisc *ld;
- int retval = -ENOIOCTLCMD;
-
- if (tty_paranoia_check(tty, inode, "tty_ioctl"))
- return -EINVAL;
-
- if (tty->ops->compat_ioctl) {
- retval = (tty->ops->compat_ioctl)(tty, file, cmd, arg);
- if (retval != -ENOIOCTLCMD)
- return retval;
- }
-
- ld = tty_ldisc_ref_wait(tty);
- if (ld->ops->compat_ioctl)
- retval = ld->ops->compat_ioctl(tty, file, cmd, arg);
- tty_ldisc_deref(ld);
-
- return retval;
-}
-#endif
-
-/*
- * This implements the "Secure Attention Key" --- the idea is to
- * prevent trojan horses by killing all processes associated with this
- * tty when the user hits the "Secure Attention Key". Required for
- * super-paranoid applications --- see the Orange Book for more details.
- *
- * This code could be nicer; ideally it should send a HUP, wait a few
- * seconds, then send a INT, and then a KILL signal. But you then
- * have to coordinate with the init process, since all processes associated
- * with the current tty must be dead before the new getty is allowed
- * to spawn.
- *
- * Now, if it would be correct ;-/ The current code has a nasty hole -
- * it doesn't catch files in flight. We may send the descriptor to ourselves
- * via AF_UNIX socket, close it and later fetch from socket. FIXME.
- *
- * Nasty bug: do_SAK is being called in interrupt context. This can
- * deadlock. We punt it up to process context. AKPM - 16Mar2001
- */
-void __do_SAK(struct tty_struct *tty)
-{
-#ifdef TTY_SOFT_SAK
- tty_hangup(tty);
-#else
- struct task_struct *g, *p;
- struct pid *session;
- int i;
- struct file *filp;
- struct fdtable *fdt;
-
- if (!tty)
- return;
- session = tty->session;
-
- tty_ldisc_flush(tty);
-
- tty_driver_flush_buffer(tty);
-
- read_lock(&tasklist_lock);
- /* Kill the entire session */
- do_each_pid_task(session, PIDTYPE_SID, p) {
- printk(KERN_NOTICE "SAK: killed process %d"
- " (%s): task_session(p)==tty->session\n",
- task_pid_nr(p), p->comm);
- send_sig(SIGKILL, p, 1);
- } while_each_pid_task(session, PIDTYPE_SID, p);
- /* Now kill any processes that happen to have the
- * tty open.
- */
- do_each_thread(g, p) {
- if (p->signal->tty == tty) {
- printk(KERN_NOTICE "SAK: killed process %d"
- " (%s): task_session(p)==tty->session\n",
- task_pid_nr(p), p->comm);
- send_sig(SIGKILL, p, 1);
- continue;
- }
- task_lock(p);
- if (p->files) {
- /*
- * We don't take a ref to the file, so we must
- * hold ->file_lock instead.
- */
- spin_lock(&p->files->file_lock);
- fdt = files_fdtable(p->files);
- for (i = 0; i < fdt->max_fds; i++) {
- filp = fcheck_files(p->files, i);
- if (!filp)
- continue;
- if (filp->f_op->read == tty_read &&
- filp->private_data == tty) {
- printk(KERN_NOTICE "SAK: killed process %d"
- " (%s): fd#%d opened to the tty\n",
- task_pid_nr(p), p->comm, i);
- force_sig(SIGKILL, p);
- break;
- }
- }
- spin_unlock(&p->files->file_lock);
- }
- task_unlock(p);
- } while_each_thread(g, p);
- read_unlock(&tasklist_lock);
-#endif
-}
-
-static void do_SAK_work(struct work_struct *work)
-{
- struct tty_struct *tty =
- container_of(work, struct tty_struct, SAK_work);
- __do_SAK(tty);
-}
-
-/*
- * The tq handling here is a little racy - tty->SAK_work may already be queued.
- * Fortunately we don't need to worry, because if ->SAK_work is already queued,
- * the values which we write to it will be identical to the values which it
- * already has. --akpm
- */
-void do_SAK(struct tty_struct *tty)
-{
- if (!tty)
- return;
- schedule_work(&tty->SAK_work);
-}
-
-EXPORT_SYMBOL(do_SAK);
-
-/**
- * initialize_tty_struct
- * @tty: tty to initialize
- *
- * This subroutine initializes a tty structure that has been newly
- * allocated.
- *
- * Locking: none - tty in question must not be exposed at this point
- */
-
-void initialize_tty_struct(struct tty_struct *tty,
- struct tty_driver *driver, int idx)
-{
- memset(tty, 0, sizeof(struct tty_struct));
- kref_init(&tty->kref);
- tty->magic = TTY_MAGIC;
- tty_ldisc_init(tty);
- tty->session = NULL;
- tty->pgrp = NULL;
- tty->overrun_time = jiffies;
- tty->buf.head = tty->buf.tail = NULL;
- tty_buffer_init(tty);
- mutex_init(&tty->termios_mutex);
- mutex_init(&tty->ldisc_mutex);
- init_waitqueue_head(&tty->write_wait);
- init_waitqueue_head(&tty->read_wait);
- INIT_WORK(&tty->hangup_work, do_tty_hangup);
- mutex_init(&tty->atomic_read_lock);
- mutex_init(&tty->atomic_write_lock);
- mutex_init(&tty->output_lock);
- mutex_init(&tty->echo_lock);
- spin_lock_init(&tty->read_lock);
- spin_lock_init(&tty->ctrl_lock);
- INIT_LIST_HEAD(&tty->tty_files);
- INIT_WORK(&tty->SAK_work, do_SAK_work);
-
- tty->driver = driver;
- tty->ops = driver->ops;
- tty->index = idx;
- tty_line_name(driver, idx, tty->name);
-}
-
-/**
- * tty_put_char - write one character to a tty
- * @tty: tty
- * @ch: character
- *
- * Write one byte to the tty using the provided put_char method
- * if present. Returns the number of characters successfully output.
- *
- * Note: the specific put_char operation in the driver layer may go
- * away soon. Don't call it directly, use this method
- */
-
-int tty_put_char(struct tty_struct *tty, unsigned char ch)
-{
- if (tty->ops->put_char)
- return tty->ops->put_char(tty, ch);
- return tty->ops->write(tty, &ch, 1);
-}
-EXPORT_SYMBOL_GPL(tty_put_char);
-
-struct class *tty_class;
-
-/**
- * tty_register_device - register a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
- * @device: a struct device that is associated with this tty device.
- * This field is optional, if there is no known struct device
- * for this tty device it can be set to NULL safely.
- *
- * Returns a pointer to the struct device for this tty device
- * (or ERR_PTR(-EFOO) on error).
- *
- * This call is required to be made to register an individual tty device
- * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If
- * that bit is not set, this function should not be called by a tty
- * driver.
- *
- * Locking: ??
- */
-
-struct device *tty_register_device(struct tty_driver *driver, unsigned index,
- struct device *device)
-{
- char name[64];
- dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
-
- if (index >= driver->num) {
- printk(KERN_ERR "Attempt to register invalid tty line number "
- " (%d).\n", index);
- return ERR_PTR(-EINVAL);
- }
-
- if (driver->type == TTY_DRIVER_TYPE_PTY)
- pty_line_name(driver, index, name);
- else
- tty_line_name(driver, index, name);
-
- return device_create(tty_class, device, dev, NULL, name);
-}
-EXPORT_SYMBOL(tty_register_device);
-
-/**
- * tty_unregister_device - unregister a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
- *
- * If a tty device is registered with a call to tty_register_device() then
- * this function must be called when the tty device is gone.
- *
- * Locking: ??
- */
-
-void tty_unregister_device(struct tty_driver *driver, unsigned index)
-{
- device_destroy(tty_class,
- MKDEV(driver->major, driver->minor_start) + index);
-}
-EXPORT_SYMBOL(tty_unregister_device);
-
-struct tty_driver *alloc_tty_driver(int lines)
-{
- struct tty_driver *driver;
-
- driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
- if (driver) {
- kref_init(&driver->kref);
- driver->magic = TTY_DRIVER_MAGIC;
- driver->num = lines;
- /* later we'll move allocation of tables here */
- }
- return driver;
-}
-EXPORT_SYMBOL(alloc_tty_driver);
-
-static void destruct_tty_driver(struct kref *kref)
-{
- struct tty_driver *driver = container_of(kref, struct tty_driver, kref);
- int i;
- struct ktermios *tp;
- void *p;
-
- if (driver->flags & TTY_DRIVER_INSTALLED) {
- /*
- * Free the termios and termios_locked structures because
- * we don't want to get memory leaks when modular tty
- * drivers are removed from the kernel.
- */
- for (i = 0; i < driver->num; i++) {
- tp = driver->termios[i];
- if (tp) {
- driver->termios[i] = NULL;
- kfree(tp);
- }
- if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
- tty_unregister_device(driver, i);
- }
- p = driver->ttys;
- proc_tty_unregister_driver(driver);
- driver->ttys = NULL;
- driver->termios = NULL;
- kfree(p);
- cdev_del(&driver->cdev);
- }
- kfree(driver);
-}
-
-void tty_driver_kref_put(struct tty_driver *driver)
-{
- kref_put(&driver->kref, destruct_tty_driver);
-}
-EXPORT_SYMBOL(tty_driver_kref_put);
-
-void tty_set_operations(struct tty_driver *driver,
- const struct tty_operations *op)
-{
- driver->ops = op;
-};
-EXPORT_SYMBOL(tty_set_operations);
-
-void put_tty_driver(struct tty_driver *d)
-{
- tty_driver_kref_put(d);
-}
-EXPORT_SYMBOL(put_tty_driver);
-
-/*
- * Called by a tty driver to register itself.
- */
-int tty_register_driver(struct tty_driver *driver)
-{
- int error;
- int i;
- dev_t dev;
- void **p = NULL;
-
- if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
- p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
- }
-
- if (!driver->major) {
- error = alloc_chrdev_region(&dev, driver->minor_start,
- driver->num, driver->name);
- if (!error) {
- driver->major = MAJOR(dev);
- driver->minor_start = MINOR(dev);
- }
- } else {
- dev = MKDEV(driver->major, driver->minor_start);
- error = register_chrdev_region(dev, driver->num, driver->name);
- }
- if (error < 0) {
- kfree(p);
- return error;
- }
-
- if (p) {
- driver->ttys = (struct tty_struct **)p;
- driver->termios = (struct ktermios **)(p + driver->num);
- } else {
- driver->ttys = NULL;
- driver->termios = NULL;
- }
-
- cdev_init(&driver->cdev, &tty_fops);
- driver->cdev.owner = driver->owner;
- error = cdev_add(&driver->cdev, dev, driver->num);
- if (error) {
- unregister_chrdev_region(dev, driver->num);
- driver->ttys = NULL;
- driver->termios = NULL;
- kfree(p);
- return error;
- }
-
- mutex_lock(&tty_mutex);
- list_add(&driver->tty_drivers, &tty_drivers);
- mutex_unlock(&tty_mutex);
-
- if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
- for (i = 0; i < driver->num; i++)
- tty_register_device(driver, i, NULL);
- }
- proc_tty_register_driver(driver);
- driver->flags |= TTY_DRIVER_INSTALLED;
- return 0;
-}
-
-EXPORT_SYMBOL(tty_register_driver);
-
-/*
- * Called by a tty driver to unregister itself.
- */
-int tty_unregister_driver(struct tty_driver *driver)
-{
-#if 0
- /* FIXME */
- if (driver->refcount)
- return -EBUSY;
-#endif
- unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
- driver->num);
- mutex_lock(&tty_mutex);
- list_del(&driver->tty_drivers);
- mutex_unlock(&tty_mutex);
- return 0;
-}
-
-EXPORT_SYMBOL(tty_unregister_driver);
-
-dev_t tty_devnum(struct tty_struct *tty)
-{
- return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
-}
-EXPORT_SYMBOL(tty_devnum);
-
-void proc_clear_tty(struct task_struct *p)
-{
- unsigned long flags;
- struct tty_struct *tty;
- spin_lock_irqsave(&p->sighand->siglock, flags);
- tty = p->signal->tty;
- p->signal->tty = NULL;
- spin_unlock_irqrestore(&p->sighand->siglock, flags);
- tty_kref_put(tty);
-}
-
-/* Called under the sighand lock */
-
-static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
-{
- if (tty) {
- unsigned long flags;
- /* We should not have a session or pgrp to put here but.... */
- spin_lock_irqsave(&tty->ctrl_lock, flags);
- put_pid(tty->session);
- put_pid(tty->pgrp);
- tty->pgrp = get_pid(task_pgrp(tsk));
- spin_unlock_irqrestore(&tty->ctrl_lock, flags);
- tty->session = get_pid(task_session(tsk));
- if (tsk->signal->tty) {
- printk(KERN_DEBUG "tty not NULL!!\n");
- tty_kref_put(tsk->signal->tty);
- }
- }
- put_pid(tsk->signal->tty_old_pgrp);
- tsk->signal->tty = tty_kref_get(tty);
- tsk->signal->tty_old_pgrp = NULL;
-}
-
-static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
-{
- spin_lock_irq(&tsk->sighand->siglock);
- __proc_set_tty(tsk, tty);
- spin_unlock_irq(&tsk->sighand->siglock);
-}
-
-struct tty_struct *get_current_tty(void)
-{
- struct tty_struct *tty;
- unsigned long flags;
-
- spin_lock_irqsave(¤t->sighand->siglock, flags);
- tty = tty_kref_get(current->signal->tty);
- spin_unlock_irqrestore(¤t->sighand->siglock, flags);
- return tty;
-}
-EXPORT_SYMBOL_GPL(get_current_tty);
-
-void tty_default_fops(struct file_operations *fops)
-{
- *fops = tty_fops;
-}
-
-/*
- * Initialize the console device. This is called *early*, so
- * we can't necessarily depend on lots of kernel help here.
- * Just do some early initializations, and do the complex setup
- * later.
- */
-void __init console_init(void)
-{
- initcall_t *call;
-
- /* Setup the default TTY line discipline. */
- tty_ldisc_begin();
-
- /*
- * set up the console device so that later boot sequences can
- * inform about problems etc..
- */
- call = __con_initcall_start;
- while (call < __con_initcall_end) {
- (*call)();
- call++;
- }
-}
-
-static char *tty_devnode(struct device *dev, mode_t *mode)
-{
- if (!mode)
- return NULL;
- if (dev->devt == MKDEV(TTYAUX_MAJOR, 0) ||
- dev->devt == MKDEV(TTYAUX_MAJOR, 2))
- *mode = 0666;
- return NULL;
-}
-
-static int __init tty_class_init(void)
-{
- tty_class = class_create(THIS_MODULE, "tty");
- if (IS_ERR(tty_class))
- return PTR_ERR(tty_class);
- tty_class->devnode = tty_devnode;
- return 0;
-}
-
-postcore_initcall(tty_class_init);
-
-/* 3/2004 jmc: why do these devices exist? */
-
-static struct cdev tty_cdev, console_cdev;
-
-/*
- * Ok, now we can initialize the rest of the tty devices and can count
- * on memory allocations, interrupts etc..
- */
-int __init tty_init(void)
-{
- cdev_init(&tty_cdev, &tty_fops);
- if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
- register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
- panic("Couldn't register /dev/tty driver\n");
- device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
- "tty");
-
- cdev_init(&console_cdev, &console_fops);
- if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
- register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
- panic("Couldn't register /dev/console driver\n");
- device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
- "console");
-
-#ifdef CONFIG_VT
- vty_init(&console_fops);
-#endif
- return 0;
-}
-
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 3157a86..ec38843 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -163,15 +163,6 @@
{
int mult = 1;
- /* for higher loadavg, we are more reluctant */
-
- /*
- * this doesn't work as intended - it is almost always 0, but can
- * sometimes, depending on workload, spike very high into the hundreds
- * even when the average cpu load is under 10%.
- */
- /* mult += 2 * get_loadavg(); */
-
/* for IO wait tasks (per cpu!) we add 5x each */
mult += 10 * nr_iowait_cpu(smp_processor_id());
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 1facf24..9d8e825 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -353,6 +353,9 @@
pce = cmdlistinfo->auth_seg_size;
pce->data = sreq->size;
+ pce = cmdlistinfo->encr_seg_cfg;
+ pce->data = 0;
+
/* write auth seg size start*/
pce = cmdlistinfo->auth_seg_start;
pce->data = 0;
@@ -521,8 +524,12 @@
pce->data = totallen_in - creq->authsize;
pce = cmdlistinfo->auth_seg_start;
pce->data = 0;
+ } else {
+ if (creq->op != QCE_REQ_AEAD) {
+ pce = cmdlistinfo->auth_seg_cfg;
+ pce->data = 0;
+ }
}
-
switch (creq->mode) {
case QCE_MODE_ECB:
encr_cfg |= (CRYPTO_ENCR_MODE_ECB << CRYPTO_ENCR_MODE);
@@ -1289,7 +1296,7 @@
CRYPTO_RESULT_DUMP_SIZE,
&pce_dev->ce_sps.out_transfer);
_qce_set_flag(&pce_dev->ce_sps.out_transfer,
- SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_INT);
+ SPS_IOVEC_FLAG_INT);
rc = sps_transfer(pce_dev->ce_sps.producer.pipe,
&pce_dev->ce_sps.out_transfer);
if (rc) {
@@ -1364,7 +1371,7 @@
CRYPTO_RESULT_DUMP_SIZE,
&pce_dev->ce_sps.out_transfer);
_qce_set_flag(&pce_dev->ce_sps.out_transfer,
- SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_INT);
+ SPS_IOVEC_FLAG_INT);
rc = sps_transfer(pce_dev->ce_sps.producer.pipe,
&pce_dev->ce_sps.out_transfer);
if (rc) {
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 0904f9fe..9ab2343 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -914,7 +914,7 @@
if (type == ION_HEAP_TYPE_SYSTEM_CONTIG ||
type == ION_HEAP_TYPE_CARVEOUT ||
type == (enum ion_heap_type) ION_HEAP_TYPE_CP)
- seq_printf(s, " : %12lx", handle->buffer->priv_phys);
+ seq_printf(s, " : %12pa", &handle->buffer->priv_phys);
else
seq_printf(s, " : %12s", "N/A");
@@ -1988,8 +1988,8 @@
ret = memblock_reserve(data->heaps[i].base,
data->heaps[i].size);
if (ret)
- pr_err("memblock reserve of %x@%lx failed\n",
+ pr_err("memblock reserve of %x@%pa failed\n",
data->heaps[i].size,
- data->heaps[i].base);
+ &data->heaps[i].base);
}
}
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 3e55a57..b51fa6a 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -297,8 +297,11 @@
const char *client_name = "(null)";
if (last_end < data->addr) {
- seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
- "FREE", last_end, data->addr-1,
+ phys_addr_t da;
+
+ da = data->addr-1;
+ seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+ "FREE", &last_end, &da,
data->addr-last_end,
data->addr-last_end);
}
@@ -306,9 +309,9 @@
if (data->client_name)
client_name = data->client_name;
- seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
- client_name, data->addr,
- data->addr_end,
+ seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+ client_name, &data->addr,
+ &data->addr_end,
data->size, data->size);
last_end = data->addr_end+1;
}
diff --git a/drivers/gpu/ion/ion_cma_heap.c b/drivers/gpu/ion/ion_cma_heap.c
index 4f5ac75..8063138 100644
--- a/drivers/gpu/ion/ion_cma_heap.c
+++ b/drivers/gpu/ion/ion_cma_heap.c
@@ -325,9 +325,9 @@
if (data->client_name)
client_name = data->client_name;
- seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
- client_name, data->addr,
- data->addr_end,
+ seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+ client_name, &data->addr,
+ &data->addr_end,
data->size, data->size);
}
}
diff --git a/drivers/gpu/ion/ion_cma_secure_heap.c b/drivers/gpu/ion/ion_cma_secure_heap.c
index 2c0e5ae..496e5b4 100644
--- a/drivers/gpu/ion/ion_cma_secure_heap.c
+++ b/drivers/gpu/ion/ion_cma_secure_heap.c
@@ -359,9 +359,9 @@
if (data->client_name)
client_name = data->client_name;
- seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
- client_name, data->addr,
- data->addr_end,
+ seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+ client_name, &data->addr,
+ &data->addr_end,
data->size, data->size);
}
}
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 56ccc8f..a7473e2 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -256,8 +256,8 @@
atomic_dec(&cp_heap->protect_cnt);
} else {
cp_heap->heap_protected = HEAP_PROTECTED;
- pr_debug("Protected heap %s @ 0x%lx\n",
- heap->name, cp_heap->base);
+ pr_debug("Protected heap %s @ 0x%pa\n",
+ heap->name, &cp_heap->base);
}
}
out:
@@ -804,8 +804,11 @@
const char *client_name = "(null)";
if (last_end < data->addr) {
- seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
- "FREE", last_end, data->addr-1,
+ phys_addr_t da;
+
+ da = data->addr-1;
+ seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+ "FREE", &last_end, &da,
data->addr-last_end,
data->addr-last_end);
}
@@ -813,9 +816,9 @@
if (data->client_name)
client_name = data->client_name;
- seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
- client_name, data->addr,
- data->addr_end,
+ seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+ client_name, &data->addr,
+ &data->addr_end,
data->size, data->size);
last_end = data->addr_end+1;
}
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index ff2b8dd..46fefb5 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -56,9 +56,9 @@
}
if (IS_ERR_OR_NULL(heap)) {
- pr_err("%s: error creating heap %s type %d base %lu size %u\n",
+ pr_err("%s: error creating heap %s type %d base %pa size %u\n",
__func__, heap_data->name, heap_data->type,
- heap_data->base, heap_data->size);
+ &heap_data->base, heap_data->size);
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 9d1e90e..2ab2ed6 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -189,8 +189,8 @@
*/
struct mem_map_data {
struct rb_node node;
- unsigned long addr;
- unsigned long addr_end;
+ ion_phys_addr_t addr;
+ ion_phys_addr_t addr_end;
unsigned long size;
const char *client_name;
};
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 7840d87..bd27385 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -172,7 +172,7 @@
}
EXPORT_SYMBOL(msm_ion_do_cache_op);
-static unsigned long msm_ion_get_base(unsigned long size, int memory_type,
+static ion_phys_addr_t msm_ion_get_base(unsigned long size, int memory_type,
unsigned int align)
{
switch (memory_type) {
@@ -340,10 +340,10 @@
static int is_heap_overlapping(const struct ion_platform_heap *heap1,
const struct ion_platform_heap *heap2)
{
- unsigned long heap1_base = heap1->base;
- unsigned long heap2_base = heap2->base;
- unsigned long heap1_end = heap1->base + heap1->size - 1;
- unsigned long heap2_end = heap2->base + heap2->size - 1;
+ ion_phys_addr_t heap1_base = heap1->base;
+ ion_phys_addr_t heap2_base = heap2->base;
+ ion_phys_addr_t heap1_end = heap1->base + heap1->size - 1;
+ ion_phys_addr_t heap2_end = heap2->base + heap2->size - 1;
if (heap1_base == heap2_base)
return 1;
@@ -792,9 +792,9 @@
continue;
} else {
if (heap_data->size)
- pr_info("ION heap %s created at %lx "
+ pr_info("ION heap %s created at %pa "
"with size %x\n", heap_data->name,
- heap_data->base,
+ &heap_data->base,
heap_data->size);
else
pr_info("ION heap %s created\n",
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index c2b5f38..51ffd21 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -586,12 +586,16 @@
return 0;
}
-static int epm_psoc_scale_result(uint32_t result, uint32_t index)
+static int epm_psoc_scale_result(int16_t result, uint32_t index)
{
struct epm_adc_drv *epm_adc = epm_adc_drv;
- int32_t result_cur;
+ int32_t result_cur, neg = 0;
if ((1 << index) & epm_adc->channel_mask) {
+ if (result & 0x800) {
+ neg = 1;
+ result = result & 0x7ff;
+ }
/* result = (2.048V * code)/(4096 * gain * rsense) */
result_cur = ((EPM_PSOC_VREF_VOLTAGE * result)/
EPM_PSOC_MAX_ADC_CODE_12_BIT);
@@ -599,14 +603,22 @@
result_cur = (result_cur/
(epm_adc->epm_psoc_ch_prop[index].gain *
epm_adc->epm_psoc_ch_prop[index].resistorvalue));
+ if (neg)
+ result_cur -= result_cur;
} else {
+ if (result & 0x8000) {
+ neg = 1;
+ result = result & 0x7fff;
+ }
/* result = (2.048V * code)/(32767 * gain * rsense) */
- result_cur = (((EPM_PSOC_VREF_VOLTAGE * result)/
+ result_cur = (((EPM_PSOC_VREF_VOLTAGE * (int) result)/
EPM_PSOC_MAX_ADC_CODE_15_BIT) * 1000);
result_cur = (result_cur/
(epm_adc->epm_psoc_ch_prop[index].gain *
epm_adc->epm_psoc_ch_prop[index].resistorvalue));
+ if (neg)
+ result_cur -= result_cur;
}
return result_cur;
@@ -869,10 +881,8 @@
psoc_get_meas->timestamp_resp_value = (rx_buf[3] << 24) |
(rx_buf[4] << 16) | (rx_buf[5] << 8) |
rx_buf[6];
- psoc_get_meas->reading_value = (rx_buf[7] << 8) | rx_buf[8];
+ psoc_get_meas->reading_raw = (rx_buf[7] << 8) | rx_buf[8];
- pr_debug("dev_num:%d, chan_num:%d\n", rx_buf[1], rx_buf[2]);
- pr_debug("data %d\n", psoc_get_meas->reading_value);
return rc;
}
@@ -1336,7 +1346,7 @@
}
psoc_get_data.reading_value = epm_psoc_scale_result(
- psoc_get_data.reading_value,
+ psoc_get_data.reading_raw,
psoc_get_data.chan_num);
if (copy_to_user((void __user *)arg, &psoc_get_data,
@@ -1753,8 +1763,6 @@
conv.device_idx = attr->index / pdata->chan_per_adc;
conv.channel_idx = attr->index % pdata->chan_per_adc;
conv.physical = 0;
- pr_info("%s: device_idx=%d channel_idx=%d", __func__, conv.device_idx,
- conv.channel_idx);
if (!epm_adc_expander_register) {
rc = epm_adc_i2c_expander_register();
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4c72b65..bfa48de 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -411,13 +411,6 @@
To compile this driver as a module, choose M here; the
module will be called opencores-kbd.
-config KEYBOARD_PM8058
- bool "Qualcomm PM8058 Matrix Keypad support"
- depends on PM8058
- help
- Say Y here to enable the driver for the keypad matrix interface
- on the Qualcomm PM8058 power management I/C device.
-
config KEYBOARD_PXA27x
tristate "PXA27x/PXA3xx keypad support"
depends on PXA27x || PXA3xx || ARCH_MMP
@@ -623,5 +616,3 @@
module will be called w90p910_keypad.
endif
-
-
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 833904a..85f1d86 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -54,4 +54,3 @@
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_QCIKBD) += qci_kbd.o
obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
-obj-$(CONFIG_KEYBOARD_PMIC8058) += pmic8058-keypad.o
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index ad43bbf..1f309d8 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -17,7 +17,6 @@
obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
-obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_TMG) += cy8c_tmg_ts.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
@@ -29,7 +28,6 @@
obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
-obj-$(CONFIG_TOUCHSCREEN_ELAN_I2C_8232) += elan8232_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 26e8496..f13e55a 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -195,23 +195,6 @@
To compile this driver as a module, choose M here: the
module will be called leds-msm-tricolor.
-config LEDS_GPIO_PLATFORM
- bool "Platform device bindings for GPIO LEDs"
- depends on LEDS_GPIO
- default y
- help
- Let the leds-gpio driver drive LEDs which have been defined as
- platform devices. If you don't know what this means, say yes.
-
-config LEDS_GPIO_OF
- bool "OpenFirmware platform device bindings for GPIO LEDs"
- depends on LEDS_GPIO && OF_DEVICE
- default y
- help
- Let the leds-gpio driver drive LEDs which have been defined as
- of_platform devices. For instance, LEDs which are listed in a "dts"
- file.
-
config LEDS_LP3944
tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
depends on LEDS_CLASS
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index da5db8b..d749d92 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -42,7 +42,7 @@
unsigned int idx_in;
unsigned int idx_out;
sector_t sector;
- atomic_t cc_pending;
+ atomic_t pending;
struct ablkcipher_request *req;
};
@@ -56,7 +56,7 @@
struct convert_context ctx;
- atomic_t io_pending;
+ atomic_t pending;
int error;
sector_t sector;
struct dm_crypt_io *base_io;
@@ -740,14 +740,14 @@
{
int r;
- atomic_set(&ctx->cc_pending, 1);
+ atomic_set(&ctx->pending, 1);
while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
ctx->idx_out < ctx->bio_out->bi_vcnt) {
crypt_alloc_req(cc, ctx);
- atomic_inc(&ctx->cc_pending);
+ atomic_inc(&ctx->pending);
r = crypt_convert_block(cc, ctx, ctx->req);
@@ -764,14 +764,14 @@
/* sync */
case 0:
- atomic_dec(&ctx->cc_pending);
+ atomic_dec(&ctx->pending);
ctx->sector++;
cond_resched();
continue;
/* error */
default:
- atomic_dec(&ctx->cc_pending);
+ atomic_dec(&ctx->pending);
return r;
}
}
@@ -868,14 +868,14 @@
io->error = 0;
io->base_io = NULL;
io->ctx.req = NULL;
- atomic_set(&io->io_pending, 0);
+ atomic_set(&io->pending, 0);
return io;
}
static void crypt_inc_pending(struct dm_crypt_io *io)
{
- atomic_inc(&io->io_pending);
+ atomic_inc(&io->pending);
}
/*
@@ -890,7 +890,7 @@
struct dm_crypt_io *base_io = io->base_io;
int error = io->error;
- if (!atomic_dec_and_test(&io->io_pending))
+ if (!atomic_dec_and_test(&io->pending))
return;
if (io->ctx.req)
@@ -1080,7 +1080,8 @@
r = crypt_convert(cc, &io->ctx);
if (r < 0)
io->error = -EIO;
- crypt_finished = atomic_dec_and_test(&io->ctx.cc_pending);
+
+ crypt_finished = atomic_dec_and_test(&io->ctx.pending);
/* Encryption was already finished, submit io now */
if (crypt_finished) {
@@ -1151,11 +1152,10 @@
io->sector);
r = crypt_convert(cc, &io->ctx);
-
if (r < 0)
io->error = -EIO;
- if (atomic_dec_and_test(&io->ctx.cc_pending))
+ if (atomic_dec_and_test(&io->ctx.pending))
kcryptd_crypt_read_done(io);
crypt_dec_pending(io);
@@ -1182,7 +1182,7 @@
mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
- if (!atomic_dec_and_test(&ctx->cc_pending))
+ if (!atomic_dec_and_test(&ctx->pending))
return;
if (bio_data_dir(io->base_bio) == READ)
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 5a61c5f..754f38f 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -770,11 +770,6 @@
if (!argc)
return 0;
- if (argc > as->argc) {
- ti->error = "not enough arguments for features";
- return -EINVAL;
- }
-
do {
arg_name = dm_shift_arg(as);
argc--;
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index ce65e3f..c99bed1 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -58,11 +58,8 @@
obj-$(CONFIG_TIMPANI_CODEC) += timpani-codec.o
-ifdef CONFIG_TIMPANI_CODEC
obj-$(CONFIG_TIMPANI_CODEC) += msm-adie-codec.o
-else ifdef CONFIG_MARIMBA_CODEC
obj-$(CONFIG_MARIMBA_CODEC) += msm-adie-codec.o
-endif
obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o
@@ -127,6 +124,10 @@
obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o
obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o
+obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
+obj-$(CONFIG_MFD_PM8821_CORE) += pm8821-core.o
+obj-$(CONFIG_MFD_PM8018_CORE) += pm8018-core.o
+obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_TPS65090) += tps65090.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
@@ -135,11 +136,7 @@
obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o
obj-$(CONFIG_PMIC8058) += pmic8058.o
obj-$(CONFIG_PMIC8901) += pmic8901.o
-obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
-obj-$(CONFIG_MFD_PM8821_CORE) += pm8821-core.o
-obj-$(CONFIG_MFD_PM8018_CORE) += pm8018-core.o
obj-$(CONFIG_MFD_PM8038_CORE) += pm8038-core.o
-obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
obj-$(CONFIG_MFD_PM8821_IRQ) += pm8821-irq.o
obj-$(CONFIG_MFD_PM8XXX_DEBUG) += pm8xxx-debug.o
obj-$(CONFIG_MFD_PM8XXX_PWM) += pm8xxx-pwm.o
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b0222ec..f80f3f2 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -54,8 +54,6 @@
obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o
obj-$(CONFIG_WL127X_RFKILL) += wl127x-rfkill.o
obj-$(CONFIG_SENSORS_AK8975) += akm8975.o
-obj-$(CONFIG_WL127X_RFKILL) += wl127x-rfkill.o
-obj-$(CONFIG_SENSORS_AK8975) += akm8975.o
obj-$(CONFIG_TSIF) += msm_tsif.o
msm_tsif-objs := tsif.o
obj-$(CONFIG_TSIF_CHRDEV) += tsif_chrdev.o
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 07702b4..bea8428 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1023,7 +1023,7 @@
if (host->areq)
mmc_post_req(host, host->areq->mrq, 0);
- /* Cancel a prepared request if it was not started. */
+ /* Cancel a prepared request if it was not started. */
if ((err || start_err) && areq)
mmc_post_req(host, areq->mrq, -EINVAL);
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index fca3274..3d8ceb4 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -215,14 +215,14 @@
card->sdio_single_irq = NULL;
if ((card->host->caps & MMC_CAP_SDIO_IRQ) &&
- card->host->sdio_irqs == 1)
+ card->host->sdio_irqs == 1)
for (i = 0; i < card->sdio_funcs; i++) {
- func = card->sdio_func[i];
- if (func && func->irq_handler) {
- card->sdio_single_irq = func;
- break;
- }
- }
+ func = card->sdio_func[i];
+ if (func && func->irq_handler) {
+ card->sdio_single_irq = func;
+ break;
+ }
+ }
}
/**
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 315efbb..47b19c0 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3219,44 +3219,6 @@
}
EXPORT_SYMBOL(nand_scan_ident);
-static void nand_panic_wait(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
- int i;
-
- if (chip->state != FL_READY)
- for (i = 0; i < 40; i++) {
- if (chip->dev_ready(mtd))
- break;
- mdelay(10);
- }
- chip->state = FL_READY;
-}
-
-static int nand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
-{
- struct nand_chip *chip = mtd->priv;
- int ret;
-
- /* Do not allow reads past end of device */
- if ((to + len) > mtd->size)
- return -EINVAL;
- if (!len)
- return 0;
-
- nand_panic_wait(mtd);
-
- chip->ops.len = len;
- chip->ops.datbuf = (uint8_t *)buf;
- chip->ops.oobbuf = NULL;
-
- ret = nand_do_write_ops(mtd, to, &chip->ops);
-
- *retlen = chip->ops.retlen;
- return ret;
-}
-
/**
* nand_scan_tail - [NAND Interface] Scan for the NAND device
diff --git a/drivers/net/pppolac.c b/drivers/net/pppolac.c
deleted file mode 100644
index a5d3d63..0000000
--- a/drivers/net/pppolac.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/* drivers/net/pppolac.c
- *
- * Driver for PPP on L2TP Access Concentrator / PPPoLAC Socket (RFC 2661)
- *
- * Copyright (C) 2009 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-/* This driver handles L2TP data packets between a UDP socket and a PPP channel.
- * The socket must keep connected, and only one session per socket is permitted.
- * Sequencing of outgoing packets is controlled by LNS. Incoming packets with
- * sequences are reordered within a sliding window of one second. Currently
- * reordering only happens when a packet is received. It is done for simplicity
- * since no additional locks or threads are required. This driver only works on
- * IPv4 due to the lack of UDP encapsulation support in IPv6. */
-
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/workqueue.h>
-#include <linux/skbuff.h>
-#include <linux/file.h>
-#include <linux/netdevice.h>
-#include <linux/net.h>
-#include <linux/udp.h>
-#include <linux/ppp_defs.h>
-#include <linux/if_ppp.h>
-#include <linux/if_pppox.h>
-#include <linux/ppp_channel.h>
-#include <net/tcp_states.h>
-#include <asm/uaccess.h>
-
-#define L2TP_CONTROL_BIT 0x80
-#define L2TP_LENGTH_BIT 0x40
-#define L2TP_SEQUENCE_BIT 0x08
-#define L2TP_OFFSET_BIT 0x02
-#define L2TP_VERSION 0x02
-#define L2TP_VERSION_MASK 0x0F
-
-#define PPP_ADDR 0xFF
-#define PPP_CTRL 0x03
-
-union unaligned {
- __u32 u32;
-} __attribute__((packed));
-
-static inline union unaligned *unaligned(void *ptr)
-{
- return (union unaligned *)ptr;
-}
-
-struct meta {
- __u32 sequence;
- __u32 timestamp;
-};
-
-static inline struct meta *skb_meta(struct sk_buff *skb)
-{
- return (struct meta *)skb->cb;
-}
-
-/******************************************************************************/
-
-static int pppolac_recv_core(struct sock *sk_udp, struct sk_buff *skb)
-{
- struct sock *sk = (struct sock *)sk_udp->sk_user_data;
- struct pppolac_opt *opt = &pppox_sk(sk)->proto.lac;
- struct meta *meta = skb_meta(skb);
- __u32 now = jiffies;
- __u8 bits;
- __u8 *ptr;
-
- /* Drop the packet if L2TP header is missing. */
- if (skb->len < sizeof(struct udphdr) + 6)
- goto drop;
-
- /* Put it back if it is a control packet. */
- if (skb->data[sizeof(struct udphdr)] & L2TP_CONTROL_BIT)
- return opt->backlog_rcv(sk_udp, skb);
-
- /* Skip UDP header. */
- skb_pull(skb, sizeof(struct udphdr));
-
- /* Check the version. */
- if ((skb->data[1] & L2TP_VERSION_MASK) != L2TP_VERSION)
- goto drop;
- bits = skb->data[0];
- ptr = &skb->data[2];
-
- /* Check the length if it is present. */
- if (bits & L2TP_LENGTH_BIT) {
- if ((ptr[0] << 8 | ptr[1]) != skb->len)
- goto drop;
- ptr += 2;
- }
-
- /* Skip all fields including optional ones. */
- if (!skb_pull(skb, 6 + (bits & L2TP_SEQUENCE_BIT ? 4 : 0) +
- (bits & L2TP_LENGTH_BIT ? 2 : 0) +
- (bits & L2TP_OFFSET_BIT ? 2 : 0)))
- goto drop;
-
- /* Skip the offset padding if it is present. */
- if (bits & L2TP_OFFSET_BIT &&
- !skb_pull(skb, skb->data[-2] << 8 | skb->data[-1]))
- goto drop;
-
- /* Check the tunnel and the session. */
- if (unaligned(ptr)->u32 != opt->local)
- goto drop;
-
- /* Check the sequence if it is present. */
- if (bits & L2TP_SEQUENCE_BIT) {
- meta->sequence = ptr[4] << 8 | ptr[5];
- if ((__s16)(meta->sequence - opt->recv_sequence) < 0)
- goto drop;
- }
-
- /* Skip PPP address and control if they are present. */
- if (skb->len >= 2 && skb->data[0] == PPP_ADDR &&
- skb->data[1] == PPP_CTRL)
- skb_pull(skb, 2);
-
- /* Fix PPP protocol if it is compressed. */
- if (skb->len >= 1 && skb->data[0] & 1)
- skb_push(skb, 1)[0] = 0;
-
- /* Drop the packet if PPP protocol is missing. */
- if (skb->len < 2)
- goto drop;
-
- /* Perform reordering if sequencing is enabled. */
- atomic_set(&opt->sequencing, bits & L2TP_SEQUENCE_BIT);
- if (bits & L2TP_SEQUENCE_BIT) {
- struct sk_buff *skb1;
-
- /* Insert the packet into receive queue in order. */
- skb_set_owner_r(skb, sk);
- skb_queue_walk(&sk->sk_receive_queue, skb1) {
- struct meta *meta1 = skb_meta(skb1);
- __s16 order = meta->sequence - meta1->sequence;
- if (order == 0)
- goto drop;
- if (order < 0) {
- meta->timestamp = meta1->timestamp;
- skb_insert(skb1, skb, &sk->sk_receive_queue);
- skb = NULL;
- break;
- }
- }
- if (skb) {
- meta->timestamp = now;
- skb_queue_tail(&sk->sk_receive_queue, skb);
- }
-
- /* Remove packets from receive queue as long as
- * 1. the receive buffer is full,
- * 2. they are queued longer than one second, or
- * 3. there are no missing packets before them. */
- skb_queue_walk_safe(&sk->sk_receive_queue, skb, skb1) {
- meta = skb_meta(skb);
- if (atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf &&
- now - meta->timestamp < HZ &&
- meta->sequence != opt->recv_sequence)
- break;
- skb_unlink(skb, &sk->sk_receive_queue);
- opt->recv_sequence = (__u16)(meta->sequence + 1);
- skb_orphan(skb);
- ppp_input(&pppox_sk(sk)->chan, skb);
- }
- return NET_RX_SUCCESS;
- }
-
- /* Flush receive queue if sequencing is disabled. */
- skb_queue_purge(&sk->sk_receive_queue);
- skb_orphan(skb);
- ppp_input(&pppox_sk(sk)->chan, skb);
- return NET_RX_SUCCESS;
-drop:
- kfree_skb(skb);
- return NET_RX_DROP;
-}
-
-static int pppolac_recv(struct sock *sk_udp, struct sk_buff *skb)
-{
- sock_hold(sk_udp);
- sk_receive_skb(sk_udp, skb, 0);
- return 0;
-}
-
-static struct sk_buff_head delivery_queue;
-
-static void pppolac_xmit_core(struct work_struct *delivery_work)
-{
- mm_segment_t old_fs = get_fs();
- struct sk_buff *skb;
-
- set_fs(KERNEL_DS);
- while ((skb = skb_dequeue(&delivery_queue))) {
- struct sock *sk_udp = skb->sk;
- struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
- struct msghdr msg = {
- .msg_iov = (struct iovec *)&iov,
- .msg_iovlen = 1,
- .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
- };
- sk_udp->sk_prot->sendmsg(NULL, sk_udp, &msg, skb->len);
- kfree_skb(skb);
- }
- set_fs(old_fs);
-}
-
-static DECLARE_WORK(delivery_work, pppolac_xmit_core);
-
-static int pppolac_xmit(struct ppp_channel *chan, struct sk_buff *skb)
-{
- struct sock *sk_udp = (struct sock *)chan->private;
- struct pppolac_opt *opt = &pppox_sk(sk_udp->sk_user_data)->proto.lac;
-
- /* Install PPP address and control. */
- skb_push(skb, 2);
- skb->data[0] = PPP_ADDR;
- skb->data[1] = PPP_CTRL;
-
- /* Install L2TP header. */
- if (atomic_read(&opt->sequencing)) {
- skb_push(skb, 10);
- skb->data[0] = L2TP_SEQUENCE_BIT;
- skb->data[6] = opt->xmit_sequence >> 8;
- skb->data[7] = opt->xmit_sequence;
- skb->data[8] = 0;
- skb->data[9] = 0;
- opt->xmit_sequence++;
- } else {
- skb_push(skb, 6);
- skb->data[0] = 0;
- }
- skb->data[1] = L2TP_VERSION;
- unaligned(&skb->data[2])->u32 = opt->remote;
-
- /* Now send the packet via the delivery queue. */
- skb_set_owner_w(skb, sk_udp);
- skb_queue_tail(&delivery_queue, skb);
- schedule_work(&delivery_work);
- return 1;
-}
-
-/******************************************************************************/
-
-static struct ppp_channel_ops pppolac_channel_ops = {
- .start_xmit = pppolac_xmit,
-};
-
-static int pppolac_connect(struct socket *sock, struct sockaddr *useraddr,
- int addrlen, int flags)
-{
- struct sock *sk = sock->sk;
- struct pppox_sock *po = pppox_sk(sk);
- struct sockaddr_pppolac *addr = (struct sockaddr_pppolac *)useraddr;
- struct socket *sock_udp = NULL;
- struct sock *sk_udp;
- int error;
-
- if (addrlen != sizeof(struct sockaddr_pppolac) ||
- !addr->local.tunnel || !addr->local.session ||
- !addr->remote.tunnel || !addr->remote.session) {
- return -EINVAL;
- }
-
- lock_sock(sk);
- error = -EALREADY;
- if (sk->sk_state != PPPOX_NONE)
- goto out;
-
- sock_udp = sockfd_lookup(addr->udp_socket, &error);
- if (!sock_udp)
- goto out;
- sk_udp = sock_udp->sk;
- lock_sock(sk_udp);
-
- /* Remove this check when IPv6 supports UDP encapsulation. */
- error = -EAFNOSUPPORT;
- if (sk_udp->sk_family != AF_INET)
- goto out;
- error = -EPROTONOSUPPORT;
- if (sk_udp->sk_protocol != IPPROTO_UDP)
- goto out;
- error = -EDESTADDRREQ;
- if (sk_udp->sk_state != TCP_ESTABLISHED)
- goto out;
- error = -EBUSY;
- if (udp_sk(sk_udp)->encap_type || sk_udp->sk_user_data)
- goto out;
- if (!sk_udp->sk_bound_dev_if) {
- struct dst_entry *dst = sk_dst_get(sk_udp);
- error = -ENODEV;
- if (!dst)
- goto out;
- sk_udp->sk_bound_dev_if = dst->dev->ifindex;
- dst_release(dst);
- }
-
- po->chan.hdrlen = 12;
- po->chan.private = sk_udp;
- po->chan.ops = &pppolac_channel_ops;
- po->chan.mtu = PPP_MRU - 80;
- po->proto.lac.local = unaligned(&addr->local)->u32;
- po->proto.lac.remote = unaligned(&addr->remote)->u32;
- atomic_set(&po->proto.lac.sequencing, 1);
- po->proto.lac.backlog_rcv = sk_udp->sk_backlog_rcv;
-
- error = ppp_register_channel(&po->chan);
- if (error)
- goto out;
-
- sk->sk_state = PPPOX_CONNECTED;
- udp_sk(sk_udp)->encap_type = UDP_ENCAP_L2TPINUDP;
- udp_sk(sk_udp)->encap_rcv = pppolac_recv;
- sk_udp->sk_backlog_rcv = pppolac_recv_core;
- sk_udp->sk_user_data = sk;
-out:
- if (sock_udp) {
- release_sock(sk_udp);
- if (error)
- sockfd_put(sock_udp);
- }
- release_sock(sk);
- return error;
-}
-
-static int pppolac_release(struct socket *sock)
-{
- struct sock *sk = sock->sk;
-
- if (!sk)
- return 0;
-
- lock_sock(sk);
- if (sock_flag(sk, SOCK_DEAD)) {
- release_sock(sk);
- return -EBADF;
- }
-
- if (sk->sk_state != PPPOX_NONE) {
- struct sock *sk_udp = (struct sock *)pppox_sk(sk)->chan.private;
- lock_sock(sk_udp);
- skb_queue_purge(&sk->sk_receive_queue);
- pppox_unbind_sock(sk);
- udp_sk(sk_udp)->encap_type = 0;
- udp_sk(sk_udp)->encap_rcv = NULL;
- sk_udp->sk_backlog_rcv = pppox_sk(sk)->proto.lac.backlog_rcv;
- sk_udp->sk_user_data = NULL;
- release_sock(sk_udp);
- sockfd_put(sk_udp->sk_socket);
- }
-
- sock_orphan(sk);
- sock->sk = NULL;
- release_sock(sk);
- sock_put(sk);
- return 0;
-}
-
-/******************************************************************************/
-
-static struct proto pppolac_proto = {
- .name = "PPPOLAC",
- .owner = THIS_MODULE,
- .obj_size = sizeof(struct pppox_sock),
-};
-
-static struct proto_ops pppolac_proto_ops = {
- .family = PF_PPPOX,
- .owner = THIS_MODULE,
- .release = pppolac_release,
- .bind = sock_no_bind,
- .connect = pppolac_connect,
- .socketpair = sock_no_socketpair,
- .accept = sock_no_accept,
- .getname = sock_no_getname,
- .poll = sock_no_poll,
- .ioctl = pppox_ioctl,
- .listen = sock_no_listen,
- .shutdown = sock_no_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .sendmsg = sock_no_sendmsg,
- .recvmsg = sock_no_recvmsg,
- .mmap = sock_no_mmap,
-};
-
-static int pppolac_create(struct net *net, struct socket *sock)
-{
- struct sock *sk;
-
- sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppolac_proto);
- if (!sk)
- return -ENOMEM;
-
- sock_init_data(sock, sk);
- sock->state = SS_UNCONNECTED;
- sock->ops = &pppolac_proto_ops;
- sk->sk_protocol = PX_PROTO_OLAC;
- sk->sk_state = PPPOX_NONE;
- return 0;
-}
-
-/******************************************************************************/
-
-static struct pppox_proto pppolac_pppox_proto = {
- .create = pppolac_create,
- .owner = THIS_MODULE,
-};
-
-static int __init pppolac_init(void)
-{
- int error;
-
- error = proto_register(&pppolac_proto, 0);
- if (error)
- return error;
-
- error = register_pppox_proto(PX_PROTO_OLAC, &pppolac_pppox_proto);
- if (error)
- proto_unregister(&pppolac_proto);
- else
- skb_queue_head_init(&delivery_queue);
- return error;
-}
-
-static void __exit pppolac_exit(void)
-{
- unregister_pppox_proto(PX_PROTO_OLAC);
- proto_unregister(&pppolac_proto);
-}
-
-module_init(pppolac_init);
-module_exit(pppolac_exit);
-
-MODULE_DESCRIPTION("PPP on L2TP Access Concentrator (PPPoLAC)");
-MODULE_AUTHOR("Chia-chi Yeh <chiachi@android.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/pppopns.c b/drivers/net/pppopns.c
deleted file mode 100644
index 6016d29..0000000
--- a/drivers/net/pppopns.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/* drivers/net/pppopns.c
- *
- * Driver for PPP on PPTP Network Server / PPPoPNS Socket (RFC 2637)
- *
- * Copyright (C) 2009 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-/* This driver handles PPTP data packets between a RAW socket and a PPP channel.
- * The socket is created in the kernel space and connected to the same address
- * of the control socket. Outgoing packets are always sent with sequences but
- * without acknowledgements. Incoming packets with sequences are reordered
- * within a sliding window of one second. Currently reordering only happens when
- * a packet is received. It is done for simplicity since no additional locks or
- * threads are required. This driver should work on both IPv4 and IPv6. */
-
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/workqueue.h>
-#include <linux/skbuff.h>
-#include <linux/file.h>
-#include <linux/netdevice.h>
-#include <linux/net.h>
-#include <linux/ppp_defs.h>
-#include <linux/if.h>
-#include <linux/if_ppp.h>
-#include <linux/if_pppox.h>
-#include <linux/ppp_channel.h>
-#include <asm/uaccess.h>
-
-#define GRE_HEADER_SIZE 8
-
-#define PPTP_GRE_BITS htons(0x2001)
-#define PPTP_GRE_BITS_MASK htons(0xEF7F)
-#define PPTP_GRE_SEQ_BIT htons(0x1000)
-#define PPTP_GRE_ACK_BIT htons(0x0080)
-#define PPTP_GRE_TYPE htons(0x880B)
-
-#define PPP_ADDR 0xFF
-#define PPP_CTRL 0x03
-
-struct header {
- __u16 bits;
- __u16 type;
- __u16 length;
- __u16 call;
- __u32 sequence;
-} __attribute__((packed));
-
-struct meta {
- __u32 sequence;
- __u32 timestamp;
-};
-
-static inline struct meta *skb_meta(struct sk_buff *skb)
-{
- return (struct meta *)skb->cb;
-}
-
-/******************************************************************************/
-
-static int pppopns_recv_core(struct sock *sk_raw, struct sk_buff *skb)
-{
- struct sock *sk = (struct sock *)sk_raw->sk_user_data;
- struct pppopns_opt *opt = &pppox_sk(sk)->proto.pns;
- struct meta *meta = skb_meta(skb);
- __u32 now = jiffies;
- struct header *hdr;
-
- /* Skip transport header */
- skb_pull(skb, skb_transport_header(skb) - skb->data);
-
- /* Drop the packet if GRE header is missing. */
- if (skb->len < GRE_HEADER_SIZE)
- goto drop;
- hdr = (struct header *)skb->data;
-
- /* Check the header. */
- if (hdr->type != PPTP_GRE_TYPE || hdr->call != opt->local ||
- (hdr->bits & PPTP_GRE_BITS_MASK) != PPTP_GRE_BITS)
- goto drop;
-
- /* Skip all fields including optional ones. */
- if (!skb_pull(skb, GRE_HEADER_SIZE +
- (hdr->bits & PPTP_GRE_SEQ_BIT ? 4 : 0) +
- (hdr->bits & PPTP_GRE_ACK_BIT ? 4 : 0)))
- goto drop;
-
- /* Check the length. */
- if (skb->len != ntohs(hdr->length))
- goto drop;
-
- /* Check the sequence if it is present. */
- if (hdr->bits & PPTP_GRE_SEQ_BIT) {
- meta->sequence = ntohl(hdr->sequence);
- if ((__s32)(meta->sequence - opt->recv_sequence) < 0)
- goto drop;
- }
-
- /* Skip PPP address and control if they are present. */
- if (skb->len >= 2 && skb->data[0] == PPP_ADDR &&
- skb->data[1] == PPP_CTRL)
- skb_pull(skb, 2);
-
- /* Fix PPP protocol if it is compressed. */
- if (skb->len >= 1 && skb->data[0] & 1)
- skb_push(skb, 1)[0] = 0;
-
- /* Drop the packet if PPP protocol is missing. */
- if (skb->len < 2)
- goto drop;
-
- /* Perform reordering if sequencing is enabled. */
- if (hdr->bits & PPTP_GRE_SEQ_BIT) {
- struct sk_buff *skb1;
-
- /* Insert the packet into receive queue in order. */
- skb_set_owner_r(skb, sk);
- skb_queue_walk(&sk->sk_receive_queue, skb1) {
- struct meta *meta1 = skb_meta(skb1);
- __s32 order = meta->sequence - meta1->sequence;
- if (order == 0)
- goto drop;
- if (order < 0) {
- meta->timestamp = meta1->timestamp;
- skb_insert(skb1, skb, &sk->sk_receive_queue);
- skb = NULL;
- break;
- }
- }
- if (skb) {
- meta->timestamp = now;
- skb_queue_tail(&sk->sk_receive_queue, skb);
- }
-
- /* Remove packets from receive queue as long as
- * 1. the receive buffer is full,
- * 2. they are queued longer than one second, or
- * 3. there are no missing packets before them. */
- skb_queue_walk_safe(&sk->sk_receive_queue, skb, skb1) {
- meta = skb_meta(skb);
- if (atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf &&
- now - meta->timestamp < HZ &&
- meta->sequence != opt->recv_sequence)
- break;
- skb_unlink(skb, &sk->sk_receive_queue);
- opt->recv_sequence = meta->sequence + 1;
- skb_orphan(skb);
- ppp_input(&pppox_sk(sk)->chan, skb);
- }
- return NET_RX_SUCCESS;
- }
-
- /* Flush receive queue if sequencing is disabled. */
- skb_queue_purge(&sk->sk_receive_queue);
- skb_orphan(skb);
- ppp_input(&pppox_sk(sk)->chan, skb);
- return NET_RX_SUCCESS;
-drop:
- kfree_skb(skb);
- return NET_RX_DROP;
-}
-
-static void pppopns_recv(struct sock *sk_raw, int length)
-{
- struct sk_buff *skb;
- while ((skb = skb_dequeue(&sk_raw->sk_receive_queue))) {
- sock_hold(sk_raw);
- sk_receive_skb(sk_raw, skb, 0);
- }
-}
-
-static struct sk_buff_head delivery_queue;
-
-static void pppopns_xmit_core(struct work_struct *delivery_work)
-{
- mm_segment_t old_fs = get_fs();
- struct sk_buff *skb;
-
- set_fs(KERNEL_DS);
- while ((skb = skb_dequeue(&delivery_queue))) {
- struct sock *sk_raw = skb->sk;
- struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
- struct msghdr msg = {
- .msg_iov = (struct iovec *)&iov,
- .msg_iovlen = 1,
- .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
- };
- sk_raw->sk_prot->sendmsg(NULL, sk_raw, &msg, skb->len);
- kfree_skb(skb);
- }
- set_fs(old_fs);
-}
-
-static DECLARE_WORK(delivery_work, pppopns_xmit_core);
-
-static int pppopns_xmit(struct ppp_channel *chan, struct sk_buff *skb)
-{
- struct sock *sk_raw = (struct sock *)chan->private;
- struct pppopns_opt *opt = &pppox_sk(sk_raw->sk_user_data)->proto.pns;
- struct header *hdr;
- __u16 length;
-
- /* Install PPP address and control. */
- skb_push(skb, 2);
- skb->data[0] = PPP_ADDR;
- skb->data[1] = PPP_CTRL;
- length = skb->len;
-
- /* Install PPTP GRE header. */
- hdr = (struct header *)skb_push(skb, 12);
- hdr->bits = PPTP_GRE_BITS | PPTP_GRE_SEQ_BIT;
- hdr->type = PPTP_GRE_TYPE;
- hdr->length = htons(length);
- hdr->call = opt->remote;
- hdr->sequence = htonl(opt->xmit_sequence);
- opt->xmit_sequence++;
-
- /* Now send the packet via the delivery queue. */
- skb_set_owner_w(skb, sk_raw);
- skb_queue_tail(&delivery_queue, skb);
- schedule_work(&delivery_work);
- return 1;
-}
-
-/******************************************************************************/
-
-static struct ppp_channel_ops pppopns_channel_ops = {
- .start_xmit = pppopns_xmit,
-};
-
-static int pppopns_connect(struct socket *sock, struct sockaddr *useraddr,
- int addrlen, int flags)
-{
- struct sock *sk = sock->sk;
- struct pppox_sock *po = pppox_sk(sk);
- struct sockaddr_pppopns *addr = (struct sockaddr_pppopns *)useraddr;
- struct sockaddr_storage ss;
- struct socket *sock_tcp = NULL;
- struct socket *sock_raw = NULL;
- struct sock *sk_tcp;
- struct sock *sk_raw;
- int error;
-
- if (addrlen != sizeof(struct sockaddr_pppopns))
- return -EINVAL;
-
- lock_sock(sk);
- error = -EALREADY;
- if (sk->sk_state != PPPOX_NONE)
- goto out;
-
- sock_tcp = sockfd_lookup(addr->tcp_socket, &error);
- if (!sock_tcp)
- goto out;
- sk_tcp = sock_tcp->sk;
- error = -EPROTONOSUPPORT;
- if (sk_tcp->sk_protocol != IPPROTO_TCP)
- goto out;
- addrlen = sizeof(struct sockaddr_storage);
- error = kernel_getpeername(sock_tcp, (struct sockaddr *)&ss, &addrlen);
- if (error)
- goto out;
- if (!sk_tcp->sk_bound_dev_if) {
- struct dst_entry *dst = sk_dst_get(sk_tcp);
- error = -ENODEV;
- if (!dst)
- goto out;
- sk_tcp->sk_bound_dev_if = dst->dev->ifindex;
- dst_release(dst);
- }
-
- error = sock_create(ss.ss_family, SOCK_RAW, IPPROTO_GRE, &sock_raw);
- if (error)
- goto out;
- sk_raw = sock_raw->sk;
- sk_raw->sk_bound_dev_if = sk_tcp->sk_bound_dev_if;
- error = kernel_connect(sock_raw, (struct sockaddr *)&ss, addrlen, 0);
- if (error)
- goto out;
-
- po->chan.hdrlen = 14;
- po->chan.private = sk_raw;
- po->chan.ops = &pppopns_channel_ops;
- po->chan.mtu = PPP_MRU - 80;
- po->proto.pns.local = addr->local;
- po->proto.pns.remote = addr->remote;
- po->proto.pns.data_ready = sk_raw->sk_data_ready;
- po->proto.pns.backlog_rcv = sk_raw->sk_backlog_rcv;
-
- error = ppp_register_channel(&po->chan);
- if (error)
- goto out;
-
- sk->sk_state = PPPOX_CONNECTED;
- lock_sock(sk_raw);
- sk_raw->sk_data_ready = pppopns_recv;
- sk_raw->sk_backlog_rcv = pppopns_recv_core;
- sk_raw->sk_user_data = sk;
- release_sock(sk_raw);
-out:
- if (sock_tcp)
- sockfd_put(sock_tcp);
- if (error && sock_raw)
- sock_release(sock_raw);
- release_sock(sk);
- return error;
-}
-
-static int pppopns_release(struct socket *sock)
-{
- struct sock *sk = sock->sk;
-
- if (!sk)
- return 0;
-
- lock_sock(sk);
- if (sock_flag(sk, SOCK_DEAD)) {
- release_sock(sk);
- return -EBADF;
- }
-
- if (sk->sk_state != PPPOX_NONE) {
- struct sock *sk_raw = (struct sock *)pppox_sk(sk)->chan.private;
- lock_sock(sk_raw);
- skb_queue_purge(&sk->sk_receive_queue);
- pppox_unbind_sock(sk);
- sk_raw->sk_data_ready = pppox_sk(sk)->proto.pns.data_ready;
- sk_raw->sk_backlog_rcv = pppox_sk(sk)->proto.pns.backlog_rcv;
- sk_raw->sk_user_data = NULL;
- release_sock(sk_raw);
- sock_release(sk_raw->sk_socket);
- }
-
- sock_orphan(sk);
- sock->sk = NULL;
- release_sock(sk);
- sock_put(sk);
- return 0;
-}
-
-/******************************************************************************/
-
-static struct proto pppopns_proto = {
- .name = "PPPOPNS",
- .owner = THIS_MODULE,
- .obj_size = sizeof(struct pppox_sock),
-};
-
-static struct proto_ops pppopns_proto_ops = {
- .family = PF_PPPOX,
- .owner = THIS_MODULE,
- .release = pppopns_release,
- .bind = sock_no_bind,
- .connect = pppopns_connect,
- .socketpair = sock_no_socketpair,
- .accept = sock_no_accept,
- .getname = sock_no_getname,
- .poll = sock_no_poll,
- .ioctl = pppox_ioctl,
- .listen = sock_no_listen,
- .shutdown = sock_no_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .sendmsg = sock_no_sendmsg,
- .recvmsg = sock_no_recvmsg,
- .mmap = sock_no_mmap,
-};
-
-static int pppopns_create(struct net *net, struct socket *sock)
-{
- struct sock *sk;
-
- sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppopns_proto);
- if (!sk)
- return -ENOMEM;
-
- sock_init_data(sock, sk);
- sock->state = SS_UNCONNECTED;
- sock->ops = &pppopns_proto_ops;
- sk->sk_protocol = PX_PROTO_OPNS;
- sk->sk_state = PPPOX_NONE;
- return 0;
-}
-
-/******************************************************************************/
-
-static struct pppox_proto pppopns_pppox_proto = {
- .create = pppopns_create,
- .owner = THIS_MODULE,
-};
-
-static int __init pppopns_init(void)
-{
- int error;
-
- error = proto_register(&pppopns_proto, 0);
- if (error)
- return error;
-
- error = register_pppox_proto(PX_PROTO_OPNS, &pppopns_pppox_proto);
- if (error)
- proto_unregister(&pppopns_proto);
- else
- skb_queue_head_init(&delivery_queue);
- return error;
-}
-
-static void __exit pppopns_exit(void)
-{
- unregister_pppox_proto(PX_PROTO_OPNS);
- proto_unregister(&pppopns_proto);
-}
-
-module_init(pppopns_init);
-module_exit(pppopns_exit);
-
-MODULE_DESCRIPTION("PPP on PPTP Network Server (PPPoPNS)");
-MODULE_AUTHOR("Chia-chi Yeh <chiachi@android.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 0d161b7..e42337f 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -294,6 +294,13 @@
help
Say Y to enable support for the battery in Qualcomm MSM.
+config BATTERY_MSM_FAKE
+ tristate "Fake MSM battery"
+ depends on ARCH_MSM && BATTERY_MSM
+ default n
+ help
+ Say Y to bypass actual battery queries.
+
config BATTERY_MSM8X60
tristate "MSM8X60 battery"
select PMIC8XXX_BATTALARM
@@ -365,13 +372,6 @@
The driver reports the charger status via the power supply framework.
A charger status change triggers an IRQ via the device STAT pin.
-config BATTERY_MSM_FAKE
- tristate "Fake MSM battery"
- depends on ARCH_MSM && BATTERY_MSM
- default n
- help
- Say Y to bypass actual battery queries.
-
config PM8058_FIX_USB
tristate "pmic8058 software workaround for usb removal"
depends on PMIC8058
@@ -396,13 +396,6 @@
help
Say Y here to enable support for batteries with BQ27520 (I2C) chips.
-config BATTERY_BQ27541
- tristate "BQ27541 battery driver"
- depends on I2C
- default n
- help
- Say Y here to enable support for batteries with BQ27541 (I2C) chips.
-
config BQ27520_TEST_ENABLE
bool "Enable BQ27520 Fuel Gauge Chip Test"
depends on BATTERY_BQ27520
@@ -410,6 +403,13 @@
help
Say Y here to enable Test sysfs Interface for BQ27520 Drivers.
+config BATTERY_BQ27541
+ tristate "BQ27541 battery driver"
+ depends on I2C
+ default n
+ help
+ Say Y here to enable support for batteries with BQ27541 (I2C) chips.
+
config BATTERY_BQ28400
tristate "BQ28400 battery driver"
depends on I2C
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 8f924d6..fe5af3a 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -436,4 +436,6 @@
comply with QPNP. QPNP is a SPMI based PMIC implementation. These
chips provide several different varieties of LDO and switching
regulators. They also provide voltage switches and boost regulators.
+
endif
+
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 054ce42..eb07c97 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -45,7 +45,6 @@
obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
-obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
obj-$(CONFIG_REGULATOR_PMIC8058) += pmic8058-regulator.o
obj-$(CONFIG_REGULATOR_PMIC8901) += pmic8901-regulator.o
obj-$(CONFIG_REGULATOR_MSM_GPIO) += msm-gpio-regulator.o
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 1849118..7a559a6 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -123,24 +123,6 @@
clock several times per second, please enable this option
only if you know that you really need it.
-config RTC_INTF_ALARM
- bool "Android alarm driver"
- depends on RTC_CLASS
- default y
- help
- Provides non-wakeup and rtc backed wakeup alarms based on rtc or
- elapsed realtime, and a non-wakeup alarm on the monotonic clock.
- Also provides an interface to set the wall time which must be used
- for elapsed realtime to work.
-
-config RTC_INTF_ALARM_DEV
- bool "Android alarm device"
- depends on RTC_INTF_ALARM
- default y
- help
- Exports the alarm interface to user-space.
-
-
config RTC_DRV_TEST
tristate "Test driver/device"
help
@@ -804,13 +786,6 @@
This driver can also be built as a module. If so, the module
will be called rtc-davinci.
-config RTC_DRV_MSM7X00A
- tristate "MSM7X00A"
- depends on ARCH_MSM
- default y
- help
- RTC driver for Qualcomm MSM7K chipsets
-
config RTC_DRV_OMAP
tristate "TI OMAP1"
depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX
@@ -1150,15 +1125,6 @@
This drive can also be built as a module. If so, the module
will be called rtc-puv3.
-config RTC_DRV_PM8XXX
- tristate "Qualcomm PMIC8XXX RTC"
- depends on MFD_PM8XXX
- help
- Say Y here if you want to support the Qualcomm PMIC8XXX RTC.
-
- To compile this driver as a module, choose M here: the
- module will be called rtc-pm8xxx.
-
config RTC_DRV_LOONGSON1
tristate "loongson1 RTC support"
depends on MACH_LOONGSON1
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 295f927..c6a0362 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -81,7 +81,6 @@
obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o
obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
-obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o
obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index bec0399..e9f056e 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -2568,11 +2568,12 @@
struct slim_pending_ch, pending);
struct slim_ich *slc = &ctrl->chans[pch->chan];
u32 sl = slc->seglen << slc->rootexp;
- if (revert) {
+ if (revert || slc->def > 0) {
if (slc->coeff == SLIM_COEFF_3)
sl *= 3;
ctrl->sched.usedslots += sl;
- slc->def = 1;
+ if (revert)
+ slc->def++;
slc->state = SLIM_CH_ACTIVE;
} else
slim_remove_ch(ctrl, slc);
@@ -2635,7 +2636,11 @@
/* Disconnect source port to free it up */
if (SLIM_HDL_TO_LA(slc->srch) == sb->laddr)
slc->srch = 0;
- if (slc->def != 0) {
+ /*
+ * If controller overrides BW allocation,
+ * delete this in remove channel itself
+ */
+ if (slc->def != 0 && !ctrl->allocbw) {
list_del(&pch->pending);
kfree(pch);
}
diff --git a/drivers/staging/ath6kl/os/linux/include/athendpack_linux.h b/drivers/staging/ath6kl/os/linux/include/athendpack_linux.h
deleted file mode 100644
index e69de29..0000000
--- a/drivers/staging/ath6kl/os/linux/include/athendpack_linux.h
+++ /dev/null
diff --git a/drivers/staging/ath6kl/os/linux/include/athstartpack_linux.h b/drivers/staging/ath6kl/os/linux/include/athstartpack_linux.h
deleted file mode 100644
index e69de29..0000000
--- a/drivers/staging/ath6kl/os/linux/include/athstartpack_linux.h
+++ /dev/null
diff --git a/drivers/staging/dream/Kconfig b/drivers/staging/dream/Kconfig
deleted file mode 100644
index 0c30b19..0000000
--- a/drivers/staging/dream/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-config DREAM
- tristate "HTC Dream support"
- depends on MACH_TROUT
-
-if DREAM
-
-source "drivers/staging/dream/camera/Kconfig"
-
-config INPUT_GPIO
- tristate "GPIO driver support"
- help
- Say Y here if you want to support gpio based keys, wheels etc...
-endif
diff --git a/drivers/staging/dream/Makefile b/drivers/staging/dream/Makefile
deleted file mode 100644
index fbea0ab..0000000
--- a/drivers/staging/dream/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-EXTRA_CFLAGS=-Idrivers/staging/dream/include
-obj-$(CONFIG_MSM_ADSP) += qdsp5/
-obj-$(CONFIG_MSM_CAMERA) += camera/
-obj-$(CONFIG_INPUT_GPIO) += gpio_axis.o gpio_event.o gpio_input.o gpio_matrix.o gpio_output.o
-
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 9274c17..5c8645a 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -988,14 +988,6 @@
Choose M here to compile it as a module. The module will be
called msm_serial_hs.
-config SERIAL_MSM_CLOCK_CONTROL
- bool "Allow tty clients to make clock requests to msm uarts."
- depends on SERIAL_MSM=y
- default y
- help
- Provides an interface for tty clients to request the msm uart clock
- to be turned on or off for power savings.
-
config SERIAL_MSM_RX_WAKEUP
bool "Wakeup the msm uart clock on GPIO activity."
depends on SERIAL_MSM_CLOCK_CONTROL
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 3e15ea7..fddb4fe 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -134,6 +134,8 @@
source "drivers/usb/musb/Kconfig"
+source "drivers/usb/renesas_usbhs/Kconfig"
+
source "drivers/usb/class/Kconfig"
source "drivers/usb/storage/Kconfig"
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 87a0078..5b97148 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2093,6 +2093,7 @@
bool audio_enabled = false;
static DEFINE_RATELIMIT_STATE(rl, 10*HZ, 1);
+
if (!cdev)
return -ENODEV;
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index ccede0c..569f200 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -3,12 +3,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
*/
#include <linux/module.h>
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 81fc1cc..e0255ce 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3280,6 +3280,7 @@
static int ci13xxx_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int ci13xxx_stop(struct usb_gadget_driver *driver);
+
/**
* Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o)
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 76028b2..3145418 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -137,10 +137,10 @@
#define CI13XXX_CONTROLLER_RESET_EVENT 0
#define CI13XXX_CONTROLLER_CONNECT_EVENT 1
#define CI13XXX_CONTROLLER_SUSPEND_EVENT 2
-#define CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT 3
-#define CI13XXX_CONTROLLER_RESUME_EVENT 4
-#define CI13XXX_CONTROLLER_DISCONNECT_EVENT 5
-#define CI13XXX_CONTROLLER_UDC_STARTED_EVENT 6
+#define CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT 3
+#define CI13XXX_CONTROLLER_RESUME_EVENT 4
+#define CI13XXX_CONTROLLER_DISCONNECT_EVENT 5
+#define CI13XXX_CONTROLLER_UDC_STARTED_EVENT 6
void (*notify_event) (struct ci13xxx *udc, unsigned event);
};
diff --git a/drivers/usb/gadget/qcom_maemo.c b/drivers/usb/gadget/qcom_maemo.c
deleted file mode 100644
index 2fb8be0..0000000
--- a/drivers/usb/gadget/qcom_maemo.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Qualcomm Maemo Composite driver
- *
- * Copyright (C) 2008 David Brownell
- * Copyright (C) 2008 Nokia Corporation
- * Copyright (C) 2009 Samsung Electronics
- * Copyright (c) 2010, The Linux Foundation. All rights reserved.
- *
- * This program from The Linux Foundation is free software; you can
- * redistribute it and/or modify it under the GNU General Public License
- * version 2 and only version 2 as published by the Free Software Foundation.
- * The original work available from [git.kernel.org ] is subject to the
- * notice below.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/utsname.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-
-
-#define DRIVER_DESC "Qcom Maemo Composite Gadget"
-#define VENDOR_ID 0x05c6
-#define PRODUCT_ID 0x902E
-
-/*
- * kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module. So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-
-#include "composite.c"
-#include "usbstring.c"
-#include "config.c"
-#include "epautoconf.c"
-
-#define USB_ETH
-
-#define USB_ETH_RNDIS
-#ifdef USB_ETH_RNDIS
-# include "f_rndis.c"
-# include "rndis.c"
-#endif
-
-
-#include "u_serial.c"
-#include "f_serial.c"
-
-#include "u_ether.c"
-
-#undef DBG /* u_ether.c has broken idea about macros */
-#undef VDBG /* so clean up after it */
-#undef ERROR
-#undef INFO
-
-#include "f_mass_storage.c"
-#include "f_diag.c"
-#include "f_rmnet.c"
-
-/*-------------------------------------------------------------------------*/
-/* string IDs are assigned dynamically */
-
-#define STRING_MANUFACTURER_IDX 0
-#define STRING_PRODUCT_IDX 1
-#define STRING_SERIAL_IDX 2
-
-/* String Table */
-static struct usb_string strings_dev[] = {
- /* These dummy values should be overridden by platform data */
- [STRING_MANUFACTURER_IDX].s = "Qualcomm Incorporated",
- [STRING_PRODUCT_IDX].s = "Usb composition",
- [STRING_SERIAL_IDX].s = "0123456789ABCDEF",
- { } /* end of list */
-};
-
-static struct usb_gadget_strings stringtab_dev = {
- .language = 0x0409, /* en-us */
- .strings = strings_dev,
-};
-
-static struct usb_gadget_strings *dev_strings[] = {
- &stringtab_dev,
- NULL,
-};
-
-static struct usb_device_descriptor device_desc = {
- .bLength = sizeof(device_desc),
- .bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
- .bDeviceClass = USB_CLASS_PER_INTERFACE,
- .bDeviceSubClass = 0,
- .bDeviceProtocol = 0,
- .idVendor = __constant_cpu_to_le16(VENDOR_ID),
- .idProduct = __constant_cpu_to_le16(PRODUCT_ID),
- .bcdDevice = __constant_cpu_to_le16(0xffff),
- .bNumConfigurations = 1,
-};
-
-static u8 hostaddr[ETH_ALEN];
-static struct usb_diag_ch *diag_ch;
-static struct usb_diag_platform_data usb_diag_pdata = {
- .ch_name = DIAG_LEGACY,
-};
-
-/****************************** Configurations ******************************/
-static struct fsg_module_parameters mod_data = {
- .stall = 0
-};
-FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
-
-static struct fsg_common *fsg_common;
-static int maemo_setup_config(struct usb_configuration *c,
- const struct usb_ctrlrequest *ctrl);
-
-static int maemo_do_config(struct usb_configuration *c)
-{
- int ret;
-
- ret = rndis_bind_config(c, hostaddr);
- if (ret < 0)
- return ret;
-
- ret = diag_function_add(c);
- if (ret < 0)
- return ret;
-
- ret = gser_bind_config(c, 0);
- if (ret < 0)
- return ret;
-
- ret = gser_bind_config(c, 1);
- if (ret < 0)
- return ret;
-
- ret = rmnet_function_add(c);
- if (ret < 0)
- return ret;
-
- ret = fsg_add(c->cdev, c, fsg_common);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static struct usb_configuration maemo_config_driver = {
- .label = "Qcom Maemo Gadget",
- .bind = maemo_do_config,
- .setup = maemo_setup_config,
- .bConfigurationValue = 1,
- .bMaxPower = 0xFA,
-};
-static int maemo_setup_config(struct usb_configuration *c,
- const struct usb_ctrlrequest *ctrl)
-{
- int i;
- int ret = -EOPNOTSUPP;
-
- for (i = 0; i < maemo_config_driver.next_interface_id; i++) {
- if (maemo_config_driver.interface[i]->setup) {
- ret = maemo_config_driver.interface[i]->setup(
- maemo_config_driver.interface[i], ctrl);
- if (ret >= 0)
- return ret;
- }
- }
-
- return ret;
-}
-
-static int maemo_bind(struct usb_composite_dev *cdev)
-{
- struct usb_gadget *gadget = cdev->gadget;
- int status, gcnum;
-
- /* set up diag channel */
- diag_ch = diag_setup(&usb_diag_pdata);
- if (IS_ERR(diag_ch))
- return PTR_ERR(diag_ch);
-
- /* set up network link layer */
- status = gether_setup(cdev->gadget, hostaddr);
- if (status < 0)
- goto diag_clean;
-
- /* set up serial link layer */
- status = gserial_setup(cdev->gadget, 2);
- if (status < 0)
- goto fail0;
-
- /* set up mass storage function */
- fsg_common = fsg_common_from_params(0, cdev, &mod_data);
- if (IS_ERR(fsg_common)) {
- status = PTR_ERR(fsg_common);
- goto fail1;
- }
-
- gcnum = usb_gadget_controller_number(gadget);
- if (gcnum >= 0)
- device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
- else {
- /* gadget zero is so simple (for now, no altsettings) that
- * it SHOULD NOT have problems with bulk-capable hardware.
- * so just warn about unrcognized controllers -- don't panic.
- *
- * things like configuration and altsetting numbering
- * can need hardware-specific attention though.
- */
- WARNING(cdev, "controller '%s' not recognized\n",
- gadget->name);
- device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
- }
-
- /* Allocate string descriptor numbers ... note that string
- * contents can be overridden by the composite_dev glue.
- */
-
- status = usb_string_id(cdev);
- if (status < 0)
- goto fail2;
- strings_dev[STRING_MANUFACTURER_IDX].id = status;
- device_desc.iManufacturer = status;
-
- status = usb_string_id(cdev);
- if (status < 0)
- goto fail2;
- strings_dev[STRING_PRODUCT_IDX].id = status;
- device_desc.iProduct = status;
-
- if (!usb_gadget_set_selfpowered(gadget))
- maemo_config_driver.bmAttributes |= USB_CONFIG_ATT_SELFPOWER;
-
- if (gadget->ops->wakeup)
- maemo_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-
- /* register our first configuration */
- status = usb_add_config(cdev, &maemo_config_driver);
- if (status < 0)
- goto fail2;
-
- usb_gadget_set_selfpowered(gadget);
- dev_info(&gadget->dev, DRIVER_DESC "\n");
- fsg_common_put(fsg_common);
- return 0;
-
-fail2:
- fsg_common_put(fsg_common);
-fail1:
- gserial_cleanup();
-fail0:
- gether_cleanup();
-diag_clean:
- diag_cleanup(diag_ch);
-
- return status;
-}
-
-static int __exit maemo_unbind(struct usb_composite_dev *cdev)
-{
- gserial_cleanup();
- gether_cleanup();
- diag_cleanup(diag_ch);
- return 0;
-}
-
-static struct usb_composite_driver qcom_maemo_driver = {
- .name = "Qcom Maemo Gadget",
- .dev = &device_desc,
- .strings = dev_strings,
- .bind = maemo_bind,
- .unbind = __exit_p(maemo_unbind),
-};
-
-static int __init qcom_maemo_usb_init(void)
-{
- return usb_composite_register(&qcom_maemo_driver);
-}
-module_init(qcom_maemo_usb_init);
-
-static void __exit qcom_maemo_usb_cleanup(void)
-{
- usb_composite_unregister(&qcom_maemo_driver);
-}
-module_exit(qcom_maemo_usb_cleanup);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION("1.0");
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 502c33a..350e723 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -1048,6 +1048,13 @@
struct gs_port *port = tty->driver_data;
unsigned long flags;
+ /*
+ * tty's driver data is set to NULL during port close. Nothing
+ * to do here.
+ */
+ if (!port)
+ return;
+
spin_lock_irqsave(&port->port_lock, flags);
if (port->port_usb) {
/* Kickstart read queue processing. We don't do xon/xoff,
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 8c0894c..ca4b01a 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -624,6 +624,15 @@
int ret;
void __iomem *reg;
+ if (pdata && pdata->resume_gpio) {
+ ret = gpio_request(pdata->resume_gpio, "HSIC_RESUME_GPIO");
+ if (ret < 0) {
+ dev_err(mehci->dev,
+ "gpio req failed for hsic resume:%d\n", ret);
+ pdata->resume_gpio = 0;
+ }
+ }
+
/* HSIC init sequence when HSIC signals (Strobe/Data) are
routed via GPIOs */
if (pdata && pdata->strobe && pdata->data) {
@@ -645,7 +654,7 @@
ret = msm_hsic_config_gpios(mehci, 1);
if (ret) {
dev_err(mehci->dev, " gpio configuarion failed\n");
- return ret;
+ goto free_resume_gpio;
}
if (pdata->strobe_pad_offset) {
/* Set CORE_CTL_EN in STROBE GPIO PAD_CTL register */
@@ -694,6 +703,12 @@
ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
return 0;
+
+free_resume_gpio:
+ if (pdata && pdata->resume_gpio)
+ gpio_free(pdata->resume_gpio);
+
+ return ret;
}
#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
@@ -1312,6 +1327,10 @@
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
u32 temp;
struct task_struct *resume_thread = NULL;
+ struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
+
+ if (pdata->resume_gpio)
+ gpio_direction_output(pdata->resume_gpio, 1);
mehci->resume_status = 0;
resume_thread = kthread_run(msm_hsic_resume_thread,
@@ -1351,6 +1370,9 @@
spin_unlock_irq(&ehci->lock);
+ if (pdata->resume_gpio)
+ gpio_direction_output(pdata->resume_gpio, 0);
+
return 0;
}
@@ -1781,6 +1803,11 @@
res_gpio = 0;
pdata->data = res_gpio;
+ res_gpio = of_get_named_gpio(node, "hsic,resume-gpio", 0);
+ if (res_gpio < 0)
+ res_gpio = 0;
+ pdata->resume_gpio = res_gpio;
+
pdata->ignore_cal_pad_config = of_property_read_bool(node,
"hsic,ignore-cal-pad-config");
of_property_read_u32(node, "hsic,strobe-pad-offset",
@@ -2099,6 +2126,10 @@
destroy_workqueue(ehci_wq);
msm_hsic_config_gpios(mehci, 0);
+
+ if (pdata && pdata->resume_gpio)
+ gpio_free(pdata->resume_gpio);
+
msm_hsic_init_vddcx(mehci, 0);
msm_hsic_init_gdsc(mehci, 0);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index cd17421..edf2a73 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -754,23 +754,6 @@
#endif
-/*
- * Writing to dma coherent memory on ARM may be delayed via L2
- * writing buffer, so introduce the helper which can flush L2 writing
- * buffer into memory immediately, especially used to flush ehci
- * descriptor to memory.
- * */
-#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
-static inline void ehci_sync_mem(void)
-{
- mb();
-}
-#else
-static inline void ehci_sync_mem(void)
-{
-}
-#endif
-
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_PCI
diff --git a/drivers/usb/otg/otg_id.c b/drivers/usb/otg/otg_id.c
deleted file mode 100644
index 7c38390..0000000
--- a/drivers/usb/otg/otg_id.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2011 Google, Inc.
- *
- * Author:
- * Colin Cross <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/notifier.h>
-#include <linux/usb/otg_id.h>
-
-static DEFINE_MUTEX(otg_id_lock);
-static struct plist_head otg_id_plist =
- PLIST_HEAD_INIT(otg_id_plist);
-static struct otg_id_notifier_block *otg_id_active;
-static bool otg_id_cancelling;
-static bool otg_id_inited;
-static int otg_id_suspended;
-static bool otg_id_pending;
-
-static void otg_id_cancel(void)
-{
- if (otg_id_active) {
- otg_id_cancelling = true;
- mutex_unlock(&otg_id_lock);
-
- otg_id_active->cancel(otg_id_active);
-
- mutex_lock(&otg_id_lock);
- otg_id_cancelling = false;
- }
-}
-
-static void __otg_id_notify(void)
-{
- int ret = 0;
- struct otg_id_notifier_block *otg_id_nb;
- bool proxy_wait = false;
- if (plist_head_empty(&otg_id_plist))
- return;
-
- plist_for_each_entry(otg_id_nb, &otg_id_plist, p) {
- if (proxy_wait) {
- if (otg_id_nb->proxy_wait)
- ret = otg_id_nb->proxy_wait(otg_id_nb);
- } else {
- ret = otg_id_nb->detect(otg_id_nb);
- }
- if (ret == OTG_ID_HANDLED) {
- otg_id_active = otg_id_nb;
- return;
- }
- if (ret == OTG_ID_PROXY_WAIT)
- proxy_wait = true;
-
- }
-
- WARN(1, "otg id event not handled");
- otg_id_active = NULL;
-}
-
-int otg_id_init(void)
-{
- mutex_lock(&otg_id_lock);
-
- otg_id_inited = true;
- __otg_id_notify();
-
- mutex_unlock(&otg_id_lock);
- return 0;
-}
-late_initcall(otg_id_init);
-
-/**
- * otg_id_register_notifier
- * @otg_id_nb: notifier block containing priority and callback function
- *
- * Register a notifier that will be called on any USB cable state change.
- * The priority determines the order the callback will be called in, a higher
- * number will be called first. A callback function needs to determine the
- * type of USB cable that is connected. If it can determine the type, it
- * should notify the appropriate drivers (for example, call an otg notifier
- * with USB_EVENT_VBUS), and return OTG_ID_HANDLED. Once a callback has
- * returned OTG_ID_HANDLED, it is responsible for calling otg_id_notify() when
- * the detected USB cable is disconnected.
- */
-int otg_id_register_notifier(struct otg_id_notifier_block *otg_id_nb)
-{
- plist_node_init(&otg_id_nb->p, otg_id_nb->priority);
-
- mutex_lock(&otg_id_lock);
- plist_add(&otg_id_nb->p, &otg_id_plist);
-
- if (otg_id_inited) {
- otg_id_cancel();
- __otg_id_notify();
- }
-
- mutex_unlock(&otg_id_lock);
-
- return 0;
-}
-
-void otg_id_unregister_notifier(struct otg_id_notifier_block *otg_id_nb)
-{
- mutex_lock(&otg_id_lock);
-
- plist_del(&otg_id_nb->p, &otg_id_plist);
-
- if (otg_id_inited && (otg_id_active == otg_id_nb)) {
- otg_id_cancel();
- __otg_id_notify();
- }
-
- mutex_unlock(&otg_id_lock);
-}
-
-/**
- * otg_id_notify
- *
- * Notify listeners on any USB cable state change.
- *
- * A driver may only call otg_id_notify if it returned OTG_ID_HANDLED the last
- * time it's notifier was called, and it's cancel function has not been called.
- */
-void otg_id_notify(void)
-{
- mutex_lock(&otg_id_lock);
-
- if (otg_id_cancelling)
- goto out;
-
- if (otg_id_suspended != 0) {
- otg_id_pending = true;
- goto out;
- }
-
- __otg_id_notify();
-out:
- mutex_unlock(&otg_id_lock);
-}
-
-/**
- * otg_id_suspend
- *
- * Mark the otg_id subsystem as going into suspend. From here on out,
- * any notifications will be deferred until the last otg_id client resumes.
- * If there is a pending notification when calling this function, it will
- * return a negative errno and expects that the caller will abort suspend.
- * Returs 0 on success.
- */
-int otg_id_suspend(void)
-{
- int ret = 0;
-
- mutex_lock(&otg_id_lock);
-
- /*
- * if there's a pending notification, tell the caller to abort suspend
- */
- if (otg_id_suspended != 0 && otg_id_pending) {
- pr_info("otg_id: pending notification, should abort suspend\n");
- ret = -EBUSY;
- goto out;
- }
-
- otg_id_suspended++;
-out:
- mutex_unlock(&otg_id_lock);
- return ret;
-}
-
-/**
- * otg_id_resume
- *
- * Inform the otg_id subsystem that a client is resuming. If this is the
- * last client to be resumed and there's a pending notification,
- * otg_id_notify() is called.
- */
-void otg_id_resume(void)
-{
- mutex_lock(&otg_id_lock);
- if (WARN(!otg_id_suspended, "unbalanced otg_id_resume\n"))
- goto out;
- if (--otg_id_suspended == 0) {
- if (otg_id_pending) {
- pr_info("otg_id: had pending notification\n");
- otg_id_pending = false;
- __otg_id_notify();
- }
- }
-out:
- mutex_unlock(&otg_id_lock);
-}
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index bfd8238..e50055f 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -3682,6 +3682,8 @@
mdp4_overlay_mdp_perf_upd(mfd, 1);
+ msm_fb_wait_for_fence(mfd);
+
switch (mfd->panel.type) {
case MIPI_CMD_PANEL:
mdp4_dsi_cmd_pipe_commit(0, 1);
@@ -3703,6 +3705,7 @@
ret = -EINVAL;
break;
}
+ msm_fb_signal_timeline(mfd);
mdp4_overlay_mdp_perf_upd(mfd, 0);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 4f95aee..6c7a1195 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -1774,6 +1774,12 @@
return -ENODEV;
}
+ if (!hdmi_ctrl->audio_sdev.state) {
+ DEV_ERR("%s: failed. HDMI is not connected/ready for audio\n",
+ __func__);
+ return -EPERM;
+ }
+
return hdmi_edid_get_audio_blk(
hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], blk);
} /* hdmi_tx_get_audio_edid_blk */
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index dcefc09..005a420 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -539,9 +539,9 @@
virt = ion_map_kernel(iclient, ihdl);
ion_phys(iclient, ihdl, &phys, &size);
- pr_debug("%s %d Allocating %u bytes at 0x%lx (%lx phys)\n",
+ pr_debug("%s %d Allocating %u bytes at 0x%lx (%pa phys)\n",
__func__, __LINE__, size,
- (unsigned long int)virt, phys);
+ (unsigned long int)virt, &phys);
bl_fb_addr_va = (unsigned long *)ioremap(bl_fb_addr, size);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index e5f8a69..57bf9f2 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -118,6 +118,8 @@
static int mdp_bl_scale_config(struct msm_fb_data_type *mfd,
struct mdp_bl_scale_data *data);
static void msm_fb_scale_bl(__u32 *bl_lvl);
+static void msm_fb_commit_wq_handler(struct work_struct *work);
+static int msm_fb_pan_idle(struct msm_fb_data_type *mfd);
#ifdef MSM_FB_ENABLE_DBGFS
@@ -879,6 +881,17 @@
if (ret)
mfd->panel_power_on = curr_pwr_state;
+ if (mfd->timeline) {
+ /* Adding 1 is enough when pan_display is still
+ * a blocking call and with mutex protection.
+ * But if it is an async call, we will still
+ * need to add 2. Adding 2 can be safer in
+ * order to signal all existing fences, and it
+ * is harmless. */
+ sw_sync_timeline_inc(mfd->timeline, 2);
+ mfd->timeline_value += 2;
+ }
+
mfd->op_enable = TRUE;
}
break;
@@ -921,7 +934,7 @@
const struct fb_fillrect *rect)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-
+ msm_fb_pan_idle(mfd);
cfb_fillrect(info, rect);
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
!mfd->sw_currently_refreshing) {
@@ -942,6 +955,7 @@
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ msm_fb_pan_idle(mfd);
cfb_copyarea(info, area);
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
!mfd->sw_currently_refreshing) {
@@ -961,6 +975,7 @@
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ msm_fb_pan_idle(mfd);
cfb_imageblit(info, image);
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
!mfd->sw_currently_refreshing) {
@@ -979,6 +994,7 @@
static int msm_fb_blank(int blank_mode, struct fb_info *info)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ msm_fb_pan_idle(mfd);
return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
}
@@ -1005,6 +1021,7 @@
u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ msm_fb_pan_idle(mfd);
if (off >= len) {
/* memory mapped io */
off -= len;
@@ -1359,7 +1376,15 @@
mfd->msmfb_no_update_notify_timer.data = (unsigned long)mfd;
init_completion(&mfd->msmfb_update_notify);
init_completion(&mfd->msmfb_no_update_notify);
-
+ init_completion(&mfd->commit_comp);
+ mutex_init(&mfd->sync_mutex);
+ INIT_WORK(&mfd->commit_work, msm_fb_commit_wq_handler);
+ mfd->msm_fb_backup = kzalloc(sizeof(struct msm_fb_backup_type),
+ GFP_KERNEL);
+ if (mfd->msm_fb_backup == 0) {
+ pr_err("error: not enough memory!\n");
+ return -ENOMEM;
+ }
fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
fbram += fbram_offset;
fbram_phys += fbram_offset;
@@ -1669,7 +1694,34 @@
return ret;
}
-DEFINE_SEMAPHORE(msm_fb_pan_sem);
+int msm_fb_wait_for_fence(struct msm_fb_data_type *mfd)
+{
+ int i, ret = 0;
+ /* buf sync */
+ for (i = 0; i < mfd->acq_fen_cnt; i++) {
+ ret = sync_fence_wait(mfd->acq_fen[i], WAIT_FENCE_TIMEOUT);
+ sync_fence_put(mfd->acq_fen[i]);
+ if (ret < 0) {
+ pr_err("%s: sync_fence_wait failed! ret = %x\n",
+ __func__, ret);
+ break;
+ }
+ }
+ mfd->acq_fen_cnt = 0;
+ return ret;
+}
+int msm_fb_signal_timeline(struct msm_fb_data_type *mfd)
+{
+ mutex_lock(&mfd->sync_mutex);
+ if (mfd->timeline) {
+ sw_sync_timeline_inc(mfd->timeline, 1);
+ mfd->timeline_value++;
+ }
+ mfd->last_rel_fence = mfd->cur_rel_fence;
+ mfd->cur_rel_fence = 0;
+ mutex_unlock(&mfd->sync_mutex);
+ return 0;
+}
static void bl_workqueue_handler(struct work_struct *work)
{
@@ -1687,13 +1739,84 @@
}
}
+DEFINE_SEMAPHORE(msm_fb_pan_sem);
+static int msm_fb_pan_idle(struct msm_fb_data_type *mfd)
+{
+ int ret = 0;
+
+ mutex_lock(&mfd->sync_mutex);
+ if (mfd->is_committing) {
+ mutex_unlock(&mfd->sync_mutex);
+ ret = wait_for_completion_timeout(&mfd->commit_comp,
+ msecs_to_jiffies(WAIT_FENCE_TIMEOUT));
+ if (ret <= 0)
+ pr_err("%s wait for commit_comp timeout %d %d",
+ __func__, ret, mfd->is_committing);
+ } else {
+ mutex_unlock(&mfd->sync_mutex);
+ }
+ return ret;
+}
+static int msm_fb_pan_display_ex(struct fb_var_screeninfo *var,
+ struct fb_info *info, u32 wait_for_finish)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct msm_fb_backup_type *fb_backup;
+ int ret = 0;
+ /*
+ * If framebuffer is 2, io pen display is not allowed.
+ */
+ if (bf_supported && info->node == 2) {
+ pr_err("%s: no pan display for fb%d!",
+ __func__, info->node);
+ return -EPERM;
+ }
+
+ if (info->node != 0 || mfd->cont_splash_done) /* primary */
+ if ((!mfd->op_enable) || (!mfd->panel_power_on))
+ return -EPERM;
+
+ if (var->xoffset > (info->var.xres_virtual - info->var.xres))
+ return -EINVAL;
+
+ if (var->yoffset > (info->var.yres_virtual - info->var.yres))
+ return -EINVAL;
+ msm_fb_pan_idle(mfd);
+
+ mutex_lock(&mfd->sync_mutex);
+
+ if (info->fix.xpanstep)
+ info->var.xoffset =
+ (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
+
+ if (info->fix.ypanstep)
+ info->var.yoffset =
+ (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+
+ fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
+ memcpy(&fb_backup->info, info, sizeof(struct fb_info));
+ memcpy(&fb_backup->var, var, sizeof(struct fb_var_screeninfo));
+ mfd->is_committing = 1;
+ INIT_COMPLETION(mfd->commit_comp);
+ schedule_work(&mfd->commit_work);
+ mutex_unlock(&mfd->sync_mutex);
+ if (wait_for_finish)
+ msm_fb_pan_idle(mfd);
+ return ret;
+}
+
static int msm_fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
+ return msm_fb_pan_display_ex(var, info, TRUE);
+}
+
+static int msm_fb_pan_display_sub(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
struct mdp_dirty_region dirty;
struct mdp_dirty_region *dirtyPtr = NULL;
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
- int i, ret;
/*
* If framebuffer is 2, io pen display is not allowed.
@@ -1765,17 +1888,7 @@
mutex_unlock(&msm_fb_notify_update_sem);
down(&msm_fb_pan_sem);
- /* buf sync */
- for (i = 0; i < mfd->acq_fen_cnt; i++) {
- ret = sync_fence_wait(mfd->acq_fen[i], WAIT_FENCE_TIMEOUT);
- sync_fence_put(mfd->acq_fen[i]);
- if (ret < 0) {
- pr_err("%s: sync_fence_wait failed! ret = %x\n",
- __func__, ret);
- break;
- }
- }
- mfd->acq_fen_cnt = 0;
+ msm_fb_wait_for_fence(mfd);
if (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */
mdp_set_dma_pan_info(info, NULL, TRUE);
if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
@@ -1790,13 +1903,9 @@
mdp_set_dma_pan_info(info, dirtyPtr,
(var->activate & FB_ACTIVATE_VBL));
+ /* async call */
mdp_dma_pan_update(info);
- if (mfd->timeline) {
- sw_sync_timeline_inc(mfd->timeline, 1);
- mfd->timeline_value++;
- }
- mfd->last_rel_fence = mfd->cur_rel_fence;
- mfd->cur_rel_fence = 0;
+ msm_fb_signal_timeline(mfd);
up(&msm_fb_pan_sem);
if (unset_bl_level && !bl_updated)
@@ -1810,8 +1919,30 @@
return 0;
}
+static void msm_fb_commit_wq_handler(struct work_struct *work)
+{
+ struct msm_fb_data_type *mfd;
+ struct fb_var_screeninfo *var;
+ struct fb_info *info;
+ struct msm_fb_backup_type *fb_backup;
+
+ mfd = container_of(work, struct msm_fb_data_type, commit_work);
+ fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
+ var = &fb_backup->var;
+ info = &fb_backup->info;
+ msm_fb_pan_display_sub(var, info);
+ mutex_lock(&mfd->sync_mutex);
+ mfd->is_committing = 0;
+ complete_all(&mfd->commit_comp);
+ mutex_unlock(&mfd->sync_mutex);
+
+}
+
static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ msm_fb_pan_idle(mfd);
if (var->rotate != FB_ROTATE_UR)
return -EINVAL;
if (var->grayscale != info->var.grayscale)
@@ -1936,7 +2067,7 @@
struct fb_var_screeninfo *var = &info->var;
int old_imgType;
int blank = 0;
-
+ msm_fb_pan_idle(mfd);
old_imgType = mfd->fb_imgType;
switch (var->bits_per_pixel) {
case 16:
@@ -3386,6 +3517,7 @@
pr_err("%s:copy_from_user failed", __func__);
return ret;
}
+ mutex_lock(&mfd->sync_mutex);
for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
fence = sync_fence_fdget(acq_fen_fd[i]);
if (fence == NULL) {
@@ -3426,6 +3558,7 @@
goto buf_sync_err_2;
}
mfd->acq_fen_cnt = buf_sync->acq_fen_fd_cnt;
+ mutex_unlock(&mfd->sync_mutex);
return ret;
buf_sync_err_2:
sync_fence_put(mfd->cur_rel_fence);
@@ -3436,6 +3569,97 @@
for (i = 0; i < fence_cnt; i++)
sync_fence_put(mfd->acq_fen[i]);
mfd->acq_fen_cnt = 0;
+ mutex_unlock(&mfd->sync_mutex);
+ return ret;
+}
+
+static int buf_fence_process(struct msm_fb_data_type *mfd,
+ struct mdp_buf_fence *buf_fence)
+{
+ int i, fence_cnt = 0, ret;
+ struct sync_fence *fence;
+
+ if ((buf_fence->acq_fen_fd_cnt == 0) ||
+ (buf_fence->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
+ (mfd->timeline == NULL))
+ return -EINVAL;
+
+ mutex_lock(&mfd->sync_mutex);
+ for (i = 0; i < buf_fence->acq_fen_fd_cnt; i++) {
+ fence = sync_fence_fdget(buf_fence->acq_fen_fd[i]);
+ if (fence == NULL) {
+ pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
+ buf_fence->acq_fen_fd[i]);
+ ret = -EINVAL;
+ break;
+ }
+ mfd->acq_fen[i] = fence;
+ }
+ fence_cnt = i;
+ if (ret)
+ goto buf_fence_err_1;
+ mfd->cur_rel_sync_pt = sw_sync_pt_create(mfd->timeline,
+ mfd->timeline_value + 2);
+ if (mfd->cur_rel_sync_pt == NULL) {
+ pr_err("%s: cannot create sync point", __func__);
+ ret = -ENOMEM;
+ goto buf_fence_err_1;
+ }
+ /* create fence */
+ mfd->cur_rel_fence = sync_fence_create("mdp-fence",
+ mfd->cur_rel_sync_pt);
+ if (mfd->cur_rel_fence == NULL) {
+ sync_pt_free(mfd->cur_rel_sync_pt);
+ mfd->cur_rel_sync_pt = NULL;
+ pr_err("%s: cannot create fence", __func__);
+ ret = -ENOMEM;
+ goto buf_fence_err_1;
+ }
+ /* create fd */
+ mfd->cur_rel_fen_fd = get_unused_fd_flags(0);
+ sync_fence_install(mfd->cur_rel_fence, mfd->cur_rel_fen_fd);
+ buf_fence->rel_fen_fd[0] = mfd->cur_rel_fen_fd;
+ /* Only one released fd for now, -1 indicates an end */
+ buf_fence->rel_fen_fd[1] = -1;
+ mfd->acq_fen_cnt = buf_fence->acq_fen_fd_cnt;
+ mutex_unlock(&mfd->sync_mutex);
+ return ret;
+buf_fence_err_1:
+ for (i = 0; i < fence_cnt; i++)
+ sync_fence_put(mfd->acq_fen[i]);
+ mfd->acq_fen_cnt = 0;
+ mutex_unlock(&mfd->sync_mutex);
+ return ret;
+}
+static int msmfb_display_commit(struct fb_info *info,
+ unsigned long *argp)
+{
+ int ret;
+ u32 copy_back = FALSE;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct mdp_display_commit disp_commit;
+ struct mdp_buf_fence *buf_fence;
+ ret = copy_from_user(&disp_commit, argp,
+ sizeof(disp_commit));
+ if (ret) {
+ pr_err("%s:copy_from_user failed", __func__);
+ return ret;
+ }
+ buf_fence = &disp_commit.buf_fence;
+ if (buf_fence->acq_fen_fd_cnt > 0)
+ ret = buf_fence_process(mfd, buf_fence);
+ if ((!ret) && (buf_fence->rel_fen_fd[0] > 0))
+ copy_back = TRUE;
+
+ ret = msm_fb_pan_display_ex(&disp_commit.var,
+ info, disp_commit.wait_for_finish);
+
+ if (copy_back) {
+ ret = copy_to_user(argp,
+ &disp_commit, sizeof(disp_commit));
+ if (ret)
+ pr_err("%s:copy_to_user failed", __func__);
+ }
return ret;
}
static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
@@ -3458,6 +3682,7 @@
struct msmfb_metadata mdp_metadata;
struct mdp_buf_sync buf_sync;
int ret = 0;
+ msm_fb_pan_idle(mfd);
switch (cmd) {
#ifdef CONFIG_FB_MSM_OVERLAY
@@ -3760,6 +3985,8 @@
if (ret)
return ret;
ret = msmfb_handle_metadata_ioctl(mfd, &mdp_metadata);
+ case MSMFB_DISPLAY_COMMIT:
+ ret = msmfb_display_commit(info, argp);
break;
case MSMFB_METADATA_GET:
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 7e1716a..7519ac7 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -205,6 +205,18 @@
struct sync_fence *last_rel_fence;
struct sw_sync_timeline *timeline;
int timeline_value;
+ u32 last_acq_fen_cnt;
+ struct sync_fence *last_acq_fen[MDP_MAX_FENCE_FD];
+ struct mutex sync_mutex;
+ struct completion commit_comp;
+ u32 is_committing;
+ struct work_struct commit_work;
+ void *msm_fb_backup;
+};
+struct msm_fb_backup_type {
+ struct fb_info info;
+ struct fb_var_screeninfo var;
+ struct msm_fb_data_type mfd;
};
struct dentry *msm_fb_get_debugfs_root(void);
@@ -224,7 +236,8 @@
int msm_fb_writeback_terminate(struct fb_info *info);
int msm_fb_detect_client(const char *name);
int calc_fb_offset(struct msm_fb_data_type *mfd, struct fb_info *fbi, int bpp);
-
+int msm_fb_wait_for_fence(struct msm_fb_data_type *mfd);
+int msm_fb_signal_timeline(struct msm_fb_data_type *mfd);
#ifdef CONFIG_FB_BACKLIGHT
void msm_fb_config_backlight(struct msm_fb_data_type *mfd);
#endif
diff --git a/fs/fat/Makefile b/fs/fat/Makefile
index 3f3e535..e061903 100644
--- a/fs/fat/Makefile
+++ b/fs/fat/Makefile
@@ -2,7 +2,6 @@
# Makefile for the Linux fat filesystem support.
#
-
obj-$(CONFIG_FAT_FS) += fat.o
obj-$(CONFIG_VFAT_FS) += vfat.o
obj-$(CONFIG_MSDOS_FS) += msdos.o
diff --git a/include/linux/cpuacct.h b/include/linux/cpuacct.h
deleted file mode 100644
index 8f68e73..0000000
--- a/include/linux/cpuacct.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* include/linux/cpuacct.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef _CPUACCT_H_
-#define _CPUACCT_H_
-
-#include <linux/cgroup.h>
-
-#ifdef CONFIG_CGROUP_CPUACCT
-
-/*
- * Platform specific CPU frequency hooks for cpuacct. These functions are
- * called from the scheduler.
- */
-struct cpuacct_charge_calls {
- /*
- * Platforms can take advantage of this data and use
- * per-cpu allocations if necessary.
- */
- void (*init) (void **cpuacct_data);
- void (*charge) (void *cpuacct_data, u64 cputime, unsigned int cpu);
- void (*cpufreq_show) (void *cpuacct_data, struct cgroup_map_cb *cb);
- /* Returns power consumed in milliWatt seconds */
- u64 (*power_usage) (void *cpuacct_data);
-};
-
-int cpuacct_charge_register(struct cpuacct_charge_calls *fn);
-
-#endif /* CONFIG_CGROUP_CPUACCT */
-
-#endif // _CPUACCT_H_
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 7a5ab0d..d208f1e 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -43,6 +43,10 @@
#define DIAG_IOCTL_DCI_REG 23
#define DIAG_IOCTL_DCI_STREAM_INIT 24
#define DIAG_IOCTL_DCI_HEALTH_STATS 25
+#define DIAG_IOCTL_DCI_LOG_STATUS 26
+#define DIAG_IOCTL_DCI_EVENT_STATUS 27
+#define DIAG_IOCTL_DCI_CLEAR_LOGS 28
+#define DIAG_IOCTL_DCI_CLEAR_EVENTS 29
#define DIAG_IOCTL_REMOTE_DEV 32
/* PC Tools IDs */
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index 14cb148..4fa41b5 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -39,7 +39,8 @@
uint8_t dev_num;
uint8_t chan_num;
uint32_t timestamp_resp_value;
- uint32_t reading_value;
+ int16_t reading_raw;
+ int32_t reading_value;
};
struct epm_psoc_get_buffered_data {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 03fc44b..093f0b8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -17,8 +17,8 @@
* nr_file rlimit, so it's safe to set up a ridiculously high absolute
* upper limit on files-per-process.
*
- * Some programs (notably those using select()) may have to be
- * recompiled to take full advantage of the new limits..
+ * Some programs (notably those using select()) may have to be
+ * recompiled to take full advantage of the new limits..
*/
/* Fixed constants first: */
@@ -178,7 +178,7 @@
#define SEL_EX 4
/* public flags for file_system_type */
-#define FS_REQUIRES_DEV 1
+#define FS_REQUIRES_DEV 1
#define FS_BINARY_MOUNTDATA 2
#define FS_HAS_SUBTYPE 4
#define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */
@@ -490,7 +490,7 @@
*/
#include <linux/quota.h>
-/**
+/**
* enum positive_aop_returns - aop return codes with specific semantics
*
* @AOP_WRITEPAGE_ACTIVATE: Informs the caller that page writeback has
@@ -500,7 +500,7 @@
* be a candidate for writeback again in the near
* future. Other callers must be careful to unlock
* the page if they get this return. Returned by
- * writepage();
+ * writepage();
*
* @AOP_TRUNCATED_PAGE: The AOP method that was handed a locked page has
* unlocked it and the page might have been truncated.
@@ -1078,10 +1078,10 @@
#define MAX_NON_LFS ((1UL<<31) - 1)
-/* Page cache limit. The filesystems should put that into their s_maxbytes
- limits, otherwise bad things can happen in VM. */
+/* Page cache limit. The filesystems should put that into their s_maxbytes
+ limits, otherwise bad things can happen in VM. */
#if BITS_PER_LONG==32
-#define MAX_LFS_FILESIZE (((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
+#define MAX_LFS_FILESIZE (((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
#elif BITS_PER_LONG==64
#define MAX_LFS_FILESIZE 0x7fffffffffffffffUL
#endif
@@ -2282,7 +2282,7 @@
extern int kernel_read(struct file *, loff_t, char *, unsigned long);
extern struct file * open_exec(const char *);
-
+
/* fs/dcache.c -- generic fs support functions */
extern int is_subdir(struct dentry *, struct dentry *);
extern int path_is_under(struct path *, struct path *);
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 37b1fdc..fb0c7af 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -710,7 +710,4 @@
#endif /* __KERNEL__ */
-/* To identify board information in panic logs, set this */
-extern char *mach_panic_string;
-
#endif
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index fc7d1a4..4473d69 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -243,10 +243,6 @@
extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
unsigned long pnum);
-extern void reserve_hotplug_pages(unsigned long start_pfn,
- unsigned long nr_pages);
-extern void unreserve_hotplug_pages(unsigned long start_pfn,
- unsigned long nr_pages);
#endif /* __LINUX_MEMORY_HOTPLUG_H */
extern int physical_remove_memory(u64 start, u64 size);
extern int arch_physical_remove_memory(u64 start, u64 size);
diff --git a/include/linux/mfd/wcd9xxx/wcd9306_registers.h b/include/linux/mfd/wcd9xxx/wcd9306_registers.h
index 1254fac..564e5b3 100644
--- a/include/linux/mfd/wcd9xxx/wcd9306_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9306_registers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -15,20 +15,20 @@
#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
-#define TAPAN_A_CHIP_CTL WCD9XXX_A_CHIP_CTL
-#define TAPAN_A_CHIP_CTL__POR WCD9XXX_A_CHIP_CTL__POR
-#define TAPAN_A_CHIP_STATUS WCD9XXX_A_CHIP_STATUS
-#define TAPAN_A_CHIP_STATUS__POR WCD9XXX_A_CHIP_STATUS__POR
-#define TAPAN_A_CHIP_ID_BYTE_0 WCD9XXX_A_CHIP_ID_BYTE_0
-#define TAPAN_A_CHIP_ID_BYTE_0__POR WCD9XXX_A_CHIP_ID_BYTE_0__POR
-#define TAPAN_A_CHIP_ID_BYTE_1 WCD9XXX_A_CHIP_ID_BYTE_1
-#define TAPAN_A_CHIP_ID_BYTE_1__POR WCD9XXX_A_CHIP_ID_BYTE_1__POR
-#define TAPAN_A_CHIP_ID_BYTE_2 WCD9XXX_A_CHIP_ID_BYTE_2
-#define TAPAN_A_CHIP_ID_BYTE_2__POR WCD9XXX_A_CHIP_ID_BYTE_2__POR
-#define TAPAN_A_CHIP_ID_BYTE_3 WCD9XXX_A_CHIP_ID_BYTE_3
-#define TAPAN_A_CHIP_ID_BYTE_3__POR WCD9XXX_A_CHIP_ID_BYTE_3__POR
-#define TAPAN_A_CHIP_VERSION WCD9XXX_A_CHIP_VERSION
-#define TAPAN_A_CHIP_VERSION__POR WCD9XXX_A_CHIP_VERSION__POR
+#define TAPAN_A_CHIP_CTL (0x000)
+#define TAPAN_A_CHIP_CTL__POR (0x00)
+#define TAPAN_A_CHIP_STATUS (0x001)
+#define TAPAN_A_CHIP_STATUS__POR (0x00)
+#define TAPAN_A_CHIP_ID_BYTE_0 (0x004)
+#define TAPAN_A_CHIP_ID_BYTE_0__POR (0x00)
+#define TAPAN_A_CHIP_ID_BYTE_1 (0x005)
+#define TAPAN_A_CHIP_ID_BYTE_1__POR (0x00)
+#define TAPAN_A_CHIP_ID_BYTE_2 (0x006)
+#define TAPAN_A_CHIP_ID_BYTE_2__POR (0x03)
+#define TAPAN_A_CHIP_ID_BYTE_3 (0x007)
+#define TAPAN_A_CHIP_ID_BYTE_3__POR (0x01)
+#define TAPAN_A_CHIP_VERSION (0x008)
+#define TAPAN_A_CHIP_VERSION__POR (0x20)
#define TAPAN_A_CHIP_DEBUG_CTL (0x009)
#define TAPAN_A_CHIP_DEBUG_CTL__POR (0x00)
#define TAPAN_A_SLAVE_ID_1 (0x00C)
@@ -566,21 +566,21 @@
#define TAPAN_A_CDC_TX4_VOL_CTL_CFG (0x23A)
#define TAPAN_A_CDC_TX4_VOL_CTL_CFG__POR (0x00)
#define TAPAN_A_CDC_TX1_MUX_CTL (0x223)
-#define TAPAN_A_CDC_TX1_MUX_CTL__POR (0x00)
+#define TAPAN_A_CDC_TX1_MUX_CTL__POR (0x08)
#define TAPAN_A_CDC_TX2_MUX_CTL (0x22B)
-#define TAPAN_A_CDC_TX2_MUX_CTL__POR (0x00)
+#define TAPAN_A_CDC_TX2_MUX_CTL__POR (0x08)
#define TAPAN_A_CDC_TX3_MUX_CTL (0x233)
-#define TAPAN_A_CDC_TX3_MUX_CTL__POR (0x00)
+#define TAPAN_A_CDC_TX3_MUX_CTL__POR (0x08)
#define TAPAN_A_CDC_TX4_MUX_CTL (0x23B)
-#define TAPAN_A_CDC_TX4_MUX_CTL__POR (0x00)
+#define TAPAN_A_CDC_TX4_MUX_CTL__POR (0x08)
#define TAPAN_A_CDC_TX1_CLK_FS_CTL (0x224)
-#define TAPAN_A_CDC_TX1_CLK_FS_CTL__POR (0x00)
+#define TAPAN_A_CDC_TX1_CLK_FS_CTL__POR (0x03)
#define TAPAN_A_CDC_TX2_CLK_FS_CTL (0x22C)
-#define TAPAN_A_CDC_TX2_CLK_FS_CTL__POR (0x00)
+#define TAPAN_A_CDC_TX2_CLK_FS_CTL__POR (0x03)
#define TAPAN_A_CDC_TX3_CLK_FS_CTL (0x234)
-#define TAPAN_A_CDC_TX3_CLK_FS_CTL__POR (0x00)
+#define TAPAN_A_CDC_TX3_CLK_FS_CTL__POR (0x03)
#define TAPAN_A_CDC_TX4_CLK_FS_CTL (0x23C)
-#define TAPAN_A_CDC_TX4_CLK_FS_CTL__POR (0x00)
+#define TAPAN_A_CDC_TX4_CLK_FS_CTL__POR (0x03)
#define TAPAN_A_CDC_TX1_DMIC_CTL (0x225)
#define TAPAN_A_CDC_TX1_DMIC_CTL__POR (0x00)
#define TAPAN_A_CDC_TX2_DMIC_CTL (0x22D)
@@ -608,9 +608,9 @@
#define TAPAN_A_CDC_SRC2_PDA_CFG (0x2A8)
#define TAPAN_A_CDC_SRC2_PDA_CFG__POR (0x00)
#define TAPAN_A_CDC_SRC1_FS_CTL (0x2A1)
-#define TAPAN_A_CDC_SRC1_FS_CTL__POR (0x00)
+#define TAPAN_A_CDC_SRC1_FS_CTL__POR (0x1B)
#define TAPAN_A_CDC_SRC2_FS_CTL (0x2A9)
-#define TAPAN_A_CDC_SRC2_FS_CTL__POR (0x00)
+#define TAPAN_A_CDC_SRC2_FS_CTL__POR (0x1B)
#define TAPAN_A_CDC_RX1_B1_CTL (0x2B0)
#define TAPAN_A_CDC_RX1_B1_CTL__POR (0x00)
#define TAPAN_A_CDC_RX2_B1_CTL (0x2B8)
@@ -644,21 +644,21 @@
#define TAPAN_A_CDC_RX4_B4_CTL (0x2CB)
#define TAPAN_A_CDC_RX4_B4_CTL__POR (0x00)
#define TAPAN_A_CDC_RX1_B5_CTL (0x2B4)
-#define TAPAN_A_CDC_RX1_B5_CTL__POR (0x00)
+#define TAPAN_A_CDC_RX1_B5_CTL__POR (0x78)
#define TAPAN_A_CDC_RX2_B5_CTL (0x2BC)
-#define TAPAN_A_CDC_RX2_B5_CTL__POR (0x00)
+#define TAPAN_A_CDC_RX2_B5_CTL__POR (0x78)
#define TAPAN_A_CDC_RX3_B5_CTL (0x2C4)
-#define TAPAN_A_CDC_RX3_B5_CTL__POR (0x00)
+#define TAPAN_A_CDC_RX3_B5_CTL__POR (0x78)
#define TAPAN_A_CDC_RX4_B5_CTL (0x2CC)
-#define TAPAN_A_CDC_RX4_B5_CTL__POR (0x00)
+#define TAPAN_A_CDC_RX4_B5_CTL__POR (0x78)
#define TAPAN_A_CDC_RX1_B6_CTL (0x2B5)
-#define TAPAN_A_CDC_RX1_B6_CTL__POR (0x00)
+#define TAPAN_A_CDC_RX1_B6_CTL__POR (0x80)
#define TAPAN_A_CDC_RX2_B6_CTL (0x2BD)
-#define TAPAN_A_CDC_RX2_B6_CTL__POR (0x00)
+#define TAPAN_A_CDC_RX2_B6_CTL__POR (0x80)
#define TAPAN_A_CDC_RX3_B6_CTL (0x2C5)
-#define TAPAN_A_CDC_RX3_B6_CTL__POR (0x00)
+#define TAPAN_A_CDC_RX3_B6_CTL__POR (0x80)
#define TAPAN_A_CDC_RX4_B6_CTL (0x2CD)
-#define TAPAN_A_CDC_RX4_B6_CTL__POR (0x00)
+#define TAPAN_A_CDC_RX4_B6_CTL__POR (0x80)
#define TAPAN_A_CDC_RX1_VOL_CTL_B1_CTL (0x2B6)
#define TAPAN_A_CDC_RX1_VOL_CTL_B1_CTL__POR (0x00)
#define TAPAN_A_CDC_RX2_VOL_CTL_B1_CTL (0x2BE)
@@ -784,9 +784,9 @@
#define TAPAN_A_CDC_IIR2_GAIN_B8_CTL (0x357)
#define TAPAN_A_CDC_IIR2_GAIN_B8_CTL__POR (0x00)
#define TAPAN_A_CDC_IIR1_CTL (0x348)
-#define TAPAN_A_CDC_IIR1_CTL__POR (0x00)
+#define TAPAN_A_CDC_IIR1_CTL__POR (0x40)
#define TAPAN_A_CDC_IIR2_CTL (0x358)
-#define TAPAN_A_CDC_IIR2_CTL__POR (0x00)
+#define TAPAN_A_CDC_IIR2_CTL__POR (0x40)
#define TAPAN_A_CDC_IIR1_GAIN_TIMER_CTL (0x349)
#define TAPAN_A_CDC_IIR1_GAIN_TIMER_CTL__POR (0x00)
#define TAPAN_A_CDC_IIR2_GAIN_TIMER_CTL (0x359)
@@ -802,35 +802,35 @@
#define TAPAN_A_CDC_TOP_GAIN_UPDATE (0x360)
#define TAPAN_A_CDC_TOP_GAIN_UPDATE__POR (0x00)
#define TAPAN_A_CDC_COMP0_B1_CTL (0x368)
-#define TAPAN_A_CDC_COMP0_B1_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP0_B1_CTL__POR (0x30)
#define TAPAN_A_CDC_COMP1_B1_CTL (0x370)
-#define TAPAN_A_CDC_COMP1_B1_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP1_B1_CTL__POR (0x30)
#define TAPAN_A_CDC_COMP2_B1_CTL (0x378)
-#define TAPAN_A_CDC_COMP2_B1_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP2_B1_CTL__POR (0x30)
#define TAPAN_A_CDC_COMP0_B2_CTL (0x369)
-#define TAPAN_A_CDC_COMP0_B2_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP0_B2_CTL__POR (0xB5)
#define TAPAN_A_CDC_COMP1_B2_CTL (0x371)
-#define TAPAN_A_CDC_COMP1_B2_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP1_B2_CTL__POR (0xB5)
#define TAPAN_A_CDC_COMP2_B2_CTL (0x379)
-#define TAPAN_A_CDC_COMP2_B2_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP2_B2_CTL__POR (0xB5)
#define TAPAN_A_CDC_COMP0_B3_CTL (0x36A)
-#define TAPAN_A_CDC_COMP0_B3_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP0_B3_CTL__POR (0x28)
#define TAPAN_A_CDC_COMP1_B3_CTL (0x372)
-#define TAPAN_A_CDC_COMP1_B3_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP1_B3_CTL__POR (0x28)
#define TAPAN_A_CDC_COMP2_B3_CTL (0x37A)
-#define TAPAN_A_CDC_COMP2_B3_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP2_B3_CTL__POR (0x28)
#define TAPAN_A_CDC_COMP0_B4_CTL (0x36B)
-#define TAPAN_A_CDC_COMP0_B4_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP0_B4_CTL__POR (0x37)
#define TAPAN_A_CDC_COMP1_B4_CTL (0x373)
-#define TAPAN_A_CDC_COMP1_B4_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP1_B4_CTL__POR (0x37)
#define TAPAN_A_CDC_COMP2_B4_CTL (0x37B)
-#define TAPAN_A_CDC_COMP2_B4_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP2_B4_CTL__POR (0x37)
#define TAPAN_A_CDC_COMP0_B5_CTL (0x36C)
-#define TAPAN_A_CDC_COMP0_B5_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP0_B5_CTL__POR (0x7F)
#define TAPAN_A_CDC_COMP1_B5_CTL (0x374)
-#define TAPAN_A_CDC_COMP1_B5_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP1_B5_CTL__POR (0x7F)
#define TAPAN_A_CDC_COMP2_B5_CTL (0x37C)
-#define TAPAN_A_CDC_COMP2_B5_CTL__POR (0x00)
+#define TAPAN_A_CDC_COMP2_B5_CTL__POR (0x7F)
#define TAPAN_A_CDC_COMP0_B6_CTL (0x36D)
#define TAPAN_A_CDC_COMP0_B6_CTL__POR (0x00)
#define TAPAN_A_CDC_COMP1_B6_CTL (0x375)
@@ -838,17 +838,17 @@
#define TAPAN_A_CDC_COMP2_B6_CTL (0x37D)
#define TAPAN_A_CDC_COMP2_B6_CTL__POR (0x00)
#define TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS (0x36E)
-#define TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS__POR (0x00)
+#define TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS__POR (0x03)
#define TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS (0x376)
-#define TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS__POR (0x00)
+#define TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS__POR (0x03)
#define TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS (0x37E)
-#define TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS__POR (0x00)
+#define TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS__POR (0x03)
#define TAPAN_A_CDC_COMP0_FS_CFG (0x36F)
-#define TAPAN_A_CDC_COMP0_FS_CFG__POR (0x00)
+#define TAPAN_A_CDC_COMP0_FS_CFG__POR (0x03)
#define TAPAN_A_CDC_COMP1_FS_CFG (0x377)
-#define TAPAN_A_CDC_COMP1_FS_CFG__POR (0x00)
+#define TAPAN_A_CDC_COMP1_FS_CFG__POR (0x03)
#define TAPAN_A_CDC_COMP2_FS_CFG (0x37F)
-#define TAPAN_A_CDC_COMP2_FS_CFG__POR (0x00)
+#define TAPAN_A_CDC_COMP2_FS_CFG__POR (0x03)
#define TAPAN_A_CDC_CONN_RX1_B1_CTL (0x380)
#define TAPAN_A_CDC_CONN_RX1_B1_CTL__POR (0x00)
#define TAPAN_A_CDC_CONN_RX1_B2_CTL (0x381)
@@ -992,12 +992,18 @@
#define TAPAN_A_CDC_MBHC_SPARE (0x3DF)
#define TAPAN_A_CDC_MBHC_SPARE__POR (0x00)
-
/* SLIMBUS Slave Registers */
-#define TAPAN_SLIM_PGD_PORT_INT_EN0 (0x30)
-#define TAPAN_SLIM_PGD_PORT_INT_STATUS0 (0x34)
-#define TAPAN_SLIM_PGD_PORT_INT_CLR0 (0x38)
-#define TAPAN_SLIM_PGD_PORT_INT_SOURCE0 (0x60)
+#define TAPAN_SLIM_PGD_PORT_INT_EN0 (0x30)
+#define TAPAN_SLIM_PGD_PORT_INT_STATUS_RX_0 (0x34)
+#define TAPAN_SLIM_PGD_PORT_INT_STATUS_RX_1 (0x35)
+#define TAPAN_SLIM_PGD_PORT_INT_STATUS_TX_0 (0x36)
+#define TAPAN_SLIM_PGD_PORT_INT_STATUS_TX_1 (0x37)
+#define TAPAN_SLIM_PGD_PORT_INT_CLR_RX_0 (0x38)
+#define TAPAN_SLIM_PGD_PORT_INT_CLR_RX_1 (0x39)
+#define TAPAN_SLIM_PGD_PORT_INT_CLR_TX_0 (0x3A)
+#define TAPAN_SLIM_PGD_PORT_INT_CLR_TX_1 (0x3B)
+#define TAPAN_SLIM_PGD_PORT_INT_RX_SOURCE0 (0x60)
+#define TAPAN_SLIM_PGD_PORT_INT_TX_SOURCE0 (0x70)
/* Macros for Packing Register Writes into a U32 */
#define TAPAN_PACKED_REG_SIZE sizeof(u32)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 6e12694..ca7a586 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -529,12 +529,6 @@
return test_bit(ZONE_OOM_LOCKED, &zone->flags);
}
-#ifdef CONFIG_SMP
-unsigned long zone_nr_free_pages(struct zone *zone);
-#else
-#define zone_nr_free_pages(zone) zone_page_state(zone, NR_FREE_PAGES)
-#endif /* CONFIG_SMP */
-
/*
* The "priority" of VM scanning is how much of the queues we will scan in one
* go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 45bc0ea..4149552 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -629,11 +629,19 @@
};
#define MDP_DISPLAY_COMMIT_OVERLAY 1
+struct mdp_buf_fence {
+ uint32_t flags;
+ uint32_t acq_fen_fd_cnt;
+ int acq_fen_fd[MDP_MAX_FENCE_FD];
+ int rel_fen_fd[MDP_MAX_FENCE_FD];
+};
+
struct mdp_display_commit {
uint32_t flags;
uint32_t wait_for_finish;
struct fb_var_screeninfo var;
+ struct mdp_buf_fence buf_fence;
};
struct mdp_page_protection {
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 6e4b7a6..ce5ddf3 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1135,55 +1135,6 @@
* %NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into
* (Re)Association Response frames when the driver (or firmware) replies to
* (Re)Association Request frames.
- * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration
- * of the station, see &enum nl80211_sta_wme_attr.
- * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working
- * as AP.
- *
- * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of
- * roaming to another AP in the same ESS if the signal lever is low.
- *
- * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching
- * candidate information, see &enum nl80211_pmksa_candidate_attr.
- *
- * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not
- * for management frames transmission. In order to avoid p2p probe/action
- * frames are being transmitted at CCK rate in 2GHz band, the user space
- * applications use this attribute.
- * This attribute is used with %NL80211_CMD_TRIGGER_SCAN and
- * %NL80211_CMD_FRAME commands.
- *
- * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup
- * request, link setup confirm, link teardown, etc.). Values are
- * described in the TDLS (802.11z) specification.
- * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a
- * TDLS conversation between two devices.
- * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see
- * &enum nl80211_tdls_operation, represented as a u8.
- * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate
- * as a TDLS peer sta.
- * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown
- * procedures should be performed by sending TDLS packets via
- * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
- * used for asking the driver to perform a TDLS operation.
- *
- * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices
- * that have AP support to indicate that they have the AP SME integrated
- * with support for the features listed in this attribute, see
- * &enum nl80211_ap_sme_features.
- *
- * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells
- * the driver to not wait for an acknowledgement. Note that due to this,
- * it will also not give a status callback nor return a cookie. This is
- * mostly useful for probe responses to save airtime.
- *
- * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from
- * &enum nl80211_feature_flags and is advertised in wiphy information.
- * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe
- *
- * requests while operating in AP-mode.
- * This attribute holds a bitmap of the supported protocols for
- * offloading (see &enum nl80211_probe_resp_offload_support_attr).
*
* @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration
* of the station, see &enum nl80211_sta_wme_attr.
diff --git a/include/linux/platform_data/ram_console.h b/include/linux/platform_data/ram_console.h
deleted file mode 100644
index 9f1125c..0000000
--- a/include/linux/platform_data/ram_console.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_
-#define _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_
-
-struct ram_console_platform_data {
- const char *bootinfo;
-};
-
-#endif /* _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_ */
diff --git a/include/linux/regulator/krait-regulator.h b/include/linux/regulator/krait-regulator.h
index b784531..2683fd7 100644
--- a/include/linux/regulator/krait-regulator.h
+++ b/include/linux/regulator/krait-regulator.h
@@ -27,22 +27,6 @@
#ifdef CONFIG_ARCH_MSM8974
int __init krait_power_init(void);
void secondary_cpu_hs_init(void *base_ptr);
-
-/**
- * krait_power_mdd_enable - function to turn on/off MDD. Turning off MDD
- * turns off badngap reference for LDO. If
- * a core is running on a LDO, requests to
- * turn off MDD will not be honoured
- * @on: boolean to indicate whether to turn MDD on/off
- *
- * CONTEXT: Can be called in interrupt context, only when the core
- * is about to go to idle, this guarantees that there are no
- * frequency changes on that cpu happening. Note if going from off
- * to on mode there will be settling delays
- *
- * RETURNS: -EINVAL if MDD cannot be turned off
- */
-int krait_power_mdd_enable(int cpu_num, bool on);
#else
static inline int __init krait_power_init(void)
{
@@ -50,10 +34,6 @@
}
static inline void secondary_cpu_hs_init(void *base_ptr) {}
-static inline int krait_power_mdd_enable(int cpu_num, bool on)
-{
- return -EINVAL;
-}
#endif
#endif
diff --git a/include/linux/rq_stats.h b/include/linux/rq_stats.h
index 65d8e8f..0accf38 100644
--- a/include/linux/rq_stats.h
+++ b/include/linux/rq_stats.h
@@ -19,6 +19,7 @@
unsigned long rq_poll_total_jiffies;
unsigned long def_timer_last_jiffy;
unsigned int def_interval;
+ unsigned int hotplug_disabled;
int64_t def_start_time;
struct attribute_group *attr_group;
struct kobject *kobj;
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index f9547f4..3b5e910 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -27,8 +27,6 @@
struct cpu_stop_done *done;
};
-extern struct mutex stop_cpus_mutex;
-
int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
struct cpu_stop_work *work_buf);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index c5943c9..ea45a8c 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -406,6 +406,9 @@
struct msm_bus_scale_pdata *bus_scale_table;
unsigned log2_irq_thresh;
+ /* gpio used to resume peripheral */
+ unsigned resume_gpio;
+
/*swfi latency is required while driving resume on to the bus */
u32 swfi_latency;
diff --git a/include/linux/usb/otg_id.h b/include/linux/usb/otg_id.h
deleted file mode 100644
index f9f5189..0000000
--- a/include/linux/usb/otg_id.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2011 Google, Inc.
- *
- * Author:
- * Colin Cross <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef __LINUX_USB_OTG_ID_H
-#define __LINUX_USB_OTG_ID_H
-
-#include <linux/notifier.h>
-#include <linux/plist.h>
-
-/**
- * otg_id_notifier_block
- *
- * @priority: Order the notifications will be called in. Higher numbers
- * get called first.
- * @detect: Called during otg_id_notify. Return OTG_ID_HANDLED if the USB cable
- * has been identified
- * @proxy_wait: Called during otg_id_notify if a previous handler returns
- * OTG_ID_PROXY_WAIT. This should wait on ID change then call otg_id_notify.
- * This is used when a handler knows what's connected but can't detect
- * the change itself.
- * @cancel: Called after detect has returned OTG_ID_HANDLED to ask it to
- * release detection resources to allow a new identification to occur.
- */
-
-struct otg_id_notifier_block {
- int priority;
- int (*detect)(struct otg_id_notifier_block *otg_id_nb);
- int (*proxy_wait)(struct otg_id_notifier_block *otg_id_nb);
- void (*cancel)(struct otg_id_notifier_block *otg_id_nb);
- struct plist_node p;
-};
-
-#define OTG_ID_PROXY_WAIT 2
-#define OTG_ID_HANDLED 1
-#define OTG_ID_UNHANDLED 0
-
-int otg_id_register_notifier(struct otg_id_notifier_block *otg_id_nb);
-void otg_id_unregister_notifier(struct otg_id_notifier_block *otg_id_nb);
-
-void otg_id_notify(void);
-int otg_id_suspend(void);
-void otg_id_resume(void);
-
-#endif /* __LINUX_USB_OTG_ID_H */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 2972dc0..a1d0445 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1491,6 +1491,7 @@
V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE = 0,
V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME = 1,
V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME = 2,
+
};
#define V4L2_CID_MPEG_VIDEO_MAX_REF_PIC (V4L2_CID_MPEG_BASE+217)
#define V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE (V4L2_CID_MPEG_BASE+218)
@@ -1602,7 +1603,6 @@
#define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP (V4L2_CID_MPEG_BASE+403)
#define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP (V4L2_CID_MPEG_BASE+404)
#define V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL (V4L2_CID_MPEG_BASE+405)
-
enum v4l2_mpeg_video_mpeg4_level {
V4L2_MPEG_VIDEO_MPEG4_LEVEL_0 = 0,
V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B = 1,
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index a51f84c..5b4ad6d 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -152,8 +152,8 @@
#define RC_MAP_TREKSTOR "rc-trekstor"
#define RC_MAP_TT_1500 "rc-tt-1500"
#define RC_MAP_TWINHAN_VP1027_DVBS "rc-twinhan1027"
-#define RC_MAP_VIDEOMATE_K100 "rc-videomate-k100"
#define RC_MAP_UE_RF4CE "rc-ue-rf4ce"
+#define RC_MAP_VIDEOMATE_K100 "rc-videomate-k100"
#define RC_MAP_VIDEOMATE_S350 "rc-videomate-s350"
#define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr"
#define RC_MAP_WINFAST "rc-winfast"
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index efc11bb..c68d427 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -26,7 +26,6 @@
#define __HCI_CORE_H
#include <net/bluetooth/hci.h>
-#include <linux/wakelock.h>
/* HCI upper protocols */
#define HCI_PROTO_L2CAP 0
#define HCI_PROTO_SCO 1
@@ -327,7 +326,6 @@
struct work_struct work_add;
struct work_struct work_del;
- struct wake_lock idle_lock;
struct device dev;
atomic_t devref;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3a7edf3..1645608 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -669,7 +669,9 @@
const u8 *assoc_req_ies;
size_t assoc_req_ies_len;
+
u32 beacon_loss_count;
+
/*
* Note: Add a new enum station_info_flags value for each new field and
* use it to check which fields are initialized.
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index 6f1470f..498433d 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -14,8 +14,6 @@
struct flowi6;
-extern void initialize_hashidentrnd(void);
-
/* extension headers */
extern int ipv6_exthdrs_init(void);
extern void ipv6_exthdrs_exit(void);
diff --git a/init/Kconfig b/init/Kconfig
index b2126bc..e4b67a1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1132,15 +1132,6 @@
option replaces shmem and tmpfs with the much simpler ramfs code,
which may be appropriate on small systems without swap.
-config ASHMEM
- bool "Enable the Anonymous Shared Memory Subsystem"
- default n
- depends on SHMEM || TINY_SHMEM
- help
- The ashmem subsystem is a new shared memory allocator, similar to
- POSIX SHM but with different behavior and sporting a simpler
- file-based API.
-
config AIO
bool "Enable AIO support" if EXPERT
default y
diff --git a/kernel/power/main.c b/kernel/power/main.c
index b54da02..7aac5f6 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -666,7 +666,6 @@
tc_ev_timer.function = &tc_ev_stop;
tc_ev_processed = 1;
-
power_kobj = kobject_create_and_add("power", NULL);
if (!power_kobj)
return -ENOMEM;
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index b0f118e..2f194e9 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -133,8 +133,8 @@
cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), work_buf);
}
-DEFINE_MUTEX(stop_cpus_mutex);
/* static data for stop_cpus */
+static DEFINE_MUTEX(stop_cpus_mutex);
static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work);
static void queue_stop_cpus_work(const struct cpumask *cpumask,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 50f73be..7ffcc1b 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -543,7 +543,6 @@
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
conn->conn_valid = true;
spin_lock_init(&conn->lock);
- wake_lock_init(&conn->idle_lock, WAKE_LOCK_SUSPEND, "bt_idle");
switch (type) {
case ACL_LINK:
@@ -621,7 +620,6 @@
/* Make sure no timers are running */
del_timer(&conn->idle_timer);
- wake_lock_destroy(&conn->idle_lock);
del_timer(&conn->disc_timer);
del_timer(&conn->smp_timer);
__cancel_delayed_work(&conn->rssi_update_work);
@@ -1082,7 +1080,6 @@
if (conn->conn_valid) {
mod_timer(&conn->idle_timer,
jiffies + msecs_to_jiffies(hdev->idle_timeout));
- wake_lock(&conn->idle_lock);
}
spin_unlock_bh(&conn->lock);
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 198773c..d243646 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2596,9 +2596,6 @@
else
conn->power_save = 0;
}
- if (conn->mode == HCI_CM_SNIFF)
- if (wake_lock_active(&conn->idle_lock))
- wake_unlock(&conn->idle_lock);
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
hci_sco_setup(conn, ev->status);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index d778ae3..83087d1 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -201,7 +201,7 @@
l2cap_pi(sk)->mode, sk->sk_state);
if (!addr || alen < sizeof(addr->sa_family) ||
- addr->sa_family != AF_BLUETOOTH)
+ addr->sa_family != AF_BLUETOOTH)
return -EINVAL;
memset(&la, 0, sizeof(la));
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 291934b..a00a904 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -69,3 +69,4 @@
obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o
obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
+
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index ab7bd2c..0cb86ce 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1991,49 +1991,6 @@
}
EXPORT_SYMBOL(tcp_v4_destroy_sock);
-/*
- * tcp_v4_nuke_addr - destroy all sockets on the given local address
- */
-void tcp_v4_nuke_addr(__u32 saddr)
-{
- unsigned int bucket;
-
- for (bucket = 0; bucket < tcp_hashinfo.ehash_mask; bucket++) {
- struct hlist_nulls_node *node;
- struct sock *sk;
- spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket);
-
-restart:
- spin_lock_bh(lock);
- sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
- struct inet_sock *inet = inet_sk(sk);
-
- if (inet->inet_rcv_saddr != saddr)
- continue;
- if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
- continue;
- if (sock_flag(sk, SOCK_DEAD))
- continue;
-
- sock_hold(sk);
- spin_unlock_bh(lock);
-
- local_bh_disable();
- bh_lock_sock(sk);
- sk->sk_err = ETIMEDOUT;
- sk->sk_error_report(sk);
-
- tcp_done(sk);
- bh_unlock_sock(sk);
- local_bh_enable();
- sock_put(sk);
-
- goto restart;
- }
- spin_unlock_bh(lock);
- }
-}
-
#ifdef CONFIG_PROC_FS
/* Proc filesystem TCP sock list dumping. */
diff --git a/net/wireless/util.c b/net/wireless/util.c
index a448b80..017d4fc 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1038,6 +1038,7 @@
if (!found)
return -EINVAL;
}
+
/*
* mask must have at least one bit set here since we
* didn't accept a 0-length rates array nor allowed
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index a09dab3..f0cd026 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -52,7 +52,7 @@
snd-soc-wcd9310-objs := wcd9310.o wcd9310-tables.o
snd-soc-cs8427-objs := cs8427.o
snd-soc-wcd9320-objs := wcd9xxx-resmgr.o wcd9320.o wcd9320-tables.o wcd9xxx-mbhc.o wcd9xxx-common.o
-snd-soc-wcd9306-objs := wcd9306.o wcd9306-tables.o
+snd-soc-wcd9306-objs := wcd9306.o wcd9306-tables.o wcd9xxx-common.o
snd-soc-msm8x10-wcd-objs := msm8x10-wcd.o msm8x10-wcd-tables.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 25d3f56..634493b 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -18,6 +18,8 @@
#include <linux/printk.h>
#include <linux/ratelimit.h>
#include <linux/debugfs.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
#include <linux/mfd/wcd9xxx/core.h>
#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
#include <linux/mfd/wcd9xxx/wcd9306_registers.h>
@@ -34,6 +36,20 @@
#include <linux/gpio.h>
#include "wcd9306.h"
#include "wcd9xxx-resmgr.h"
+#include "wcd9xxx-common.h"
+
+static atomic_t kp_tapan_priv;
+static int spkr_drv_wrnd_param_set(const char *val,
+ const struct kernel_param *kp);
+static int spkr_drv_wrnd = 1;
+
+static struct kernel_param_ops spkr_drv_wrnd_param_ops = {
+ .set = spkr_drv_wrnd_param_set,
+ .get = param_get_int,
+};
+module_param_cb(spkr_drv_wrnd, &spkr_drv_wrnd_param_ops, &spkr_drv_wrnd, 0644);
+MODULE_PARM_DESC(spkr_drv_wrnd,
+ "Run software workaround to avoid leakage on the speaker drive");
#define WCD9306_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
@@ -42,10 +58,22 @@
#define NUM_DECIMATORS 4
#define NUM_INTERPOLATORS 4
#define BITS_PER_REG 8
+/* This actual number of TX ports supported in slimbus slave */
#define TAPAN_TX_PORT_NUMBER 16
-#define TAPAN_I2S_MASTER_MODE_MASK 0x08
+/* Nummer of TX ports actually connected from Slimbus slave to codec Digital */
+#define TAPAN_SLIM_CODEC_TX_PORTS 5
+#define TAPAN_I2S_MASTER_MODE_MASK 0x08
+#define TAPAN_MCLK_CLK_12P288MHZ 12288000
+#define TAPAN_MCLK_CLK_9P6HZ 9600000
+
+#define TAPAN_SLIM_CLOSE_TIMEOUT 1000
+#define TAPAN_SLIM_IRQ_OVERFLOW (1 << 0)
+#define TAPAN_SLIM_IRQ_UNDERFLOW (1 << 1)
+#define TAPAN_SLIM_IRQ_PORT_CLOSED (1 << 2)
+#define TAPAN_MCLK_CLK_12P288MHZ 12288000
+#define TAPAN_MCLK_CLK_9P6HZ 9600000
enum {
AIF1_PB = 0,
AIF1_CAP,
@@ -67,8 +95,6 @@
RX_MIX1_INP_SEL_RX3,
RX_MIX1_INP_SEL_RX4,
RX_MIX1_INP_SEL_RX5,
- RX_MIX1_INP_SEL_RX6,
- RX_MIX1_INP_SEL_RX7,
RX_MIX1_INP_SEL_AUXRX,
};
@@ -97,7 +123,8 @@
};
enum {
- COMPANDER_1 = 0,
+ COMPANDER_0,
+ COMPANDER_1,
COMPANDER_2,
COMPANDER_MAX,
};
@@ -152,6 +179,11 @@
(1 << AIF1_CAP) | (1 << AIF2_CAP), /* AIF2_CAP */
};
+static const u32 vport_i2s_check_table[NUM_CODEC_DAIS] = {
+ 0, /* AIF1_PB */
+ 0, /* AIF1_CAP */
+};
+
struct tapan_priv {
struct snd_soc_codec *codec;
u32 adc_count;
@@ -168,22 +200,82 @@
/* num of slim ports required */
struct wcd9xxx_codec_dai_data dai[NUM_CODEC_DAIS];
+ /*compander*/
+ int comp_enabled[COMPANDER_MAX];
+ u32 comp_fs[COMPANDER_MAX];
+
/* Maintain the status of AUX PGA */
int aux_pga_cnt;
u8 aux_l_gain;
u8 aux_r_gain;
+ bool spkr_pa_widget_on;
+
/* resmgr module */
struct wcd9xxx_resmgr resmgr;
/* mbhc module */
struct wcd9xxx_mbhc mbhc;
+
+ /* class h specific data */
+ struct wcd9xxx_clsh_cdc_data clsh_d;
};
static const u32 comp_shift[] = {
+ 4, /* Compander 0's clock source is on interpolator 7 */
0,
2,
};
+static const int comp_rx_path[] = {
+ COMPANDER_1,
+ COMPANDER_1,
+ COMPANDER_2,
+ COMPANDER_2,
+ COMPANDER_2,
+ COMPANDER_2,
+ COMPANDER_0,
+ COMPANDER_MAX,
+};
+
+static const struct comp_sample_dependent_params comp_samp_params[] = {
+ {
+ /* 8 Khz */
+ .peak_det_timeout = 0x02,
+ .rms_meter_div_fact = 0x09,
+ .rms_meter_resamp_fact = 0x06,
+ },
+ {
+ /* 16 Khz */
+ .peak_det_timeout = 0x03,
+ .rms_meter_div_fact = 0x0A,
+ .rms_meter_resamp_fact = 0x0C,
+ },
+ {
+ /* 32 Khz */
+ .peak_det_timeout = 0x05,
+ .rms_meter_div_fact = 0x0B,
+ .rms_meter_resamp_fact = 0x1E,
+ },
+ {
+ /* 48 Khz */
+ .peak_det_timeout = 0x05,
+ .rms_meter_div_fact = 0x0B,
+ .rms_meter_resamp_fact = 0x28,
+ },
+ {
+ /* 96 Khz */
+ .peak_det_timeout = 0x06,
+ .rms_meter_div_fact = 0x0C,
+ .rms_meter_resamp_fact = 0x50,
+ },
+ {
+ /* 192 Khz */
+ .peak_det_timeout = 0x07,
+ .rms_meter_div_fact = 0xD,
+ .rms_meter_resamp_fact = 0xA0,
+ },
+};
+
static unsigned short rx_digital_gain_reg[] = {
TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL,
TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL,
@@ -198,71 +290,61 @@
TAPAN_A_CDC_TX4_VOL_CTL_GAIN,
};
-static int tapan_codec_enable_class_h_clk(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
+static int spkr_drv_wrnd_param_set(const char *val,
+ const struct kernel_param *kp)
{
- struct snd_soc_codec *codec = w->codec;
+ struct snd_soc_codec *codec;
+ int ret, old;
+ struct tapan_priv *priv;
- dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, TAPAN_A_CDC_CLSH_B1_CTL, 0x01, 0x01);
- break;
- case SND_SOC_DAPM_PRE_PMD:
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x80, 0x00);
- snd_soc_update_bits(codec, TAPAN_A_CDC_CLSH_B1_CTL, 0x01, 0x00);
- break;
+ priv = (struct tapan_priv *)atomic_read(&kp_tapan_priv);
+ if (!priv) {
+ pr_debug("%s: codec isn't yet registered\n", __func__);
+ return 0;
}
+
+ WCD9XXX_BCL_LOCK(&priv->resmgr);
+ old = spkr_drv_wrnd;
+ ret = param_set_int(val, kp);
+ if (ret) {
+ WCD9XXX_BCL_UNLOCK(&priv->resmgr);
+ return ret;
+ }
+
+ codec = priv->codec;
+ dev_dbg(codec->dev, "%s: spkr_drv_wrnd %d -> %d\n",
+ __func__, old, spkr_drv_wrnd);
+ if (old == 0 && spkr_drv_wrnd == 1) {
+ wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80, 0x80);
+ } else if (old == 1 && spkr_drv_wrnd == 0) {
+ wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ if (!priv->spkr_pa_widget_on)
+ snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80,
+ 0x00);
+ }
+
+ WCD9XXX_BCL_UNLOCK(&priv->resmgr);
return 0;
}
-static int tapan_codec_enable_class_h(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
+static int tapan_get_anc_slot(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = w->codec;
-
- dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
-
- switch (event) {
- case SND_SOC_DAPM_POST_PMU:
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_5, 0x02, 0x02);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_4, 0xFF, 0xFF);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x04, 0x04);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x04, 0x00);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x04, 0x00);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x08, 0x00);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x80, 0x80);
- usleep_range(1000, 1000);
- break;
- }
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ ucontrol->value.integer.value[0] = tapan->anc_slot;
return 0;
}
-static int tapan_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
+static int tapan_put_anc_slot(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = w->codec;
-
- dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, w->reg, 0x01, 0x01);
- snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
- snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x0f, 0x01);
- break;
-
- case SND_SOC_DAPM_POST_PMU:
- usleep_range(1000, 1000);
- break;
-
- case SND_SOC_DAPM_PRE_PMD:
- snd_soc_update_bits(codec, w->reg, 0x01, 0x00);
- snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
- snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x0f, 0x08);
- break;
- }
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ tapan->anc_slot = ucontrol->value.integer.value[0];
return 0;
}
@@ -464,6 +546,168 @@
return 0;
}
+static int tapan_get_compander(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int comp = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = tapan->comp_enabled[comp];
+ return 0;
+}
+
+static int tapan_set_compander(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ int comp = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ int value = ucontrol->value.integer.value[0];
+
+ dev_dbg(codec->dev, "%s: Compander %d enable current %d, new %d\n",
+ __func__, comp, tapan->comp_enabled[comp], value);
+ tapan->comp_enabled[comp] = value;
+ return 0;
+}
+
+static int tapan_config_gain_compander(struct snd_soc_codec *codec,
+ int comp, bool enable)
+{
+ int ret = 0;
+
+ switch (comp) {
+ case COMPANDER_0:
+ snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_GAIN,
+ 1 << 2, !enable << 2);
+ break;
+ case COMPANDER_1:
+ snd_soc_update_bits(codec, TAPAN_A_RX_HPH_L_GAIN,
+ 1 << 5, !enable << 5);
+ snd_soc_update_bits(codec, TAPAN_A_RX_HPH_R_GAIN,
+ 1 << 5, !enable << 5);
+ break;
+ case COMPANDER_2:
+ snd_soc_update_bits(codec, TAPAN_A_RX_LINE_1_GAIN,
+ 1 << 5, !enable << 5);
+ snd_soc_update_bits(codec, TAPAN_A_RX_LINE_2_GAIN,
+ 1 << 5, !enable << 5);
+ break;
+ default:
+ WARN_ON(1);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static void tapan_discharge_comp(struct snd_soc_codec *codec, int comp)
+{
+ /* Update RSM to 1, DIVF to 5 */
+ snd_soc_write(codec, TAPAN_A_CDC_COMP0_B3_CTL + (comp * 8), 1);
+ snd_soc_update_bits(codec, TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8), 0xF0,
+ 1 << 5);
+ /* Wait for 1ms */
+ usleep_range(1000, 1000);
+}
+
+static int tapan_config_compander(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ int mask, emask;
+ bool timedout;
+ unsigned long timeout;
+ struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ const int comp = w->shift;
+ const u32 rate = tapan->comp_fs[comp];
+ const struct comp_sample_dependent_params *comp_params =
+ &comp_samp_params[rate];
+
+ dev_dbg(codec->dev, "%s: %s event %d compander %d, enabled %d",
+ __func__, w->name, event, comp, tapan->comp_enabled[comp]);
+
+ if (!tapan->comp_enabled[comp])
+ return 0;
+
+ /* Compander 0 has single channel */
+ mask = (comp == COMPANDER_0 ? 0x01 : 0x03);
+ emask = (comp == COMPANDER_0 ? 0x02 : 0x03);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Set gain source to compander */
+ tapan_config_gain_compander(codec, comp, true);
+ /* Enable RX interpolation path clocks */
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RX_B2_CTL,
+ mask << comp_shift[comp],
+ mask << comp_shift[comp]);
+
+ tapan_discharge_comp(codec, comp);
+
+ /* Clear compander halt */
+ snd_soc_update_bits(codec, TAPAN_A_CDC_COMP0_B1_CTL +
+ (comp * 8),
+ 1 << 2, 0);
+ /* Toggle compander reset bits */
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL,
+ mask << comp_shift[comp],
+ mask << comp_shift[comp]);
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL,
+ mask << comp_shift[comp], 0);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* Set sample rate dependent paramater */
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_COMP0_FS_CFG + (comp * 8),
+ 0x07, rate);
+ snd_soc_write(codec, TAPAN_A_CDC_COMP0_B3_CTL + (comp * 8),
+ comp_params->rms_meter_resamp_fact);
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8),
+ 0x0F, comp_params->peak_det_timeout);
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_COMP0_B2_CTL + (comp * 8),
+ 0xF0, comp_params->rms_meter_div_fact << 4);
+ /* Compander enable */
+ snd_soc_update_bits(codec, TAPAN_A_CDC_COMP0_B1_CTL +
+ (comp * 8), emask, emask);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Halt compander */
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_COMP0_B1_CTL + (comp * 8),
+ 1 << 2, 1 << 2);
+ /* Wait up to a second for shutdown complete */
+ timeout = jiffies + HZ;
+ do {
+ if ((snd_soc_read(codec,
+ TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS +
+ (comp * 8)) & mask) == mask)
+ break;
+ } while (!(timedout = time_after(jiffies, timeout)));
+ dev_dbg(codec->dev, "%s: Compander %d shutdown %s in %dms\n",
+ __func__, comp, timedout ? "timedout" : "completed",
+ jiffies_to_msecs(timeout - HZ - jiffies));
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* Disable compander */
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_COMP0_B1_CTL + (comp * 8),
+ emask, 0x00);
+ /* Turn off the clock for compander in pair */
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RX_B2_CTL,
+ mask << comp_shift[comp], 0);
+ /* Set gain source to register */
+ tapan_config_gain_compander(codec, comp, false);
+ break;
+ }
+ return 0;
+}
+
static const char * const tapan_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
static const struct soc_enum tapan_ear_pa_gain_enum[] = {
SOC_ENUM_SINGLE_EXT(2, tapan_ear_pa_gain_text),
@@ -498,21 +742,40 @@
static const struct soc_enum cf_rxmix4_enum =
SOC_ENUM_SINGLE(TAPAN_A_CDC_RX4_B4_CTL, 0, 3, cf_text);
+static const char * const class_h_dsm_text[] = {
+ "ZERO", "RX_HPHL", "RX_SPKR"
+};
+
+static const struct soc_enum class_h_dsm_enum =
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_CLSH_CTL, 2, 3, class_h_dsm_text);
+
+static const struct snd_kcontrol_new class_h_dsm_mux =
+ SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);
+
static const struct snd_kcontrol_new tapan_snd_controls[] = {
SOC_ENUM_EXT("EAR PA Gain", tapan_ear_pa_gain_enum[0],
tapan_pa_gain_get, tapan_pa_gain_put),
- SOC_SINGLE_TLV("LINEOUT1 Volume", TAPAN_A_RX_LINE_1_GAIN, 0, 12, 1,
+ SOC_SINGLE_TLV("HPHL Volume", TAPAN_A_RX_HPH_L_GAIN, 0, 14, 1,
line_gain),
- SOC_SINGLE_TLV("LINEOUT2 Volume", TAPAN_A_RX_LINE_2_GAIN, 0, 12, 1,
+ SOC_SINGLE_TLV("HPHR Volume", TAPAN_A_RX_HPH_R_GAIN, 0, 14, 1,
line_gain),
- SOC_SINGLE_TLV("HPHL Volume", TAPAN_A_RX_HPH_L_GAIN, 0, 12, 1,
+ SOC_SINGLE_TLV("LINEOUT1 Volume", TAPAN_A_RX_LINE_1_GAIN, 0, 14, 1,
line_gain),
- SOC_SINGLE_TLV("HPHR Volume", TAPAN_A_RX_HPH_R_GAIN, 0, 12, 1,
+ SOC_SINGLE_TLV("LINEOUT2 Volume", TAPAN_A_RX_LINE_2_GAIN, 0, 14, 1,
line_gain),
+ SOC_SINGLE_TLV("SPK DRV Volume", TAPAN_A_SPKR_DRV_GAIN, 3, 7, 1,
+ line_gain),
+
+ SOC_SINGLE_TLV("ADC1 Volume", TAPAN_A_TX_1_EN, 2, 13, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", TAPAN_A_TX_2_EN, 2, 13, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC3 Volume", TAPAN_A_TX_3_EN, 2, 13, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC4 Volume", TAPAN_A_TX_4_EN, 2, 13, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC5 Volume", TAPAN_A_TX_5_EN, 2, 13, 0, analog_gain),
+
SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL,
-84, 40, digital_gain),
SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL,
@@ -540,9 +803,8 @@
SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAPAN_A_CDC_IIR1_GAIN_B4_CTL, -84,
40, digital_gain),
- SOC_SINGLE("MICBIAS1 CAPLESS Switch", TAPAN_A_MICB_1_CTL, 4, 1, 1),
- SOC_SINGLE("MICBIAS2 CAPLESS Switch", TAPAN_A_MICB_2_CTL, 4, 1, 1),
- SOC_SINGLE("MICBIAS3 CAPLESS Switch", TAPAN_A_MICB_3_CTL, 4, 1, 1),
+ SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, tapan_get_anc_slot,
+ tapan_put_anc_slot),
SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
@@ -606,11 +868,23 @@
SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+ SOC_SINGLE_EXT("COMP0 Switch", SND_SOC_NOPM, COMPANDER_0, 1, 0,
+ tapan_get_compander, tapan_set_compander),
+ SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
+ tapan_get_compander, tapan_set_compander),
+ SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
+ tapan_get_compander, tapan_set_compander),
+
};
-static const char * const rx_mix1_text[] = {
+static const char * const rx_1_2_mix1_text[] = {
"ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
- "RX5", "RX6", "RX7"
+ "RX5", "AUXRX", "AUXTX1"
+};
+
+static const char * const rx_3_4_mix1_text[] = {
+ "ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
+ "RX5", "AUXRX", "AUXTX1", "AUXTX2"
};
static const char * const rx_mix2_text[] = {
@@ -621,86 +895,85 @@
"DEM4", "DEM3_INV"
};
-static const char * const rx_rdac7_text[] = {
- "DEM6", "DEM5_INV"
-};
-
-static const char * const sb_tx1_mux_text[] = {
- "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
- "DEC1"
-};
-
-static const char * const sb_tx2_mux_text[] = {
- "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
- "DEC2"
+static const char * const sb_tx_1_2_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4",
+ "RSVD", "RSVD", "RSVD",
+ "DEC1", "DEC2", "DEC3", "DEC4"
};
static const char * const sb_tx3_mux_text[] = {
- "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
- "DEC3"
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4",
+ "RSVD", "RSVD", "RSVD", "RSVD", "RSVD",
+ "DEC3"
};
static const char * const sb_tx4_mux_text[] = {
- "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
- "DEC4"
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4",
+ "RSVD", "RSVD", "RSVD", "RSVD", "RSVD", "RSVD",
+ "DEC4"
};
-static const char * const dec1_mux_text[] = {
- "ZERO", "DMIC1", "ADC6",
+static const char * const sb_tx5_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4",
+ "RSVD", "RSVD", "RSVD",
+ "DEC1"
};
-static const char * const dec2_mux_text[] = {
- "ZERO", "DMIC2", "ADC5",
+static const char * const dec_1_2_mux_text[] = {
+ "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADCMB",
+ "DMIC1", "DMIC2", "DMIC3", "DMIC4"
};
static const char * const dec3_mux_text[] = {
- "ZERO", "DMIC3", "ADC4",
+ "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADCMB",
+ "DMIC1", "DMIC2", "DMIC3", "DMIC4",
+ "ANCFBTUNE1"
};
static const char * const dec4_mux_text[] = {
- "ZERO", "DMIC4", "ADC3",
+ "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADCMB",
+ "DMIC1", "DMIC2", "DMIC3", "DMIC4",
+ "ANCFBTUNE2"
};
static const char * const anc_mux_text[] = {
- "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
- "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
-};
-
-static const char * const anc1_fb_mux_text[] = {
- "ZERO", "EAR_HPH_L", "EAR_LINE_1",
+ "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5",
+ "RSVD", "RSVD", "RSVD",
+ "DMIC1", "DMIC2", "DMIC3", "DMIC4",
+ "RSVD", "RSVD"
};
static const char * const iir1_inp1_text[] = {
- "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
- "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
+ "ZERO", "DEC1", "DEC2", "DEC3", "DEC4",
+ "RX1", "RX2", "RX3", "RX4", "RX5"
};
static const struct soc_enum rx_mix1_inp1_chain_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_1_2_mix1_text);
static const struct soc_enum rx_mix1_inp2_chain_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_1_2_mix1_text);
static const struct soc_enum rx_mix1_inp3_chain_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_mix1_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_1_2_mix1_text);
static const struct soc_enum rx2_mix1_inp1_chain_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_1_2_mix1_text);
static const struct soc_enum rx2_mix1_inp2_chain_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_1_2_mix1_text);
static const struct soc_enum rx3_mix1_inp1_chain_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX3_B1_CTL, 0, 13, rx_3_4_mix1_text);
static const struct soc_enum rx3_mix1_inp2_chain_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX3_B1_CTL, 4, 13, rx_3_4_mix1_text);
static const struct soc_enum rx4_mix1_inp1_chain_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B1_CTL, 0, 13, rx_3_4_mix1_text);
static const struct soc_enum rx4_mix1_inp2_chain_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B1_CTL, 4, 13, rx_3_4_mix1_text);
static const struct soc_enum rx1_mix2_inp1_chain_enum =
SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B3_CTL, 0, 5, rx_mix2_text);
@@ -714,38 +987,52 @@
static const struct soc_enum rx2_mix2_inp2_chain_enum =
SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B3_CTL, 3, 5, rx_mix2_text);
+static const struct soc_enum rx4_mix2_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B3_CTL, 0, 5, rx_mix2_text);
+
+static const struct soc_enum rx4_mix2_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B3_CTL, 3, 5, rx_mix2_text);
+
static const struct soc_enum rx_rdac5_enum =
SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_MISC, 2, 2, rx_rdac5_text);
-static const struct soc_enum rx_rdac7_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_MISC, 1, 2, rx_rdac7_text);
-
static const struct soc_enum sb_tx1_mux_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B1_CTL, 0, 12,
+ sb_tx_1_2_mux_text);
static const struct soc_enum sb_tx2_mux_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B2_CTL, 0, 9, sb_tx2_mux_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B2_CTL, 0, 12,
+ sb_tx_1_2_mux_text);
static const struct soc_enum sb_tx3_mux_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B3_CTL, 0, 11, sb_tx3_mux_text);
static const struct soc_enum sb_tx4_mux_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B4_CTL, 0, 9, sb_tx4_mux_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B4_CTL, 0, 12, sb_tx4_mux_text);
+
+static const struct soc_enum sb_tx5_mux_enum =
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
static const struct soc_enum dec1_mux_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 0, 10, dec_1_2_mux_text);
static const struct soc_enum dec2_mux_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 4, 10, dec_1_2_mux_text);
static const struct soc_enum dec3_mux_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B2_CTL, 0, 12, dec3_mux_text);
static const struct soc_enum dec4_mux_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B2_CTL, 4, 12, dec4_mux_text);
+
+static const struct soc_enum anc1_mux_enum =
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_ANC_B1_CTL, 0, 15, anc_mux_text);
+
+static const struct soc_enum anc2_mux_enum =
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_ANC_B1_CTL, 4, 15, anc_mux_text);
static const struct soc_enum iir1_inp1_mux_enum =
- SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_EQ1_B1_CTL, 0, 10, iir1_inp1_text);
static const struct snd_kcontrol_new rx_mix1_inp1_mux =
SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
@@ -786,6 +1073,12 @@
static const struct snd_kcontrol_new rx2_mix2_inp2_mux =
SOC_DAPM_ENUM("RX2 MIX2 INP2 Mux", rx2_mix2_inp2_chain_enum);
+static const struct snd_kcontrol_new rx4_mix2_inp1_mux =
+ SOC_DAPM_ENUM("RX4 MIX2 INP1 Mux", rx4_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx4_mix2_inp2_mux =
+ SOC_DAPM_ENUM("RX4 MIX2 INP2 Mux", rx4_mix2_inp2_chain_enum);
+
static const struct snd_kcontrol_new rx_dac5_mux =
SOC_DAPM_ENUM("RDAC5 MUX Mux", rx_rdac5_enum);
@@ -801,9 +1094,8 @@
static const struct snd_kcontrol_new sb_tx4_mux =
SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);
-/*static const struct snd_kcontrol_new sb_tx5_mux =
+static const struct snd_kcontrol_new sb_tx5_mux =
SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
-*/
static int wcd9306_put_dec_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -851,23 +1143,17 @@
switch (decimator) {
case 1:
case 2:
+ if ((dec_mux >= 1) && (dec_mux <= 5))
+ adc_dmic_sel = 0x0;
+ else if ((dec_mux >= 6) && (dec_mux <= 9))
+ adc_dmic_sel = 0x1;
+ break;
case 3:
case 4:
- case 5:
- case 6:
- if (dec_mux == 1)
- adc_dmic_sel = 0x1;
- else
+ if ((dec_mux >= 1) && (dec_mux <= 6))
adc_dmic_sel = 0x0;
- break;
- case 7:
- case 8:
- case 9:
- case 10:
- if ((dec_mux == 1) || (dec_mux == 2))
+ else if ((dec_mux >= 7) && (dec_mux <= 10))
adc_dmic_sel = 0x1;
- else
- adc_dmic_sel = 0x0;
break;
default:
pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
@@ -908,6 +1194,12 @@
static const struct snd_kcontrol_new iir1_inp1_mux =
SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+static const struct snd_kcontrol_new anc1_mux =
+ SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
+
+static const struct snd_kcontrol_new anc2_mux =
+ SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
+
static const struct snd_kcontrol_new dac1_switch[] = {
SOC_DAPM_SINGLE("Switch", TAPAN_A_RX_EAR_EN, 5, 1, 0)
};
@@ -915,6 +1207,10 @@
SOC_DAPM_SINGLE("Switch", TAPAN_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
};
+static const struct snd_kcontrol_new spk_dac_switch[] = {
+ SOC_DAPM_SINGLE("Switch", TAPAN_A_SPKR_DRV_DAC_CTL, 2, 1, 0)
+};
+
static const struct snd_kcontrol_new hphl_pa_mix[] = {
SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
7, 1, 0),
@@ -939,15 +1235,6 @@
3, 1, 0),
};
-static const struct snd_kcontrol_new lineout3_pa_mix[] = {
- SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
- 2, 1, 0),
-};
-
-static const struct snd_kcontrol_new lineout4_pa_mix[] = {
- SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
- 1, 1, 0),
-};
/* virtual port entries */
static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
@@ -973,6 +1260,7 @@
u32 dai_id = widget->shift;
u32 port_id = mixer->shift;
u32 enable = ucontrol->value.integer.value[0];
+ u32 vtable = vport_check_table[dai_id];
dev_dbg(codec->dev, "%s: wname %s cname %s\n",
__func__, widget->name, ucontrol->id.name);
@@ -997,8 +1285,15 @@
/* only add to the list if value not set
*/
if (enable && !(widget->value & 1 << port_id)) {
+ if (tapan_p->intf_type ==
+ WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ vtable = vport_check_table[dai_id];
+ if (tapan_p->intf_type ==
+ WCD9XXX_INTERFACE_TYPE_I2C)
+ vtable = vport_i2s_check_table[dai_id];
+
if (wcd9xxx_tx_vport_validation(
- vport_check_table[dai_id],
+ vtable,
port_id,
tapan_p->dai)) {
dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
@@ -1009,27 +1304,29 @@
widget->value |= 1 << port_id;
list_add_tail(&core->tx_chs[port_id].list,
&tapan_p->dai[dai_id].wcd9xxx_ch_list
- );
+ );
} else if (!enable && (widget->value & 1 << port_id)) {
widget->value &= ~(1 << port_id);
list_del_init(&core->tx_chs[port_id].list);
} else {
if (enable)
- dev_dbg(codec->dev, "%s: TX%u port is used by this virtual port\n",
+ dev_dbg(codec->dev, "%s: TX%u port is used by\n"
+ "this virtual port\n",
__func__, port_id + 1);
else
- dev_dbg(codec->dev, "%s: TX%u port is not used by this virtual port\n",
+ dev_dbg(codec->dev, "%s: TX%u port is not used by\n"
+ "this virtual port\n",
__func__, port_id + 1);
/* avoid update power function */
mutex_unlock(&codec->mutex);
return 0;
}
break;
- default:
- pr_err("Unknown AIF %d\n", dai_id);
- mutex_unlock(&codec->mutex);
- return -EINVAL;
- }
+ default:
+ dev_err(codec->dev, "Unknown AIF %d\n", dai_id);
+ mutex_unlock(&codec->mutex);
+ return -EINVAL;
+ }
dev_dbg(codec->dev, "%s: name %s sname %s updated value %u shift %d\n",
__func__, widget->name, widget->sname,
widget->value, widget->shift);
@@ -1153,6 +1450,49 @@
slim_tx_mixer_get, slim_tx_mixer_put),
};
+static int tapan_codec_enable_adc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 adc_reg;
+ u8 init_bit_shift;
+
+ dev_dbg(codec->dev, "%s(): %s %d\n", __func__, w->name, event);
+
+ if (w->reg == TAPAN_A_TX_1_EN) {
+ init_bit_shift = 7;
+ adc_reg = TAPAN_A_TX_1_2_TEST_CTL;
+ } else if (w->reg == TAPAN_A_TX_2_EN) {
+ init_bit_shift = 6;
+ adc_reg = TAPAN_A_TX_1_2_TEST_CTL;
+ } else if (w->reg == TAPAN_A_TX_3_EN) {
+ init_bit_shift = 6;
+ adc_reg = TAPAN_A_TX_1_2_TEST_CTL;
+ } else if (w->reg == TAPAN_A_TX_4_EN) {
+ init_bit_shift = 7;
+ adc_reg = TAPAN_A_TX_4_5_TEST_CTL;
+ } else if (w->reg == TAPAN_A_TX_5_EN) {
+ init_bit_shift = 6;
+ adc_reg = TAPAN_A_TX_4_5_TEST_CTL;
+ } else {
+ pr_err("%s: Error, invalid adc register\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
+ 1 << init_bit_shift);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+
+ snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
+
+ break;
+ }
+ return 0;
+}
+
static int tapan_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -1188,6 +1528,7 @@
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
u16 lineout_gain_reg;
dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
@@ -1207,15 +1548,21 @@
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
break;
case SND_SOC_DAPM_POST_PMU:
- dev_dbg(codec->dev, "%s: sleeping 16 ms after %s PA turn on\n",
+ wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
+ WCD9XXX_CLSH_STATE_LO,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
+ dev_dbg(codec->dev, "%s: sleeping 3 ms after %s PA turn on\n",
__func__, w->name);
- usleep_range(16000, 16000);
+ usleep_range(3000, 3010);
break;
case SND_SOC_DAPM_POST_PMD:
- snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
+ wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
+ WCD9XXX_CLSH_STATE_LO,
+ WCD9XXX_CLSH_REQ_DISABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
break;
}
return 0;
@@ -1224,7 +1571,22 @@
static int tapan_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- dev_dbg(w->codec->dev, "%s %d %s\n", __func__, event, w->name);
+ struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "%s: %s %d\n", __func__, w->name, event);
+ WCD9XXX_BCL_LOCK(&tapan->resmgr);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ tapan->spkr_pa_widget_on = true;
+ snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80, 0x80);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ tapan->spkr_pa_widget_on = false;
+ snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80, 0x00);
+ break;
+ }
+ WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
return 0;
}
@@ -1239,7 +1601,7 @@
unsigned int dmic;
int ret;
- ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
+ ret = kstrtouint(strpbrk(w->name, "1234"), 10, &dmic);
if (ret < 0) {
pr_err("%s: Invalid DMIC line on the codec\n", __func__);
return -EINVAL;
@@ -1266,17 +1628,6 @@
__func__, event, dmic, *dmic_clk_cnt);
break;
- case 5:
- case 6:
- dmic_clk_en = 0x01;
- dmic_clk_cnt = &(tapan->dmic_5_6_clk_cnt);
- dmic_clk_reg = TAPAN_A_CDC_CLK_DMIC_B2_CTL;
-
- dev_dbg(codec->dev, "%s() event %d DMIC%d dmic_5_6_clk_cnt %d\n",
- __func__, event, dmic, *dmic_clk_cnt);
-
- break;
-
default:
pr_err("%s: Invalid DMIC Selection\n", __func__);
return -EINVAL;
@@ -1600,7 +1951,7 @@
msecs_to_jiffies(300));
}
/* apply the digital gain after the decimator is enabled*/
- if ((w->shift) < ARRAY_SIZE(tx_digital_gain_reg))
+ if ((w->shift + offset) < ARRAY_SIZE(tx_digital_gain_reg))
snd_soc_write(codec,
tx_digital_gain_reg[w->shift + offset],
snd_soc_read(codec,
@@ -1628,6 +1979,42 @@
return ret;
}
+static int tapan_codec_enable_vdd_spkr(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+
+ dev_dbg(codec->dev, "%s: %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+
+ if (spkr_drv_wrnd > 0) {
+ WARN_ON(!(snd_soc_read(codec, TAPAN_A_SPKR_DRV_EN) &
+ 0x80));
+ snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80,
+ 0x00);
+ }
+ if (TAPAN_IS_1_0(core->version))
+ snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_DBG_PWRSTG,
+ 0x24, 0x00);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (TAPAN_IS_1_0(core->version))
+ snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_DBG_PWRSTG,
+ 0x24, 0x24);
+ if (spkr_drv_wrnd > 0) {
+ WARN_ON(!!(snd_soc_read(codec, TAPAN_A_SPKR_DRV_EN) &
+ 0x80));
+ snd_soc_update_bits(codec, TAPAN_A_SPKR_DRV_EN, 0x80,
+ 0x80);
+ }
+ break;
+ }
+ return 0;
+}
+
static int tapan_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -1685,18 +2072,53 @@
}
return 0;
}
-static int tapan_hphr_dac_event(struct snd_soc_dapm_widget *w,
+
+
+static int tapan_hphl_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL,
+ 0x02, 0x02);
+ wcd9xxx_clsh_fsm(codec, &tapan_p->clsh_d,
+ WCD9XXX_CLSH_STATE_HPHL,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_PRE_DAC);
break;
case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL,
+ 0x02, 0x00);
+ }
+ return 0;
+}
+
+static int tapan_hphr_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL,
+ 0x04, 0x04);
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ wcd9xxx_clsh_fsm(codec, &tapan_p->clsh_d,
+ WCD9XXX_CLSH_STATE_HPHR,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_PRE_DAC);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL,
+ 0x04, 0x00);
snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
break;
}
@@ -1709,14 +2131,17 @@
struct snd_soc_codec *codec = w->codec;
struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
enum wcd9xxx_notify_event e_pre_on, e_post_off;
+ u8 req_clsh_state;
dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
if (w->shift == 5) {
e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
+ req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
} else if (w->shift == 4) {
e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
+ req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
} else {
pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
return -EINVAL;
@@ -1729,43 +2154,51 @@
break;
case SND_SOC_DAPM_POST_PMU:
- usleep_range(10000, 10000);
+ wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
+ req_clsh_state,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_5, 0x02, 0x00);
- snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x20, 0x00);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x04, 0x04);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x08, 0x00);
- usleep_range(10, 10);
+ usleep_range(5000, 5010);
break;
case SND_SOC_DAPM_POST_PMD:
/* Let MBHC module know PA turned off */
wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_off);
- /*
- * schedule work is required because at the time HPH PA DAPM
- * event callback is called by DAPM framework, CODEC dapm mutex
- * would have been locked while snd_soc_jack_report also
- * attempts to acquire same lock.
- */
+ wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
+ req_clsh_state,
+ WCD9XXX_CLSH_REQ_DISABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
+
dev_dbg(codec->dev, "%s: sleep 10 ms after %s PA disable.\n",
__func__, w->name);
- usleep_range(5000, 5000);
+ usleep_range(5000, 5010);
break;
}
return 0;
}
+static const struct snd_soc_dapm_widget tapan_dapm_i2s_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("I2S_CLK", TAPAN_A_CDC_CLK_I2S_CTL,
+ 4, 0, NULL, 0),
+};
+
static int tapan_lineout_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ wcd9xxx_clsh_fsm(codec, &tapan->clsh_d,
+ WCD9XXX_CLSH_STATE_LO,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_PRE_DAC);
snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
break;
@@ -1786,12 +2219,12 @@
}
static const struct snd_soc_dapm_route audio_i2s_map[] = {
- {"RX_I2S_CLK", NULL, "CDC_CONN"},
- {"SLIM RX1", NULL, "RX_I2S_CLK"},
- {"SLIM RX2", NULL, "RX_I2S_CLK"},
+ {"I2S_CLK", NULL, "CDC_CONN"},
+ {"SLIM RX1", NULL, "I2S_CLK"},
+ {"SLIM RX2", NULL, "I2S_CLK"},
- {"SLIM TX1 MUX", NULL, "TX_I2S_CLK"},
- {"SLIM TX2 MUX", NULL, "TX_I2S_CLK"},
+ {"SLIM TX1 MUX", NULL, "I2S_CLK"},
+ {"SLIM TX2 MUX", NULL, "I2S_CLK"},
};
static const struct snd_soc_dapm_route audio_map[] = {
@@ -1806,122 +2239,60 @@
{"AIF1_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
{"AIF1_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
{"AIF1_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
- {"AIF1_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
- {"AIF1_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
- {"AIF1_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
- {"AIF1_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
- {"AIF1_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
/* SLIM_MIXER("AIF2_CAP Mixer"),*/
{"AIF2_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
{"AIF2_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
{"AIF2_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
{"AIF2_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
{"AIF2_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
- {"AIF2_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
- {"AIF2_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
- {"AIF2_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
- {"AIF2_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
- {"AIF2_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
/* SLIM_MIXER("AIF3_CAP Mixer"),*/
{"AIF3_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
{"AIF3_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
{"AIF3_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
{"AIF3_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
{"AIF3_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
- {"AIF3_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
- {"AIF3_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
- {"AIF3_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
- {"AIF3_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
- {"AIF3_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
{"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
+ {"SLIM TX1 MUX", "DEC2", "DEC2 MUX"},
+ {"SLIM TX1 MUX", "DEC3", "DEC3 MUX"},
+ {"SLIM TX1 MUX", "DEC4", "DEC4 MUX"},
+ {"SLIM TX1 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX1 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX1 MUX", "RMIX3", "RX3 MIX1"},
+ {"SLIM TX1 MUX", "RMIX4", "RX4 MIX1"},
+ {"SLIM TX2 MUX", "DEC1", "DEC1 MUX"},
{"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
+ {"SLIM TX2 MUX", "DEC3", "DEC3 MUX"},
+ {"SLIM TX2 MUX", "DEC4", "DEC4 MUX"},
+ {"SLIM TX2 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX2 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX2 MUX", "RMIX3", "RX3 MIX1"},
+ {"SLIM TX2 MUX", "RMIX4", "RX4 MIX1"},
{"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
{"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
{"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
{"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
{"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
- {"SLIM TX3 MUX", "RMIX5", "RX5 MIX1"},
- {"SLIM TX3 MUX", "RMIX6", "RX6 MIX1"},
- {"SLIM TX3 MUX", "RMIX7", "RX7 MIX1"},
{"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
+ {"SLIM TX4 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX4 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX4 MUX", "RMIX3", "RX3 MIX1"},
+ {"SLIM TX4 MUX", "RMIX4", "RX4 MIX1"},
- {"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
+ {"SLIM TX5 MUX", "DEC1", "DEC1 MUX"},
{"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
{"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
{"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
{"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
- {"SLIM TX5 MUX", "RMIX5", "RX5 MIX1"},
- {"SLIM TX5 MUX", "RMIX6", "RX6 MIX1"},
- {"SLIM TX5 MUX", "RMIX7", "RX7 MIX1"},
-
- {"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
-
- {"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
- {"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
- {"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
- {"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
- {"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
- {"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
- {"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
- {"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
- {"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
- {"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
- {"SLIM TX7 MUX", "RMIX1", "RX1 MIX1"},
- {"SLIM TX7 MUX", "RMIX2", "RX2 MIX1"},
- {"SLIM TX7 MUX", "RMIX3", "RX3 MIX1"},
- {"SLIM TX7 MUX", "RMIX4", "RX4 MIX1"},
- {"SLIM TX7 MUX", "RMIX5", "RX5 MIX1"},
- {"SLIM TX7 MUX", "RMIX6", "RX6 MIX1"},
- {"SLIM TX7 MUX", "RMIX7", "RX7 MIX1"},
-
- {"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
- {"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
- {"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
- {"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
- {"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
- {"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
- {"SLIM TX8 MUX", "DEC7", "DEC7 MUX"},
- {"SLIM TX8 MUX", "DEC8", "DEC8 MUX"},
- {"SLIM TX8 MUX", "DEC9", "DEC9 MUX"},
- {"SLIM TX8 MUX", "DEC10", "DEC10 MUX"},
-
- {"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
- {"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
- {"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
- {"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
- {"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
- {"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
- {"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
- {"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
- {"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
- {"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
-
- {"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
- {"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
- {"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
- {"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
- {"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
- {"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
- {"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
- {"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
- {"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
- {"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
/* Earpiece (RX MIX1) */
{"EAR", NULL, "EAR PA"},
{"EAR PA", NULL, "EAR_PA_MIXER"},
{"EAR_PA_MIXER", NULL, "DAC1"},
- {"DAC1", NULL, "CP"},
- {"CP", NULL, "CLASS_H_EAR"},
- {"CLASS_H_EAR", NULL, "CLASS_H_CLK"},
-
- {"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
- {"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
- {"ANC", NULL, "ANC1 FB MUX"},
+ {"DAC1", NULL, "RX_BIAS"},
/* Headset (RX MIX1 and RX MIX2) */
{"HEADPHONE", NULL, "HPHL"},
@@ -1929,93 +2300,47 @@
{"HPHL", NULL, "HPHL_PA_MIXER"},
{"HPHL_PA_MIXER", NULL, "HPHL DAC"},
+ {"HPHL DAC", NULL, "RX_BIAS"},
{"HPHR", NULL, "HPHR_PA_MIXER"},
{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
+ {"HPHR DAC", NULL, "RX_BIAS"},
- {"HPHL DAC", NULL, "CP"},
- {"CP", NULL, "CLASS_H_HPH_L"},
- {"CLASS_H_HPH_L", NULL, "CLASS_H_CLK"},
-
- {"HPHR DAC", NULL, "CP"},
- {"CP", NULL, "CLASS_H_HPH_R"},
- {"CLASS_H_HPH_R", NULL, "CLASS_H_CLK"},
-
- {"ANC", NULL, "ANC1 MUX"},
- {"ANC", NULL, "ANC2 MUX"},
- {"ANC1 MUX", "ADC1", "ADC1"},
- {"ANC1 MUX", "ADC2", "ADC2"},
- {"ANC1 MUX", "ADC3", "ADC3"},
- {"ANC1 MUX", "ADC4", "ADC4"},
- {"ANC2 MUX", "ADC1", "ADC1"},
- {"ANC2 MUX", "ADC2", "ADC2"},
- {"ANC2 MUX", "ADC3", "ADC3"},
- {"ANC2 MUX", "ADC4", "ADC4"},
-
- {"ANC", NULL, "CDC_CONN"},
-
- {"DAC1", "Switch", "RX1 CHAIN"},
- {"HPHL DAC", "Switch", "RX1 CHAIN"},
+ {"DAC1", "Switch", "CLASS_H_DSM MUX"},
+ {"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
{"HPHR DAC", NULL, "RX2 CHAIN"},
{"LINEOUT1", NULL, "LINEOUT1 PA"},
{"LINEOUT2", NULL, "LINEOUT2 PA"},
- {"LINEOUT3", NULL, "LINEOUT3 PA"},
- {"LINEOUT4", NULL, "LINEOUT4 PA"},
{"SPK_OUT", NULL, "SPK PA"},
- {"LINEOUT1 PA", NULL, "CP"},
{"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
{"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
- {"LINEOUT2 PA", NULL, "CP"},
{"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
{"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
- {"LINEOUT3 PA", NULL, "CP"},
- {"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
- {"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
-
- {"LINEOUT4 PA", NULL, "CP"},
- {"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
- {"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
-
- {"CP", NULL, "CLASS_H_LINEOUTS_PA"},
- {"CLASS_H_LINEOUTS_PA", NULL, "CLASS_H_CLK"},
-
{"LINEOUT1 DAC", NULL, "RX3 MIX1"},
{"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
- {"RDAC5 MUX", "DEM4", "RX4 MIX1"},
+ {"RDAC5 MUX", "DEM4", "RX4 MIX2"},
- {"LINEOUT3 DAC", NULL, "RDAC5 MUX"},
-
- {"LINEOUT2 DAC", NULL, "RX5 MIX1"},
-
- {"RDAC7 MUX", "DEM5_INV", "RX5 MIX1"},
- {"RDAC7 MUX", "DEM6", "RX6 MIX1"},
-
- {"LINEOUT4 DAC", NULL, "RDAC7 MUX"},
+ {"LINEOUT2 DAC", NULL, "RDAC5 MUX"},
{"SPK PA", NULL, "SPK DAC"},
- {"SPK DAC", NULL, "RX7 MIX2"},
+ {"SPK DAC", "Switch", "RX4 MIX2"},
+ {"SPK DAC", NULL, "VDD_SPKDRV"},
{"RX1 CHAIN", NULL, "RX1 MIX2"},
{"RX2 CHAIN", NULL, "RX2 MIX2"},
- {"RX1 CHAIN", NULL, "ANC"},
- {"RX2 CHAIN", NULL, "ANC"},
+ {"CLASS_H_DSM MUX", "RX_HPHL", "RX1 CHAIN"},
- {"CLASS_H_CLK", NULL, "RX_BIAS"},
{"LINEOUT1 DAC", NULL, "RX_BIAS"},
{"LINEOUT2 DAC", NULL, "RX_BIAS"},
- {"LINEOUT3 DAC", NULL, "RX_BIAS"},
- {"LINEOUT4 DAC", NULL, "RX_BIAS"},
- {"SPK DAC", NULL, "RX_BIAS"},
{"RX1 MIX1", NULL, "COMP1_CLK"},
{"RX2 MIX1", NULL, "COMP1_CLK"},
{"RX3 MIX1", NULL, "COMP2_CLK"},
- {"RX5 MIX1", NULL, "COMP2_CLK"},
{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
@@ -2026,21 +2351,15 @@
{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
{"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
{"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
- {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
- {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
- {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
- {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
- {"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
- {"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
{"RX1 MIX2", NULL, "RX1 MIX1"},
{"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
{"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
{"RX2 MIX2", NULL, "RX2 MIX1"},
{"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
{"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
- {"RX7 MIX2", NULL, "RX7 MIX1"},
- {"RX7 MIX2", NULL, "RX7 MIX2 INP1"},
- {"RX7 MIX2", NULL, "RX7 MIX2 INP2"},
+ {"RX4 MIX2", NULL, "RX4 MIX1"},
+ {"RX4 MIX2", NULL, "RX4 MIX2 INP1"},
+ {"RX4 MIX2", NULL, "RX4 MIX2 INP2"},
/* SLIM_MUX("AIF1_PB", "AIF1 PB"),*/
{"SLIM RX1 MUX", "AIF1_PB", "AIF1 PB"},
@@ -2048,198 +2367,128 @@
{"SLIM RX3 MUX", "AIF1_PB", "AIF1 PB"},
{"SLIM RX4 MUX", "AIF1_PB", "AIF1 PB"},
{"SLIM RX5 MUX", "AIF1_PB", "AIF1 PB"},
- {"SLIM RX6 MUX", "AIF1_PB", "AIF1 PB"},
- {"SLIM RX7 MUX", "AIF1_PB", "AIF1 PB"},
/* SLIM_MUX("AIF2_PB", "AIF2 PB"),*/
{"SLIM RX1 MUX", "AIF2_PB", "AIF2 PB"},
{"SLIM RX2 MUX", "AIF2_PB", "AIF2 PB"},
{"SLIM RX3 MUX", "AIF2_PB", "AIF2 PB"},
{"SLIM RX4 MUX", "AIF2_PB", "AIF2 PB"},
{"SLIM RX5 MUX", "AIF2_PB", "AIF2 PB"},
- {"SLIM RX6 MUX", "AIF2_PB", "AIF2 PB"},
- {"SLIM RX7 MUX", "AIF2_PB", "AIF2 PB"},
/* SLIM_MUX("AIF3_PB", "AIF3 PB"),*/
{"SLIM RX1 MUX", "AIF3_PB", "AIF3 PB"},
{"SLIM RX2 MUX", "AIF3_PB", "AIF3 PB"},
{"SLIM RX3 MUX", "AIF3_PB", "AIF3 PB"},
{"SLIM RX4 MUX", "AIF3_PB", "AIF3 PB"},
{"SLIM RX5 MUX", "AIF3_PB", "AIF3 PB"},
- {"SLIM RX6 MUX", "AIF3_PB", "AIF3 PB"},
- {"SLIM RX7 MUX", "AIF3_PB", "AIF3 PB"},
{"SLIM RX1", NULL, "SLIM RX1 MUX"},
{"SLIM RX2", NULL, "SLIM RX2 MUX"},
{"SLIM RX3", NULL, "SLIM RX3 MUX"},
{"SLIM RX4", NULL, "SLIM RX4 MUX"},
{"SLIM RX5", NULL, "SLIM RX5 MUX"},
- {"SLIM RX6", NULL, "SLIM RX6 MUX"},
- {"SLIM RX7", NULL, "SLIM RX7 MUX"},
{"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
{"RX1 MIX1 INP1", "RX5", "SLIM RX5"},
- {"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
- {"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX1 MIX1 INP1", "IIR1", "IIR1"},
{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
{"RX1 MIX1 INP2", "RX5", "SLIM RX5"},
- {"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
- {"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX1 MIX1 INP2", "IIR1", "IIR1"},
{"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
{"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
{"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
{"RX1 MIX1 INP3", "RX4", "SLIM RX4"},
{"RX1 MIX1 INP3", "RX5", "SLIM RX5"},
- {"RX1 MIX1 INP3", "RX6", "SLIM RX6"},
- {"RX1 MIX1 INP3", "RX7", "SLIM RX7"},
{"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
{"RX2 MIX1 INP1", "RX5", "SLIM RX5"},
- {"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
- {"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX2 MIX1 INP1", "IIR1", "IIR1"},
{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
{"RX2 MIX1 INP2", "RX5", "SLIM RX5"},
- {"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
- {"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX2 MIX1 INP2", "IIR1", "IIR1"},
{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
{"RX3 MIX1 INP1", "RX5", "SLIM RX5"},
- {"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
- {"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX3 MIX1 INP1", "IIR1", "IIR1"},
{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
{"RX3 MIX1 INP2", "RX5", "SLIM RX5"},
- {"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
- {"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX3 MIX1 INP2", "IIR1", "IIR1"},
{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
{"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
{"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
- {"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
- {"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX4 MIX1 INP1", "IIR1", "IIR1"},
{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
{"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
{"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
- {"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
- {"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX4 MIX1 INP2", "IIR1", "IIR1"},
- {"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
- {"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
- {"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
- {"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
- {"RX5 MIX1 INP1", "RX5", "SLIM RX5"},
- {"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
- {"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
- {"RX5 MIX1 INP1", "IIR1", "IIR1"},
- {"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
- {"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
- {"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
- {"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
- {"RX5 MIX1 INP2", "RX5", "SLIM RX5"},
- {"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
- {"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
- {"RX5 MIX1 INP2", "IIR1", "IIR1"},
- {"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
- {"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
- {"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
- {"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
- {"RX6 MIX1 INP1", "RX5", "SLIM RX5"},
- {"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
- {"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
- {"RX6 MIX1 INP1", "IIR1", "IIR1"},
- {"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
- {"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
- {"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
- {"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
- {"RX6 MIX1 INP2", "RX5", "SLIM RX5"},
- {"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
- {"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
- {"RX6 MIX1 INP2", "IIR1", "IIR1"},
- {"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
- {"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
- {"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
- {"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
- {"RX7 MIX1 INP1", "RX5", "SLIM RX5"},
- {"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
- {"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
- {"RX7 MIX1 INP1", "IIR1", "IIR1"},
- {"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
- {"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
- {"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
- {"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
- {"RX7 MIX1 INP2", "RX5", "SLIM RX5"},
- {"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
- {"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
- {"RX7 MIX1 INP2", "IIR1", "IIR1"},
+
{"RX1 MIX2 INP1", "IIR1", "IIR1"},
{"RX1 MIX2 INP2", "IIR1", "IIR1"},
{"RX2 MIX2 INP1", "IIR1", "IIR1"},
{"RX2 MIX2 INP2", "IIR1", "IIR1"},
- {"RX7 MIX2 INP1", "IIR1", "IIR1"},
- {"RX7 MIX2 INP2", "IIR1", "IIR1"},
+ {"RX4 MIX2 INP1", "IIR1", "IIR1"},
+ {"RX4 MIX2 INP2", "IIR1", "IIR1"},
/* Decimator Inputs */
+ {"DEC1 MUX", "ADC1", "ADC1"},
+ {"DEC1 MUX", "ADC2", "ADC2"},
+ {"DEC1 MUX", "ADC3", "ADC3"},
+ {"DEC1 MUX", "ADC4", "ADC4"},
{"DEC1 MUX", "DMIC1", "DMIC1"},
- {"DEC1 MUX", "ADC6", "ADC6"},
+ {"DEC1 MUX", "DMIC2", "DMIC2"},
+ {"DEC1 MUX", "DMIC3", "DMIC3"},
+ {"DEC1 MUX", "DMIC4", "DMIC4"},
{"DEC1 MUX", NULL, "CDC_CONN"},
+
+ {"DEC2 MUX", "ADC1", "ADC1"},
+ {"DEC2 MUX", "ADC2", "ADC2"},
+ {"DEC2 MUX", "ADC3", "ADC3"},
+ {"DEC2 MUX", "ADC4", "ADC4"},
+ {"DEC2 MUX", "DMIC1", "DMIC1"},
{"DEC2 MUX", "DMIC2", "DMIC2"},
- {"DEC2 MUX", "ADC5", "ADC5"},
+ {"DEC2 MUX", "DMIC3", "DMIC3"},
+ {"DEC2 MUX", "DMIC4", "DMIC4"},
{"DEC2 MUX", NULL, "CDC_CONN"},
- {"DEC3 MUX", "DMIC3", "DMIC3"},
+
+ {"DEC3 MUX", "ADC1", "ADC1"},
+ {"DEC3 MUX", "ADC2", "ADC2"},
+ {"DEC3 MUX", "ADC3", "ADC3"},
{"DEC3 MUX", "ADC4", "ADC4"},
+ {"DEC3 MUX", "ADC5", "ADC5"},
+ {"DEC3 MUX", "DMIC1", "DMIC1"},
+ {"DEC3 MUX", "DMIC2", "DMIC2"},
+ {"DEC3 MUX", "DMIC3", "DMIC3"},
+ {"DEC3 MUX", "DMIC4", "DMIC4"},
{"DEC3 MUX", NULL, "CDC_CONN"},
- {"DEC4 MUX", "DMIC4", "DMIC4"},
+
+ {"DEC4 MUX", "ADC1", "ADC1"},
+ {"DEC4 MUX", "ADC2", "ADC2"},
{"DEC4 MUX", "ADC3", "ADC3"},
+ {"DEC4 MUX", "ADC4", "ADC4"},
+ {"DEC4 MUX", "ADC5", "ADC5"},
+ {"DEC4 MUX", "DMIC1", "DMIC1"},
+ {"DEC4 MUX", "DMIC2", "DMIC2"},
+ {"DEC4 MUX", "DMIC3", "DMIC3"},
+ {"DEC4 MUX", "DMIC4", "DMIC4"},
{"DEC4 MUX", NULL, "CDC_CONN"},
- {"DEC5 MUX", "DMIC5", "DMIC5"},
- {"DEC5 MUX", "ADC2", "ADC2"},
- {"DEC5 MUX", NULL, "CDC_CONN"},
- {"DEC6 MUX", "DMIC6", "DMIC6"},
- {"DEC6 MUX", "ADC1", "ADC1"},
- {"DEC6 MUX", NULL, "CDC_CONN"},
- {"DEC7 MUX", "DMIC1", "DMIC1"},
- {"DEC7 MUX", "DMIC6", "DMIC6"},
- {"DEC7 MUX", "ADC1", "ADC1"},
- {"DEC7 MUX", "ADC6", "ADC6"},
- {"DEC7 MUX", NULL, "CDC_CONN"},
- {"DEC8 MUX", "DMIC2", "DMIC2"},
- {"DEC8 MUX", "DMIC5", "DMIC5"},
- {"DEC8 MUX", "ADC2", "ADC2"},
- {"DEC8 MUX", "ADC5", "ADC5"},
- {"DEC8 MUX", NULL, "CDC_CONN"},
- {"DEC9 MUX", "DMIC4", "DMIC4"},
- {"DEC9 MUX", "DMIC5", "DMIC5"},
- {"DEC9 MUX", "ADC2", "ADC2"},
- {"DEC9 MUX", "ADC3", "ADC3"},
- {"DEC9 MUX", NULL, "CDC_CONN"},
- {"DEC10 MUX", "DMIC3", "DMIC3"},
- {"DEC10 MUX", "DMIC6", "DMIC6"},
- {"DEC10 MUX", "ADC1", "ADC1"},
- {"DEC10 MUX", "ADC4", "ADC4"},
- {"DEC10 MUX", NULL, "CDC_CONN"},
/* ADC Connections */
{"ADC1", NULL, "AMIC1"},
@@ -2247,7 +2496,6 @@
{"ADC3", NULL, "AMIC3"},
{"ADC4", NULL, "AMIC4"},
{"ADC5", NULL, "AMIC5"},
- {"ADC6", NULL, "AMIC6"},
/* AUX PGA Connections */
{"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
@@ -2255,22 +2503,13 @@
{"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
{"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
{"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
- {"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
- {"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
{"AUX_PGA_Left", NULL, "AMIC5"},
- {"AUX_PGA_Right", NULL, "AMIC6"},
{"IIR1", NULL, "IIR1 INP1 MUX"},
{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
{"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
{"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
{"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
- {"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
- {"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
- {"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
- {"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
- {"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
- {"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
{"MIC BIAS1 Internal1", NULL, "LDO_H"},
{"MIC BIAS1 Internal2", NULL, "LDO_H"},
@@ -2282,7 +2521,6 @@
{"MIC BIAS3 Internal1", NULL, "LDO_H"},
{"MIC BIAS3 Internal2", NULL, "LDO_H"},
{"MIC BIAS3 External", NULL, "LDO_H"},
- {"MIC BIAS4 External", NULL, "LDO_H"},
};
static int tapan_readable(struct snd_soc_codec *ssc, unsigned int reg)
@@ -2313,7 +2551,7 @@
static int tapan_volatile(struct snd_soc_codec *ssc, unsigned int reg)
{
/* Registers lower than 0x100 are top level registers which can be
- * written by the Taiko core driver.
+ * written by the Tapan core driver.
*/
if ((reg >= TAPAN_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
@@ -2445,6 +2683,40 @@
static int tapan_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
+ u8 val = 0;
+ struct snd_soc_codec *codec = dai->codec;
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "%s\n", __func__);
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ /* CPU is master */
+ if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ if (dai->id == AIF1_CAP)
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CLK_I2S_CTL,
+ TAPAN_I2S_MASTER_MODE_MASK, 0);
+ else if (dai->id == AIF1_PB)
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CLK_I2S_CTL,
+ TAPAN_I2S_MASTER_MODE_MASK, 0);
+ }
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ /* CPU is slave */
+ if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ val = TAPAN_I2S_MASTER_MODE_MASK;
+ if (dai->id == AIF1_CAP)
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CLK_I2S_CTL, val, val);
+ else if (dai->id == AIF1_PB)
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CLK_I2S_CTL, val, val);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
return 0;
}
@@ -2490,7 +2762,7 @@
}
list_for_each_entry(ch, &tapan_p->dai[dai->id].wcd9xxx_ch_list,
list) {
- dev_dbg(dai->codec->dev, "%s: rx_slot[%d] %d ch->ch_num %d\n",
+ dev_dbg(dai->codec->dev, "%s: rx_slot[%d] %d, ch->ch_num %d\n",
__func__, i, rx_slot[i], ch->ch_num);
rx_slot[i++] = ch->ch_num;
}
@@ -2524,7 +2796,7 @@
}
static int tapan_set_interpolator_rate(struct snd_soc_dai *dai,
- u8 rx_fs_rate_reg_val, u32 sample_rate)
+ u8 rx_fs_rate_reg_val, u32 compander_fs, u32 sample_rate)
{
u32 j;
u8 rx_mix1_inp;
@@ -2540,7 +2812,7 @@
rx_mix1_inp = ch->port + RX_MIX1_INP_SEL_RX1 -
TAPAN_TX_PORT_NUMBER;
if ((rx_mix1_inp < RX_MIX1_INP_SEL_RX1) ||
- (rx_mix1_inp > RX_MIX1_INP_SEL_RX7)) {
+ (rx_mix1_inp > RX_MIX1_INP_SEL_RX5)) {
pr_err("%s: Invalid TAPAN_RX%u port. Dai ID is %d\n",
__func__, rx_mix1_inp - 5 , dai->id);
return -EINVAL;
@@ -2572,6 +2844,9 @@
snd_soc_update_bits(codec, rx_fs_reg,
0xE0, rx_fs_rate_reg_val);
+ if (comp_rx_path[j] < COMPANDER_MAX)
+ tapan->comp_fs[comp_rx_path[j]]
+ = compander_fs;
}
if (j <= 2)
rx_mix_1_reg_1 += 3;
@@ -2599,7 +2874,7 @@
dev_dbg(codec->dev, "%s: dai->id = %d, tx_port = %d",
__func__, dai->id, tx_port);
- if ((tx_port < 1) || (tx_port > NUM_DECIMATORS)) {
+ if ((tx_port < 1) || (tx_port > TAPAN_SLIM_CODEC_TX_PORTS)) {
pr_err("%s: Invalid SLIM TX%u port. DAI ID is %d\n",
__func__, tx_port, dai->id);
return -EINVAL;
@@ -2610,23 +2885,15 @@
decimator = 0;
- if ((tx_port >= 1) && (tx_port <= 6)) {
+ tx_port_reg_val = tx_port_reg_val & 0x0F;
- tx_port_reg_val = tx_port_reg_val & 0x0F;
- if (tx_port_reg_val == 0x8)
- decimator = tx_port;
-
- } else if ((tx_port >= 7) && (tx_port <= NUM_DECIMATORS)) {
-
- tx_port_reg_val = tx_port_reg_val & 0x1F;
-
- if ((tx_port_reg_val >= 0x8) &&
+ if ((tx_port_reg_val >= 0x8) &&
(tx_port_reg_val <= 0x11)) {
decimator = (tx_port_reg_val - 0x8) + 1;
- }
}
+
if (decimator) { /* SLIM_TX port has a DEC as input */
tx_fs_reg = TAPAN_A_CDC_TX1_CLK_FS_CTL +
@@ -2640,7 +2907,7 @@
} else {
if ((tx_port_reg_val >= 0x1) &&
- (tx_port_reg_val <= 0x7)) {
+ (tx_port_reg_val <= 0x4)) {
dev_dbg(codec->dev, "%s: RMIX%u going to SLIM TX%u\n",
__func__, tx_port_reg_val, tx_port);
@@ -2673,8 +2940,10 @@
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
+ struct snd_soc_codec *codec = dai->codec;
struct tapan_priv *tapan = snd_soc_codec_get_drvdata(dai->codec);
u8 tx_fs_rate, rx_fs_rate;
+ u32 compander_fs;
int ret;
dev_dbg(dai->codec->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
@@ -2685,26 +2954,32 @@
case 8000:
tx_fs_rate = 0x00;
rx_fs_rate = 0x00;
+ compander_fs = COMPANDER_FS_8KHZ;
break;
case 16000:
tx_fs_rate = 0x01;
rx_fs_rate = 0x20;
+ compander_fs = COMPANDER_FS_16KHZ;
break;
case 32000:
tx_fs_rate = 0x02;
rx_fs_rate = 0x40;
+ compander_fs = COMPANDER_FS_32KHZ;
break;
case 48000:
tx_fs_rate = 0x03;
rx_fs_rate = 0x60;
+ compander_fs = COMPANDER_FS_48KHZ;
break;
case 96000:
tx_fs_rate = 0x04;
rx_fs_rate = 0x80;
+ compander_fs = COMPANDER_FS_96KHZ;
break;
case 192000:
tx_fs_rate = 0x05;
rx_fs_rate = 0xA0;
+ compander_fs = COMPANDER_FS_192KHZ;
break;
default:
pr_err("%s: Invalid sampling rate %d\n", __func__,
@@ -2722,31 +2997,85 @@
return ret;
}
- if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
- pr_err("%s: I2C interface not yet supported\n",
- __func__);
- else
- tapan->dai[dai->id].rate = params_rate(params);
-
+ if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CLK_I2S_CTL,
+ 0x20, 0x20);
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CLK_I2S_CTL,
+ 0x20, 0x00);
+ break;
+ default:
+ pr_err("invalid format\n");
+ break;
+ }
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_I2S_CTL,
+ 0x07, tx_fs_rate);
+ } else {
+ tapan->dai[dai->id].rate = params_rate(params);
+ }
break;
case SNDRV_PCM_STREAM_PLAYBACK:
ret = tapan_set_interpolator_rate(dai, rx_fs_rate,
+ compander_fs,
params_rate(params));
if (ret < 0) {
- pr_err("%s: set decimator rate failed %d\n", __func__,
- ret);
+ dev_err(codec->dev, "%s: set decimator rate failed %d\n",
+ __func__, ret);
return ret;
}
- if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
- pr_err("%s: I2C interface not yet supported\n",
- __func__);
- else
+ if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CLK_I2S_CTL,
+ 0x20, 0x20);
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CLK_I2S_CTL,
+ 0x20, 0x00);
+ break;
+ default:
+ dev_err(codec->dev, "invalid format\n");
+ break;
+ }
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_I2S_CTL,
+ 0x03, (rx_fs_rate >> 0x05));
+ } else {
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CONN_RX_SB_B1_CTL,
+ 0xFF, 0xAA);
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CONN_RX_SB_B2_CTL,
+ 0xFF, 0x2A);
+ tapan->dai[dai->id].bit_width = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CONN_RX_SB_B1_CTL,
+ 0xFF, 0x00);
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CONN_RX_SB_B2_CTL,
+ 0xFF, 0x00);
+ tapan->dai[dai->id].bit_width = 24;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid format\n");
+ break;
+ }
tapan->dai[dai->id].rate = params_rate(params);
-
+ }
break;
default:
- pr_err("%s: Invalid stream type %d\n", __func__,
+ dev_err(codec->dev, "%s: Invalid stream type %d\n", __func__,
substream->stream);
return -EINVAL;
}
@@ -2882,6 +3211,38 @@
},
};
+static int tapan_codec_enable_slim_chmask(struct wcd9xxx_codec_dai_data *dai,
+ bool up)
+{
+ int ret = 0;
+ struct wcd9xxx_ch *ch;
+
+ if (up) {
+ list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
+ ret = wcd9xxx_get_slave_port(ch->ch_num);
+ if (ret < 0) {
+ pr_debug("%s: Invalid slave port ID: %d\n",
+ __func__, ret);
+ ret = -EINVAL;
+ } else {
+ set_bit(ret, &dai->ch_mask);
+ }
+ }
+ } else {
+ ret = wait_event_timeout(dai->dai_wait, (dai->ch_mask == 0),
+ msecs_to_jiffies(
+ TAPAN_SLIM_CLOSE_TIMEOUT));
+ if (!ret) {
+ pr_debug("%s: Slim close tx/rx wait timeout\n",
+ __func__);
+ ret = -ETIMEDOUT;
+ } else {
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
static int tapan_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
@@ -2889,7 +3250,7 @@
struct wcd9xxx *core;
struct snd_soc_codec *codec = w->codec;
struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
- u32 ret = 0;
+ int ret = 0;
struct wcd9xxx_codec_dai_data *dai;
core = dev_get_drvdata(codec->dev->parent);
@@ -2909,6 +3270,7 @@
switch (event) {
case SND_SOC_DAPM_POST_PMU:
+ (void) tapan_codec_enable_slim_chmask(dai, true);
ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
dai->rate, dai->bit_width,
&dai->grph);
@@ -2916,7 +3278,14 @@
case SND_SOC_DAPM_POST_PMD:
ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
dai->grph);
- usleep_range(15000, 15000);
+ ret = tapan_codec_enable_slim_chmask(dai, false);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(core,
+ &dai->wcd9xxx_ch_list,
+ dai->grph);
+ dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
+ __func__, ret);
+ }
break;
}
return ret;
@@ -2938,7 +3307,6 @@
__func__, w->codec->name);
dev_dbg(codec->dev, "%s: num_dai %d stream name %s\n",
__func__, w->codec->num_dai, w->sname);
-
/* Execute the callback only if interface type is slimbus */
if (tapan_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
return 0;
@@ -2949,6 +3317,7 @@
dai = &tapan_p->dai[w->shift];
switch (event) {
case SND_SOC_DAPM_POST_PMU:
+ (void) tapan_codec_enable_slim_chmask(dai, true);
ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
dai->rate, dai->bit_width,
&dai->grph);
@@ -2956,45 +3325,103 @@
case SND_SOC_DAPM_POST_PMD:
ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
dai->grph);
+ ret = tapan_codec_enable_slim_chmask(dai, false);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(core,
+ &dai->wcd9xxx_ch_list,
+ dai->grph);
+ dev_dbg(codec->dev, "%s: Disconnect RX port, ret = %d\n",
+ __func__, ret);
+ }
break;
}
return ret;
}
+
static int tapan_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
switch (event) {
-
case SND_SOC_DAPM_POST_PMU:
+ wcd9xxx_clsh_fsm(codec, &tapan_p->clsh_d,
+ WCD9XXX_CLSH_STATE_EAR,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_5, 0x02, 0x00);
- snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x20, 0x00);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x04, 0x04);
- snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x08, 0x00);
+ usleep_range(5000, 5010);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd9xxx_clsh_fsm(codec, &tapan_p->clsh_d,
+ WCD9XXX_CLSH_STATE_EAR,
+ WCD9XXX_CLSH_REQ_DISABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
+ usleep_range(5000, 5010);
+ }
+ return 0;
+}
- usleep_range(5000, 5000);
+static int tapan_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ wcd9xxx_clsh_fsm(codec, &tapan_p->clsh_d,
+ WCD9XXX_CLSH_STATE_EAR,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_PRE_DAC);
+ break;
+ }
+
+ return 0;
+}
+
+static int tapan_codec_dsm_mux_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u8 reg_val, zoh_mux_val = 0x00;
+
+ dev_dbg(codec->dev, "%s: event = %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ reg_val = snd_soc_read(codec, TAPAN_A_CDC_CONN_CLSH_CTL);
+
+ if ((reg_val & 0x30) == 0x10)
+ zoh_mux_val = 0x04;
+ else if ((reg_val & 0x30) == 0x20)
+ zoh_mux_val = 0x08;
+
+ if (zoh_mux_val != 0x00)
+ snd_soc_update_bits(codec,
+ TAPAN_A_CDC_CONN_CLSH_CTL,
+ 0x0C, zoh_mux_val);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CONN_CLSH_CTL,
+ 0x0C, 0x00);
break;
}
return 0;
}
+
/* Todo: Have seperate dapm widgets for I2S and Slimbus.
* Might Need to have callbacks registered only for slimbus
*/
static const struct snd_soc_dapm_widget tapan_dapm_widgets[] = {
- /*RX stuff */
- SND_SOC_DAPM_OUTPUT("EAR"),
-
- SND_SOC_DAPM_PGA_E("EAR PA", TAPAN_A_RX_EAR_EN, 4, 0, NULL, 0,
- tapan_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_MIXER("DAC1", TAPAN_A_RX_EAR_EN, 6, 0, dac1_switch,
- ARRAY_SIZE(dac1_switch)),
SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
AIF1_PB, 0, tapan_codec_enable_slimrx,
@@ -3023,51 +3450,61 @@
SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
- /* Headphone */
- SND_SOC_DAPM_OUTPUT("HEADPHONE"),
- SND_SOC_DAPM_PGA_E("HPHL", TAPAN_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
- tapan_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MIXER("HPHL DAC", TAPAN_A_RX_HPH_L_DAC_CTL, 7, 0,
- hphl_switch, ARRAY_SIZE(hphl_switch)),
- SND_SOC_DAPM_PGA_E("HPHR", TAPAN_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
- tapan_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ /* RX1 MIX1 mux inputs */
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp3_mux),
- SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAPAN_A_RX_HPH_R_DAC_CTL, 7, 0,
- tapan_hphr_dac_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ /* RX2 MIX1 mux inputs */
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp2_mux),
- /* Speaker */
- SND_SOC_DAPM_OUTPUT("LINEOUT1"),
- SND_SOC_DAPM_OUTPUT("LINEOUT2"),
- SND_SOC_DAPM_OUTPUT("SPK_OUT"),
+ /* RX3 MIX1 mux inputs */
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp2_mux),
- SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TAPAN_A_RX_LINE_CNP_EN, 0, 0, NULL,
- 0, tapan_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TAPAN_A_RX_LINE_CNP_EN, 1, 0, NULL,
- 0, tapan_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ /* RX4 MIX1 mux inputs */
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp2_mux),
- SND_SOC_DAPM_PGA_E("SPK PA", TAPAN_A_SPKR_DRV_EN, 7, 0 , NULL,
- 0, tapan_codec_enable_spk_pa, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ /* RX1 MIX2 mux inputs */
+ SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx1_mix2_inp1_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+ &rx1_mix2_inp2_mux),
- SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAPAN_A_RX_LINE_1_DAC_CTL, 7, 0
- , tapan_lineout_dac_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAPAN_A_RX_LINE_2_DAC_CTL, 7, 0
- , tapan_lineout_dac_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ /* RX2 MIX2 mux inputs */
+ SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix2_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+ &rx2_mix2_inp2_mux),
- SND_SOC_DAPM_DAC_E("SPK DAC", NULL, SND_SOC_NOPM, 0, 0,
- tapan_spk_dac_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ /* RX4 MIX2 mux inputs */
+ SND_SOC_DAPM_MUX("RX4 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx4_mix2_inp1_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+ &rx4_mix2_inp2_mux),
+
SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX4 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAPAN_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
@@ -3078,94 +3515,116 @@
SND_SOC_DAPM_MIXER_E("RX3 MIX1", TAPAN_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_MIXER_E("RX4 MIX1", TAPAN_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
- 0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_MIXER_E("RX5 MIX1", TAPAN_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
+ SND_SOC_DAPM_MIXER_E("RX4 MIX2", TAPAN_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_MIXER("RX1 CHAIN", TAPAN_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
- SND_SOC_DAPM_MIXER("RX2 CHAIN", TAPAN_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX1 CHAIN", TAPAN_A_CDC_RX1_B6_CTL, 5, 0,
+ NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 CHAIN", TAPAN_A_CDC_RX2_B6_CTL, 5, 0,
+ NULL, 0),
- SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
- &rx_mix1_inp3_mux),
- SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx2_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx2_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx3_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx3_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx4_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx4_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
- &rx1_mix2_inp1_mux),
- SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
- &rx1_mix2_inp2_mux),
- SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
- &rx2_mix2_inp1_mux),
- SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
- &rx2_mix2_inp2_mux),
+ SND_SOC_DAPM_MUX_E("CLASS_H_DSM MUX", SND_SOC_NOPM, 0, 0,
+ &class_h_dsm_mux, tapan_codec_dsm_mux_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
- &rx_dac5_mux),
-
- SND_SOC_DAPM_SUPPLY("CLASS_H_CLK", TAPAN_A_CDC_CLK_OTHR_CTL, 0, 0,
- tapan_codec_enable_class_h_clk, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_PRE_PMD),
-
- SND_SOC_DAPM_SUPPLY("CLASS_H_EAR", TAPAN_A_CDC_CLSH_B1_CTL, 4, 0,
- tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_L", TAPAN_A_CDC_CLSH_B1_CTL, 3, 0,
- tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_R", TAPAN_A_CDC_CLSH_B1_CTL, 2, 0,
- tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_SUPPLY("CLASS_H_LINEOUTS_PA", SND_SOC_NOPM, 0, 0,
- tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_SUPPLY("CP", TAPAN_A_NCP_EN, 0, 0,
- tapan_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-
+ /* RX Bias */
SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
tapan_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
- /* TX */
+ /*EAR */
+ SND_SOC_DAPM_PGA_E("EAR PA", TAPAN_A_RX_EAR_EN, 4, 0, NULL, 0,
+ tapan_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_SUPPLY("CDC_CONN", TAPAN_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
+ SND_SOC_DAPM_MIXER_E("DAC1", TAPAN_A_RX_EAR_EN, 6, 0, dac1_switch,
+ ARRAY_SIZE(dac1_switch), tapan_codec_ear_dac_event,
+ SND_SOC_DAPM_PRE_PMU),
+
+ /* Headphone Left */
+ SND_SOC_DAPM_PGA_E("HPHL", TAPAN_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
+ tapan_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER_E("HPHL DAC", TAPAN_A_RX_HPH_L_DAC_CTL, 7, 0,
+ hphl_switch, ARRAY_SIZE(hphl_switch), tapan_hphl_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Headphone Right */
+ SND_SOC_DAPM_PGA_E("HPHR", TAPAN_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
+ tapan_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAPAN_A_RX_HPH_R_DAC_CTL, 7, 0,
+ tapan_hphr_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* LINEOUT1*/
+ SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAPAN_A_RX_LINE_1_DAC_CTL, 7, 0
+ , tapan_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TAPAN_A_RX_LINE_CNP_EN, 0, 0, NULL,
+ 0, tapan_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* LINEOUT2*/
+ SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
+ &rx_dac5_mux),
+
+ SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAPAN_A_RX_LINE_2_DAC_CTL, 7, 0
+ , tapan_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TAPAN_A_RX_LINE_CNP_EN, 1, 0, NULL,
+ 0, tapan_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* CLASS-D SPK */
+ SND_SOC_DAPM_MIXER_E("SPK DAC", SND_SOC_NOPM, 0, 0,
+ spk_dac_switch, ARRAY_SIZE(spk_dac_switch), tapan_spk_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0 , NULL,
+ 0, tapan_codec_enable_spk_pa,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
+ tapan_codec_enable_vdd_spkr,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_OUTPUT("EAR"),
+ SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+ SND_SOC_DAPM_OUTPUT("SPK_OUT"),
+
+ /* TX Path*/
+ SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
+ aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+
+ SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
+ aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+
+ SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
+ aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+
+ SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, TAPAN_TX1, 0,
+ &sb_tx1_mux),
+ SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, TAPAN_TX2, 0,
+ &sb_tx2_mux),
+ SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, TAPAN_TX3, 0,
+ &sb_tx3_mux),
+ SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, TAPAN_TX4, 0,
+ &sb_tx4_mux),
+ SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, TAPAN_TX5, 0,
+ &sb_tx5_mux),
+
+ SND_SOC_DAPM_SUPPLY("CDC_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
0),
- SND_SOC_DAPM_SUPPLY("LDO_H", TAPAN_A_LDO_H_MODE_1, 7, 0,
- tapan_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_INPUT("AMIC1"),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0,
- tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAPAN_A_MICB_1_CTL, 7, 0,
- tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAPAN_A_MICB_1_CTL, 7, 0,
- tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_INPUT("AMIC3"),
-
- SND_SOC_DAPM_INPUT("AMIC4"),
-
- SND_SOC_DAPM_INPUT("AMIC5"),
-
+ /* Decimator MUX */
SND_SOC_DAPM_MUX_E("DEC1 MUX", TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
&dec1_mux, tapan_codec_enable_dec,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
@@ -3186,6 +3645,54 @@
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("LDO_H", TAPAN_A_LDO_H_MODE_1, 7, 0,
+ tapan_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_SUPPLY("COMP0_CLK", SND_SOC_NOPM, 0, 0,
+ tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 1, 0,
+ tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 2, 0,
+ tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC1"),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0,
+ tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAPAN_A_MICB_1_CTL, 7, 0,
+ tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAPAN_A_MICB_1_CTL, 7, 0,
+ tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("ADC1", NULL, TAPAN_A_TX_1_EN, 7, 0,
+ tapan_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC2", NULL, TAPAN_A_TX_2_EN, 7, 0,
+ tapan_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC3"),
+ SND_SOC_DAPM_ADC_E("ADC3", NULL, TAPAN_A_TX_3_EN, 7, 0,
+ tapan_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC4"),
+ SND_SOC_DAPM_ADC_E("ADC4", NULL, TAPAN_A_TX_4_EN, 7, 0,
+ tapan_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC5"),
+ SND_SOC_DAPM_ADC_E("ADC5", NULL, TAPAN_A_TX_5_EN, 7, 0,
+ tapan_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
+ SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
+
SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
tapan_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
@@ -3225,25 +3732,7 @@
AIF3_CAP, 0, tapan_codec_enable_slimtx,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
- aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
-
- SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
- aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
-
- SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
- aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
-
- SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, TAPAN_TX1, 0,
- &sb_tx1_mux),
- SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, TAPAN_TX2, 0,
- &sb_tx2_mux),
- SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, TAPAN_TX3, 0,
- &sb_tx3_mux),
- SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, TAPAN_TX4, 0,
- &sb_tx4_mux),
-
- /* Digital Mic Inputs */
+ /* Digital Mic Inputs */
SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
@@ -3289,142 +3778,98 @@
SND_SOC_DAPM_MIXER("LINEOUT2_PA_MIXER", SND_SOC_NOPM, 0, 0,
lineout2_pa_mix, ARRAY_SIZE(lineout2_pa_mix)),
-
};
-static unsigned long slimbus_value;
-
static irqreturn_t tapan_slimbus_irq(int irq, void *data)
{
struct tapan_priv *priv = data;
struct snd_soc_codec *codec = priv->codec;
- int i, j;
+ unsigned long status = 0;
+ int i, j, port_id, k;
+ u32 bit;
u8 val;
+ bool tx, cleared;
- for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
- slimbus_value = wcd9xxx_interface_reg_read(codec->control_data,
- TAPAN_SLIM_PGD_PORT_INT_STATUS0 + i);
- for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
- val = wcd9xxx_interface_reg_read(codec->control_data,
- TAPAN_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
- if (val & 0x1)
- pr_err_ratelimited(
- "overflow error on port %x, value %x\n",
- i*8 + j, val);
- if (val & 0x2)
- pr_err_ratelimited(
- "underflow error on port %x, value %x\n",
- i*8 + j, val);
+ for (i = TAPAN_SLIM_PGD_PORT_INT_STATUS_RX_0, j = 0;
+ i <= TAPAN_SLIM_PGD_PORT_INT_STATUS_TX_1; i++, j++) {
+ val = wcd9xxx_interface_reg_read(codec->control_data, i);
+ status |= ((u32)val << (8 * j));
+ }
+
+ for_each_set_bit(j, &status, 32) {
+ tx = (j >= 16 ? true : false);
+ port_id = (tx ? j - 16 : j);
+ val = wcd9xxx_interface_reg_read(codec->control_data,
+ TAPAN_SLIM_PGD_PORT_INT_RX_SOURCE0 + j);
+ if (val & TAPAN_SLIM_IRQ_OVERFLOW)
+ pr_err_ratelimited(
+ "%s: overflow error on %s port %d, value %x\n",
+ __func__, (tx ? "TX" : "RX"), port_id, val);
+ if (val & TAPAN_SLIM_IRQ_UNDERFLOW)
+ pr_err_ratelimited(
+ "%s: underflow error on %s port %d, value %x\n",
+ __func__, (tx ? "TX" : "RX"), port_id, val);
+ if (val & TAPAN_SLIM_IRQ_PORT_CLOSED) {
+ /*
+ * INT SOURCE register starts from RX to TX
+ * but port number in the ch_mask is in opposite way
+ */
+ bit = (tx ? j - 16 : j + 16);
+ dev_dbg(codec->dev, "%s: %s port %d closed value %x, bit %u\n",
+ __func__, (tx ? "TX" : "RX"), port_id, val,
+ bit);
+ for (k = 0, cleared = false; k < NUM_CODEC_DAIS; k++) {
+ dev_dbg(codec->dev, "%s: priv->dai[%d].ch_mask = 0x%lx\n",
+ __func__, k, priv->dai[k].ch_mask);
+ if (test_and_clear_bit(bit,
+ &priv->dai[k].ch_mask)) {
+ cleared = true;
+ if (!priv->dai[k].ch_mask)
+ wake_up(&priv->dai[k].dai_wait);
+ /*
+ * There are cases when multiple DAIs
+ * might be using the same slimbus
+ * channel. Hence don't break here.
+ */
+ }
+ }
+ WARN(!cleared,
+ "Couldn't find slimbus %s port %d for closing\n",
+ (tx ? "TX" : "RX"), port_id);
}
wcd9xxx_interface_reg_write(codec->control_data,
- TAPAN_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
-
+ TAPAN_SLIM_PGD_PORT_INT_CLR_RX_0 +
+ (j / 8),
+ 1 << (j % 8));
}
+
return IRQ_HANDLED;
}
-static const struct tapan_reg_mask_val tapan_1_0_class_h_ear[] = {
-
- /* CLASS-H EAR IDLE_THRESHOLD Table */
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_IDLE_EAR_THSD, 0x26),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_FCLKONLY_EAR_THSD, 0x2C),
-
- /* CLASS-H EAR I_PA_FACT Table. */
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_L, 0xA9),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_U, 0x07),
-
- /* CLASS-H EAR Voltage Headroom , Voltage Min. */
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_HD_EAR, 0x0D),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_MIN_EAR, 0x3A),
-
- /* CLASS-H EAR K values --chnages from load. */
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_ADDR, 0x08),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x1B),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x2D),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x36),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x37),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
- /** end of Ear PA load 32 */
-};
-
-static const struct tapan_reg_mask_val tapan_1_0_class_h_hph[] = {
-
- /* CLASS-H HPH IDLE_THRESHOLD Table */
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_IDLE_HPH_THSD, 0x13),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0x19),
-
- /* CLASS-H HPH I_PA_FACT Table */
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_L, 0x9A),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_U, 0x06),
-
- /* CLASS-H HPH Voltage Headroom , Voltage Min */
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_HD_HPH, 0x0D),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_MIN_HPH, 0x1D),
-
- /* CLASS-H HPH K values --chnages from load .*/
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_ADDR, 0x00),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0xAE),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x01),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x1C),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x25),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x27),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
-};
-
-static int tapan_config_ear_class_h(struct snd_soc_codec *codec, u32 ear_load)
-{
- u32 i;
-
- if (ear_load != 32)
- return -EINVAL;
-
- for (i = 0; i < ARRAY_SIZE(tapan_1_0_class_h_ear); i++)
- snd_soc_write(codec, tapan_1_0_class_h_ear[i].reg,
- tapan_1_0_class_h_ear[i].val);
- return 0;
-}
-
-static int tapan_config_hph_class_h(struct snd_soc_codec *codec, u32 hph_load)
-{
- u32 i;
- if (hph_load != 16)
- return -EINVAL;
-
- for (i = 0; i < ARRAY_SIZE(tapan_1_0_class_h_hph); i++)
- snd_soc_write(codec, tapan_1_0_class_h_hph[i].reg,
- tapan_1_0_class_h_hph[i].val);
- return 0;
-}
-
static int tapan_handle_pdata(struct tapan_priv *tapan)
{
struct snd_soc_codec *codec = tapan->codec;
struct wcd9xxx_pdata *pdata = tapan->resmgr.pdata;
int k1, k2, k3, rc = 0;
- u8 leg_mode, txfe_bypass, txfe_buff, flag;
- u8 value = 0;
+ u8 txfe_bypass = pdata->amic_settings.txfe_enable;
+ u8 txfe_buff = pdata->amic_settings.txfe_buff;
+ u8 flag = pdata->amic_settings.use_pdata;
+ u8 i = 0, j = 0;
+ u8 val_txfe = 0, value = 0;
if (!pdata) {
- pr_err("%s: NULL pdata\n", __func__);
+ dev_err(codec->dev, "%s: NULL pdata\n", __func__);
rc = -ENODEV;
goto done;
}
- leg_mode = pdata->amic_settings.legacy_mode;
- txfe_bypass = pdata->amic_settings.txfe_enable;
- txfe_buff = pdata->amic_settings.txfe_buff;
- flag = pdata->amic_settings.use_pdata;
-
/* Make sure settings are correct */
if ((pdata->micbias.ldoh_v > WCD9XXX_LDOH_3P0_V) ||
(pdata->micbias.bias1_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
(pdata->micbias.bias2_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
(pdata->micbias.bias3_cfilt_sel > WCD9XXX_CFILT3_SEL)) {
+ dev_err(codec->dev, "%s: Invalid ldoh voltage or bias cfilt\n",
+ __func__);
rc = -EINVAL;
goto done;
}
@@ -3434,6 +3879,9 @@
k3 = wcd9xxx_resmgr_get_k_val(&tapan->resmgr, pdata->micbias.cfilt3_mv);
if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
+ dev_err(codec->dev,
+ "%s: could not get K value. k1 = %d k2 = %d k3 = %d\n",
+ __func__, k1, k2, k3);
rc = -EINVAL;
goto done;
}
@@ -3445,19 +3893,34 @@
snd_soc_update_bits(codec, TAPAN_A_MICB_CFILT_2_VAL, 0xFC, (k2 << 2));
snd_soc_update_bits(codec, TAPAN_A_MICB_CFILT_3_VAL, 0xFC, (k3 << 2));
- snd_soc_update_bits(codec, TAPAN_A_MICB_1_CTL, 0x60,
- (pdata->micbias.bias1_cfilt_sel << 5));
- snd_soc_update_bits(codec, TAPAN_A_MICB_2_CTL, 0x60,
- (pdata->micbias.bias2_cfilt_sel << 5));
- snd_soc_update_bits(codec, TAPAN_A_MICB_3_CTL, 0x60,
- (pdata->micbias.bias3_cfilt_sel << 5));
+ i = 0;
+ while (i < 5) {
+ if (flag & (0x01 << i)) {
+ val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
+ val_txfe = val_txfe |
+ ((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
+ snd_soc_update_bits(codec,
+ TAPAN_A_TX_1_2_TEST_EN + j * 10,
+ 0x30, val_txfe);
+ }
+ if (flag & (0x01 << (i + 1))) {
+ val_txfe = (txfe_bypass &
+ (0x01 << (i + 1))) ? 0x02 : 0x00;
+ val_txfe |= (txfe_buff &
+ (0x01 << (i + 1))) ? 0x01 : 0x00;
+ snd_soc_update_bits(codec,
+ TAPAN_A_TX_1_2_TEST_EN + j * 10,
+ 0x03, val_txfe);
+ }
+ /* Tapan only has TAPAN_A_TX_1_2_TEST_EN and
+ TAPAN_A_TX_4_5_TEST_EN reg */
- if (flag & 0x40) {
- value = (leg_mode & 0x40) ? 0x10 : 0x00;
- value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
- value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
- snd_soc_update_bits(codec, TAPAN_A_TX_7_MBHC_EN,
- 0x13, value);
+ if (i == 0) {
+ i = 3;
+ continue;
+ } else if (i == 3) {
+ break;
+ }
}
if (pdata->ocp.use_pdata) {
@@ -3475,8 +3938,16 @@
0xE0, (pdata->ocp.hph_ocp_limit << 5));
}
- tapan_config_ear_class_h(codec, 32);
- tapan_config_hph_class_h(codec, 16);
+ /* Set micbias capless mode with tail current */
+ value = (pdata->micbias.bias1_cap_mode == MICBIAS_EXT_BYP_CAP ?
+ 0x00 : 0x10);
+ snd_soc_update_bits(codec, TAPAN_A_MICB_1_CTL, 0x10, value);
+ value = (pdata->micbias.bias2_cap_mode == MICBIAS_EXT_BYP_CAP ?
+ 0x00 : 0x10);
+ snd_soc_update_bits(codec, TAPAN_A_MICB_2_CTL, 0x10, value);
+ value = (pdata->micbias.bias3_cap_mode == MICBIAS_EXT_BYP_CAP ?
+ 0x00 : 0x10);
+ snd_soc_update_bits(codec, TAPAN_A_MICB_3_CTL, 0x10, value);
done:
return rc;
@@ -3484,60 +3955,54 @@
static const struct tapan_reg_mask_val tapan_reg_defaults[] = {
- /* set MCLk to 9.6 */
- TAPAN_REG_VAL(TAPAN_A_CHIP_CTL, 0x0A),
+ /* enable QFUSE for wcd9306 */
+ TAPAN_REG_VAL(TAPAN_A_QFUSE_CTL, 0x03),
+
+ /* PROGRAM_THE_0P85V_VBG_REFERENCE = V_0P858V */
+ TAPAN_REG_VAL(TAPAN_A_BIAS_CURR_CTL_2, 0x04),
+
TAPAN_REG_VAL(TAPAN_A_CDC_CLK_POWER_CTL, 0x03),
/* EAR PA deafults */
TAPAN_REG_VAL(TAPAN_A_RX_EAR_CMBUFF, 0x05),
- /** BUCK and NCP defaults for EAR and HS */
- TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_CCL_4, 0x50),
- TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_CCL_1, 0x5B),
-
- /* CLASS-H defaults for EAR and HS */
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_BUCK_NCP_VARS, 0x00),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_BUCK_NCP_VARS, 0x04),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x01),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x05),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x35),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B3_CTL, 0x30),
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B3_CTL, 0x3B),
-
- /*
- * For CLASS-H, Enable ANC delay buffer,
- * set HPHL and EAR PA ref gain to 0 DB.
- */
- TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B1_CTL, 0x26),
-
- /* RX deafults */
- TAPAN_REG_VAL(TAPAN_A_CDC_RX1_B5_CTL, 0x78),
- TAPAN_REG_VAL(TAPAN_A_CDC_RX2_B5_CTL, 0x78),
- TAPAN_REG_VAL(TAPAN_A_CDC_RX3_B5_CTL, 0x78),
- TAPAN_REG_VAL(TAPAN_A_CDC_RX4_B5_CTL, 0x78),
-
/* RX1 and RX2 defaults */
TAPAN_REG_VAL(TAPAN_A_CDC_RX1_B6_CTL, 0xA0),
TAPAN_REG_VAL(TAPAN_A_CDC_RX2_B6_CTL, 0xA0),
- /* RX3 to RX7 defaults */
- TAPAN_REG_VAL(TAPAN_A_CDC_RX3_B6_CTL, 0x80),
- TAPAN_REG_VAL(TAPAN_A_CDC_RX4_B6_CTL, 0x80),
+ /* Heaset set Right from RX2 */
+ TAPAN_REG_VAL(TAPAN_A_CDC_CONN_RX2_B2_CTL, 0x10),
+
/*
- * The following only need to be written for Taiko 1.0 parts.
- * Taiko 2.0 will have appropriate defaults for these registers.
+ * The following only need to be written for Tapan 1.0 parts.
+ * Tapan 2.0 will have appropriate defaults for these registers.
*/
+
+ /* Required defaults for class H operation */
+ /* borrowed from Taiko class-h */
+ TAPAN_REG_VAL(TAPAN_A_RX_HPH_CHOP_CTL, 0xF4),
+ TAPAN_REG_VAL(TAPAN_A_BIAS_CURR_CTL_2, 0x08),
+ TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
+ TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_3, 0x60),
+
+ /* TODO: Check below reg writes conflict with above */
+ /* PROGRAM_THE_0P85V_VBG_REFERENCE = V_0P858V */
+ TAPAN_REG_VAL(TAPAN_A_BIAS_CURR_CTL_2, 0x04),
+ TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x54),
+ TAPAN_REG_VAL(TAPAN_A_RX_HPH_CHOP_CTL, 0x74),
+ TAPAN_REG_VAL(TAPAN_A_RX_BUCK_BIAS1, 0x62),
+
/* Choose max non-overlap time for NCP */
TAPAN_REG_VAL(TAPAN_A_NCP_CLK, 0xFC),
/* Use 25mV/50mV for deltap/m to reduce ripple */
- TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_VCL_1, 0x08),
+ TAPAN_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x08),
/*
* Set DISABLE_MODE_SEL<1:0> to 0b10 (disable PWM in auto mode).
* Note that the other bits of this register will be changed during
* Rx PA bring up.
*/
- TAPAN_REG_VAL(TAPAN_A_BUCK_MODE_3, 0xCE),
+ TAPAN_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
/* Reduce HPH DAC bias to 70% */
TAPAN_REG_VAL(TAPAN_A_RX_HPH_BIAS_PA, 0x7A),
/*Reduce EAR DAC bias to 70% */
@@ -3553,17 +4018,64 @@
*/
TAPAN_REG_VAL(TAPAN_A_MICB_2_MBHC, 0x41),
+ /* not needed if MBHC is not needed */
/* Disable TX7 internal biasing path which can cause leakage */
TAPAN_REG_VAL(TAPAN_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
};
+static const struct tapan_reg_mask_val tapan_2_x_reg_reset_values[] = {
+
+ TAPAN_REG_VAL(TAPAN_A_TX_7_MBHC_EN, 0x6C),
+ TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_CCL_4, 0x51),
+ TAPAN_REG_VAL(TAPAN_A_RX_HPH_CNP_WG_CTL, 0xDA),
+ TAPAN_REG_VAL(TAPAN_A_RX_EAR_CNP, 0xC0),
+ TAPAN_REG_VAL(TAPAN_A_RX_LINE_1_TEST, 0x02),
+ TAPAN_REG_VAL(TAPAN_A_RX_LINE_2_TEST, 0x02),
+ TAPAN_REG_VAL(TAPAN_A_SPKR_DRV_OCP_CTL, 0x97),
+ TAPAN_REG_VAL(TAPAN_A_SPKR_DRV_CLIP_DET, 0x01),
+ TAPAN_REG_VAL(TAPAN_A_SPKR_DRV_IEC, 0x00),
+ TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B1_CTL, 0xE4),
+ TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x00),
+ TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B3_CTL, 0x00),
+ TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_BUCK_NCP_VARS, 0x00),
+ TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_HD_EAR, 0x00),
+ TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_HD_HPH, 0x00),
+ TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_MIN_EAR, 0x00),
+ TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_MIN_HPH, 0x00),
+};
+
+static const struct tapan_reg_mask_val tapan_1_0_reg_defaults[] = {
+ /* Close leakage on the spkdrv */
+ TAPAN_REG_VAL(TAPAN_A_SPKR_DRV_DBG_PWRSTG, 0x24),
+ TAPAN_REG_VAL(TAPAN_A_SPKR_DRV_DBG_DAC, 0xE5),
+
+};
+
static void tapan_update_reg_defaults(struct snd_soc_codec *codec)
{
u32 i;
+ struct wcd9xxx *tapan_core = dev_get_drvdata(codec->dev->parent);
+
+ if (!TAPAN_IS_1_0(tapan_core->version)) {
+ for (i = 0; i < ARRAY_SIZE(tapan_2_x_reg_reset_values); i++)
+ snd_soc_write(codec, tapan_2_x_reg_reset_values[i].reg,
+ tapan_2_x_reg_reset_values[i].val);
+ }
for (i = 0; i < ARRAY_SIZE(tapan_reg_defaults); i++)
snd_soc_write(codec, tapan_reg_defaults[i].reg,
tapan_reg_defaults[i].val);
+
+ if (TAPAN_IS_1_0(tapan_core->version)) {
+ for (i = 0; i < ARRAY_SIZE(tapan_1_0_reg_defaults); i++)
+ snd_soc_write(codec, tapan_1_0_reg_defaults[i].reg,
+ tapan_1_0_reg_defaults[i].val);
+ }
+
+ if (!TAPAN_IS_1_0(tapan_core->version))
+ spkr_drv_wrnd = -1;
+ else if (spkr_drv_wrnd == 1)
+ snd_soc_write(codec, TAPAN_A_SPKR_DRV_EN, 0xEF);
}
static const struct tapan_reg_mask_val tapan_codec_reg_init_val[] = {
@@ -3578,17 +4090,27 @@
{TAPAN_A_RX_HPH_R_GAIN, 0x20, 0x20},
{TAPAN_A_RX_LINE_1_GAIN, 0x20, 0x20},
{TAPAN_A_RX_LINE_2_GAIN, 0x20, 0x20},
+ {TAPAN_A_SPKR_DRV_GAIN, 0x04, 0x04},
+
+ /* Set RDAC5 MUX to take input from DEM3_INV.
+ * This sets LO2 DAC to get input from DEM3_INV
+ * for LO1 and LO2 to work as differential outputs.
+ */
+ {TAPAN_A_CDC_CONN_MISC, 0x04, 0x04},
/* CLASS H config */
{TAPAN_A_CDC_CONN_CLSH_CTL, 0x3C, 0x14},
- /* Use 16 bit sample size for TX1 to TX6 */
+ /* Use 16 bit sample size for TX1 to TX5 */
{TAPAN_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
{TAPAN_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
{TAPAN_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
{TAPAN_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
{TAPAN_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
+ /* Disable SPK SWITCH */
+ {TAPAN_A_SPKR_DRV_DAC_CTL, 0x04, 0x00},
+
/* Use 16 bit sample size for RX */
{TAPAN_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
{TAPAN_A_CDC_CONN_RX_SB_B2_CTL, 0xFF, 0x2A},
@@ -3607,8 +4129,14 @@
/* config DMIC clk to CLK_MODE_1 (3.2Mhz@9.6Mhz mclk) */
{TAPAN_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x22},
- {TAPAN_A_CDC_CLK_DMIC_B2_CTL, 0x0E, 0x02},
+ /* Compander zone selection */
+ {TAPAN_A_CDC_COMP0_B4_CTL, 0x3F, 0x37},
+ {TAPAN_A_CDC_COMP1_B4_CTL, 0x3F, 0x37},
+ {TAPAN_A_CDC_COMP2_B4_CTL, 0x3F, 0x37},
+ {TAPAN_A_CDC_COMP0_B5_CTL, 0x7F, 0x7F},
+ {TAPAN_A_CDC_COMP1_B5_CTL, 0x7F, 0x7F},
+ {TAPAN_A_CDC_COMP2_B5_CTL, 0x7F, 0x7F},
};
static void tapan_codec_init_reg(struct snd_soc_codec *codec)
@@ -3684,6 +4212,10 @@
snd_soc_codec_set_drvdata(codec, tapan);
+ /* TODO: Read buck voltage from DT property */
+ tapan->clsh_d.buck_mv = WCD9XXX_CDC_BUCK_MV_1P8;
+ wcd9xxx_clsh_init(&tapan->clsh_d, &tapan->resmgr);
+
/* codec resmgr module init */
wcd9xxx = codec->control_data;
pdata = dev_get_platdata(codec->dev->parent);
@@ -3691,28 +4223,44 @@
&tapan_reg_address);
if (ret) {
pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
- goto err_codec;
+ return ret;
}
- /* init and start mbhc */
- ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec);
- if (ret) {
- pr_err("%s: mbhc init failed %d\n", __func__, ret);
- goto err_codec;
- }
+ /* TODO: wcd9xxx_mbhc_init to enable mbhc */
tapan->codec = codec;
-
+ for (i = 0; i < COMPANDER_MAX; i++) {
+ tapan->comp_enabled[i] = 0;
+ tapan->comp_fs[i] = COMPANDER_FS_48KHZ;
+ }
tapan->intf_type = wcd9xxx_get_intf_type();
tapan->aux_pga_cnt = 0;
tapan->aux_l_gain = 0x1F;
tapan->aux_r_gain = 0x1F;
tapan_update_reg_defaults(codec);
+
+ dev_dbg(codec->dev, "%s: MCLK Rate = %x\n",
+ __func__, wcd9xxx->mclk_rate);
+
+ if (wcd9xxx->mclk_rate == TAPAN_MCLK_CLK_12P288MHZ) {
+ snd_soc_update_bits(codec, TAPAN_A_CHIP_CTL, 0x06, 0x0);
+ snd_soc_update_bits(codec, TAPAN_A_RX_COM_TIMER_DIV, 0x01,
+ 0x01);
+ } else if (wcd9xxx->mclk_rate == TAPAN_MCLK_CLK_9P6HZ) {
+ snd_soc_update_bits(codec, TAPAN_A_CHIP_CTL, 0x06, 0x2);
+ }
tapan_codec_init_reg(codec);
ret = tapan_handle_pdata(tapan);
if (IS_ERR_VALUE(ret)) {
- pr_err("%s: bad pdata\n", __func__);
- goto err_codec;
+ dev_err(codec->dev, "%s: bad pdata\n", __func__);
+ goto err_pdata;
+ }
+
+ if (spkr_drv_wrnd > 0) {
+ WCD9XXX_BCL_LOCK(&tapan->resmgr);
+ wcd9xxx_resmgr_get_bandgap(&tapan->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
}
ptr = kmalloc((sizeof(tapan_rx_chs) +
@@ -3724,8 +4272,12 @@
}
if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
- pr_err("%s: I2C interface not supported yet\n",
- __func__);
+ snd_soc_dapm_new_controls(dapm, tapan_dapm_i2s_widgets,
+ ARRAY_SIZE(tapan_dapm_i2s_widgets));
+ snd_soc_dapm_add_routes(dapm, audio_i2s_map,
+ ARRAY_SIZE(audio_i2s_map));
+ for (i = 0; i < ARRAY_SIZE(tapan_i2s_dai); i++)
+ INIT_LIST_HEAD(&tapan->dai[i].wcd9xxx_ch_list);
} else if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
for (i = 0; i < NUM_CODEC_DAIS; i++) {
INIT_LIST_HEAD(&tapan->dai[i].wcd9xxx_ch_list);
@@ -3744,12 +4296,14 @@
(void) tapan_setup_irqs(tapan);
+ atomic_set(&kp_tapan_priv, (unsigned long)tapan);
+
codec->ignore_pmdown_time = 1;
return ret;
-err_nomem_slimch:
+err_pdata:
kfree(ptr);
-err_codec:
+err_nomem_slimch:
kfree(tapan);
return ret;
}
@@ -3758,6 +4312,13 @@
{
struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ WCD9XXX_BCL_LOCK(&tapan->resmgr);
+ atomic_set(&kp_tapan_priv, 0);
+
+ if (spkr_drv_wrnd > 0)
+ wcd9xxx_resmgr_put_bandgap(&tapan->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
/* cleanup MBHC */
wcd9xxx_mbhc_deinit(&tapan->mbhc);
/* cleanup resmgr */
@@ -3801,6 +4362,7 @@
struct platform_device *pdev = to_platform_device(dev);
struct tapan_priv *tapan = platform_get_drvdata(pdev);
dev_dbg(dev, "%s: system resume\n", __func__);
+ /* Notify */
wcd9xxx_resmgr_notifier_call(&tapan->resmgr, WCD9XXX_EVENT_POST_RESUME);
return 0;
}
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 328c380..7766b60 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -84,7 +84,6 @@
static int msm_btsco_ch = 1;
static struct mutex cdc_mclk_mutex;
-static struct q_clkdiv *codec_clk;
static int clk_users;
static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
@@ -96,24 +95,18 @@
mutex_lock(&cdc_mclk_mutex);
if (enable) {
- if (!codec_clk) {
- dev_err(codec->dev, "%s: did not get Taiko MCLK\n",
- __func__);
- ret = -EINVAL;
- goto exit;
- }
clk_users++;
if (clk_users != 1)
goto exit;
- /* TODO: qpnp_clkdiv_enable */
+ /* TODO: clk_disable */
tapan_mclk_enable(codec, 1, dapm);
} else {
if (clk_users > 0) {
clk_users--;
if (clk_users == 0) {
tapan_mclk_enable(codec, 0, dapm);
- /* TODO: qpnp_clkdiv_disable */
+ /* TODO: clk_enable */
}
} else {
pr_err("%s: Error releasing Tabla MCLK\n", __func__);
@@ -268,23 +261,6 @@
return 0;
}
-static int msm8226_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
- struct snd_pcm_hw_params *params)
-{
- struct snd_interval *rate = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_RATE);
-
- struct snd_interval *channels = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_CHANNELS);
-
- pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
- channels->min, channels->max);
-
- rate->min = rate->max = 48000;
-
- return 0;
-}
-
static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -335,9 +311,9 @@
};
static const struct snd_kcontrol_new msm_snd_controls[] = {
- SOC_ENUM_EXT("SLIM_0_RX Channels", msm_snd_enum[1],
+ SOC_ENUM_EXT("SLIM_0_RX Channels", msm_snd_enum[0],
msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
- SOC_ENUM_EXT("SLIM_0_TX Channels", msm_snd_enum[2],
+ SOC_ENUM_EXT("SLIM_0_TX Channels", msm_snd_enum[1],
msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
};
@@ -378,8 +354,11 @@
/* start mbhc */
mbhc_cfg.calibration = def_tapan_mbhc_cal();
- if (mbhc_cfg.calibration)
- err = tapan_hs_detect(codec, &mbhc_cfg);
+ if (mbhc_cfg.calibration) {
+ pr_info("%s: WCD9306: Headset detection disabled\n",
+ __func__);
+ }
+
else
err = -ENOMEM;
@@ -550,7 +529,7 @@
.name = "MSM8226 Media1",
.stream_name = "MultiMedia1",
.cpu_dai_name = "MultiMedia1",
- .platform_name = "msm-pcm-dsp",
+ .platform_name = "msm-pcm-dsp.0",
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
@@ -565,7 +544,7 @@
.name = "MSM8226 Media2",
.stream_name = "MultiMedia2",
.cpu_dai_name = "MultiMedia2",
- .platform_name = "msm-pcm-dsp",
+ .platform_name = "msm-pcm-dsp.0",
.dynamic = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
@@ -744,6 +723,22 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
+ {
+ .name = "VoLTE",
+ .stream_name = "VoLTE",
+ .cpu_dai_name = "VoLTE",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_VOLTE,
+ },
/* Backend BT/FM DAI Links */
{
.name = LPASS_BE_INT_BT_SCO_RX,
@@ -757,6 +752,7 @@
.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
/* this dainlink has playback support */
.ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_INT_BT_SCO_TX,
@@ -768,6 +764,7 @@
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_INT_FM_RX,
@@ -781,6 +778,7 @@
.be_hw_params_fixup = msm_be_hw_params_fixup,
/* this dainlink has playback support */
.ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_INT_FM_TX,
@@ -792,6 +790,7 @@
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_INT_FM_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
},
/* Backend AFE DAI Links */
{
@@ -806,6 +805,7 @@
.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
/* this dainlink has playback support */
.ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_AFE_PCM_TX,
@@ -817,6 +817,7 @@
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+ .ignore_suspend = 1,
},
/* HDMI Hostless */
{
@@ -833,19 +834,6 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
- /* HDMI BACK END DAI Link */
- {
- .name = LPASS_BE_HDMI,
- .stream_name = "HDMI Playback",
- .cpu_dai_name = "msm-dai-q6-hdmi.8",
- .platform_name = "msm-pcm-routing",
- .codec_name = "msm-stub-codec.1",
- .codec_dai_name = "msm-stub-rx",
- .no_pcm = 1,
- .be_id = MSM_BACKEND_DAI_HDMI_RX,
- .be_hw_params_fixup = msm8226_hdmi_be_hw_params_fixup,
- .ignore_pmdown_time = 1,
- },
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,
@@ -860,6 +848,7 @@
.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
.ops = &msm8226_be_ops,
.ignore_pmdown_time = 1, /* dai link has playback support */
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_0_TX,
@@ -872,6 +861,7 @@
.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
.ops = &msm8226_be_ops,
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_1_RX,
@@ -886,6 +876,7 @@
.ops = &msm8226_be_ops,
/* dai link has playback support */
.ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_1_TX,
@@ -898,6 +889,7 @@
.be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
.ops = &msm8226_be_ops,
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_3_RX,
@@ -912,6 +904,7 @@
.ops = &msm8226_be_ops,
/* dai link has playback support */
.ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_3_TX,
@@ -924,6 +917,7 @@
.be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
.ops = &msm8226_be_ops,
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_4_RX,
@@ -938,6 +932,7 @@
.ops = &msm8226_be_ops,
/* dai link has playback support */
.ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_4_TX,
@@ -950,6 +945,7 @@
.be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
.ops = &msm8226_be_ops,
+ .ignore_suspend = 1,
},
};
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index ccaf39d..259f3ed 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -839,7 +839,7 @@
{
int result;
int i;
- unsigned long paddr;
+ ion_phys_addr_t paddr;
void *kvptr;
unsigned long kvaddr;
unsigned long mem_len;