Merge "USB: android: Schedule work only if suspended variable is changed"
diff --git a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
index d9a0d59..f969e2f 100644
--- a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
+++ b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
@@ -40,6 +40,8 @@
- qcom,saw2-spm-cmd-wfi: The WFI command sequence
- qcom,saw2-spm-cmd-ret: The Retention command sequence
- qcom,saw2-spm-cmd-spc: The Standalone PC command sequence
+- qcom,saw2-spm-cmd-pc-no-rpm: The Power Collapse command sequence where APPS
+ proc won't inform the RPM.
- qcom,saw2-spm-cmd-pc: The Power Collapse command sequence
- qcom,saw2-spm-cmd-gdhs: L2 GDHS command sequence
- qcom,L2-spm-is-apcs-master: Boolean indicates if the target uses L2 SAW to
diff --git a/arch/arm/boot/dts/msm8226-1080p-cdp.dtsi b/arch/arm/boot/dts/msm8226-1080p-cdp.dtsi
index e310c17..bb66538 100644
--- a/arch/arm/boot/dts/msm8226-1080p-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-1080p-cdp.dtsi
@@ -27,13 +27,23 @@
vcc_i2c-supply = <&pm8226_lvs1>;
synaptics,reset-gpio = <&msmgpio 16 0x00>;
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
- synaptics,button-map = <139 102 158>;
+ synaptics,display-coords = <0 0 1079 1919>;
synaptics,i2c-pull-up;
synaptics,power-down;
synaptics,disable-gpios;
};
};
+ gen-vkeys {
+ compatible = "qcom,gen-vkeys";
+ label = "synaptics_rmi4_i2c";
+ qcom,disp-maxx = <1079>;
+ qcom,disp-maxy = <1919>;
+ qcom,panel-maxx = <1079>;
+ qcom,panel-maxy = <2084>;
+ qcom,key-codes = <158 139 102 217>;
+ };
+
i2c@f9925000 { /* BLSP1 QUP3 */
nfc-nci@0e {
compatible = "qcom,nfc-nci";
diff --git a/arch/arm/boot/dts/msm8226-1080p-mtp.dtsi b/arch/arm/boot/dts/msm8226-1080p-mtp.dtsi
index e58c321..31624de 100644
--- a/arch/arm/boot/dts/msm8226-1080p-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-1080p-mtp.dtsi
@@ -27,13 +27,23 @@
vcc_i2c-supply = <&pm8226_lvs1>;
synaptics,reset-gpio = <&msmgpio 16 0x00>;
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
- synaptics,button-map = <139 102 158>;
+ synaptics,display-coords = <0 0 1079 1919>;
synaptics,i2c-pull-up;
synaptics,power-down;
synaptics,disable-gpios;
};
};
+ gen-vkeys {
+ compatible = "qcom,gen-vkeys";
+ label = "synaptics_rmi4_i2c";
+ qcom,disp-maxx = <1079>;
+ qcom,disp-maxy = <1919>;
+ qcom,panel-maxx = <1079>;
+ qcom,panel-maxy = <2084>;
+ qcom,key-codes = <158 139 102 217>;
+ };
+
i2c@f9925000 { /* BLSP1 QUP3 */
nfc-nci@0e {
compatible = "qcom,nfc-nci";
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 3e2507ff..e2891d1 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -36,7 +36,7 @@
qcom,mdss-wb-off = <0x00011100 0x00013100>;
qcom,mdss-intf-off = <0x00000000 0x00021300>;
qcom,mdss-rot-block-size = <64>;
- qcom,mdss-smp-mb-per-pipe = <2>;
+ qcom,mdss-smp-mb-per-pipe = <4>;
vdd-cx-supply = <&pm8226_s1_corner>;
qcom,vbif-settings = <0x004 0x00000001>,
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index abe5ff3..08ebf88 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -39,7 +39,7 @@
qsecom_mem: qsecom_region {
linux,contiguous-region;
- reg = <0 0x780000>;
+ reg = <0 0xd00000>;
label = "qsecom_mem";
};
};
diff --git a/arch/arm/boot/dts/msm8610-v1-pm.dtsi b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
index 6296692..9ed8fd9 100644
--- a/arch/arm/boot/dts/msm8610-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
@@ -56,10 +56,10 @@
qcom,saw2-spm-dly= <0x3c102800>;
qcom,saw2-spm-ctl = <0x8>;
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 06 26 30 0f];
- qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
- 0b 94 5b 80 10 06 26 30 0f];
+ qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 26 30 0f];
};
qcom,spm@f90b9000 {
@@ -99,6 +99,9 @@
qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+ qcom,saw2-spm-cmd-pc-no-rpm = [00 32 b0 10 e0 d0 6b c0 42 f0
+ 11 03 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+ 50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
qcom,L2-spm-is-apcs-master;
};
@@ -131,22 +134,23 @@
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "pc";
- qcom,l2 = "l2_cache_retention";
- qcom,latency-us = <520>;
- qcom,ss-power = <460>;
- qcom,energy-overhead = <704900>;
- qcom,time-overhead = <1300>;
+ qcom,l2 = "l2_cache_pc_no_rpm";
+ qcom,latency-us = <1000>;
+ qcom,ss-power = <315>;
+ qcom,energy-overhead = <1027150>;
+ qcom,time-overhead = <2400>;
};
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
qcom,l2 = "l2_cache_pc";
- qcom,latency-us = <11700>;
+ qcom,latency-us = <11000>;
qcom,ss-power = <315>;
qcom,energy-overhead = <1027150>;
qcom,time-overhead = <2400>;
};
+
};
qcom,pm-boot {
diff --git a/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
index 4a08f3f..de48f1f 100644
--- a/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
@@ -33,3 +33,10 @@
&dsi_hx8389b_qhd_vid {
qcom,cont-splash-enabled;
};
+&soc {
+ i2c@f9925000 {
+ fsl@1c {
+ fsl,sensors-position = <7>;
+ };
+ };
+};
\ No newline at end of file
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
index 6c7f2f6..0b82ea0 100644
--- a/arch/arm/boot/dts/msm8610-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -56,10 +56,10 @@
qcom,saw2-spm-dly= <0x3c102800>;
qcom,saw2-spm-ctl = <0x8>;
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 06 26 30 0f];
- qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
- 0b 94 5b 80 10 06 26 30 0f];
+ qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 26 30 0f];
};
qcom,spm@f90b9000 {
@@ -101,6 +101,9 @@
qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+ qcom,saw2-spm-cmd-pc-no-rpm = [00 32 b0 10 e0 d0 6b c0 42 f0
+ 11 03 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+ 50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
qcom,L2-spm-is-apcs-master;
};
@@ -143,6 +146,16 @@
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
+ qcom,l2 = "l2_cache_pc_no_rpm";
+ qcom,latency-us = <1000>;
+ qcom,ss-power = <315>;
+ qcom,energy-overhead = <1027150>;
+ qcom,time-overhead = <2400>;
+ };
+
+ qcom,lpm-level@4 {
+ reg = <0x4>;
+ qcom,mode = "pc";
qcom,l2 = "l2_cache_pc";
qcom,latency-us = <11700>;
qcom,ss-power = <315>;
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
index 4735554..95a5da5 100644
--- a/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
@@ -56,3 +56,10 @@
&dsi_hx8389b_qhd_vid {
qcom,cont-splash-enabled;
};
+&soc {
+ i2c@f9925000 {
+ fsl@1c {
+ fsl,sensors-position = <7>;
+ };
+ };
+};
\ No newline at end of file
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 133757a..bc1e031 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -422,7 +422,6 @@
compatible = "qcom,rpm-smd";
rpm-channel-name = "rpm_requests";
rpm-channel-type = <15>; /* SMD_APPS_RPM */
- rpm-standalone;
};
qcom,bcl {
diff --git a/arch/arm/boot/dts/msm8926-qrd-skug.dts b/arch/arm/boot/dts/msm8926-qrd-skug.dts
index 6d907ef..15a2d58 100644
--- a/arch/arm/boot/dts/msm8926-qrd-skug.dts
+++ b/arch/arm/boot/dts/msm8926-qrd-skug.dts
@@ -61,8 +61,8 @@
focaltech,fw-name = "ft_8926_qrd_fw.bin";
focaltech,fw-delay-aa-ms = <30>;
focaltech,fw-delay-55-ms = <30>;
- focaltech,fw-upgrade-id1 = <0x79>;
- focaltech,fw-upgrade-id2 = <0x08>;
+ focaltech,fw-upgrade-id1 = <0x11>;
+ focaltech,fw-upgrade-id2 = <0x11>;
focaltech,fw-delay-readid-ms = <10>;
focaltech,fw-delay-era-flsh-ms = <2000>;
focaltech,fw-auto-cal;
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index 0115d89..e850c55 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -208,10 +208,26 @@
<50 172>, /* usb1_hs_async_wakeup_irq */
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <0xff 34>, /* APCC_qgicL2ErrorIrptReq */
+ <0xff 35>, /* WDT_barkInt */
+ <0xff 40>, /* qtimer_phy_irq */
<0xff 57>, /* mss_to_apps_irq(0) */
<0xff 58>, /* mss_to_apps_irq(1) */
<0xff 59>, /* mss_to_apps_irq(2) */
<0xff 60>, /* mss_to_apps_irq(3) */
+ <0xff 74>, /* osmmu_CIrpt[1] */
+ <0xff 75>, /* osmmu_CIrpt[0] */
+ <0xff 77>, /* osmmu_CIrpt[0] */
+ <0xff 78>, /* osmmu_CIrpt[0] */
+ <0xff 79>, /* osmmu_CIrpt[0] */
+ <0xff 94>, /* osmmu_CIrpt[0] */
+ <0xff 99>, /* msm_iommu_pmon_nonsecure_irq */
+ <0xff 102>, /* osmmu_CIrpt[1] */
+ <0xff 109>, /* ocmem_dm_nonsec_irq */
+ <0xff 126>, /* bam_irq[0] */
+ <0xff 155>, /* sdcc_irq[0] */
+ <0xff 163>, /* usb30_ee1_irq */
+ <0xff 170>, /* sdcc_pwr_cmd_irq */
<0xff 173>, /* o_wcss_apss_smd_hi */
<0xff 174>, /* o_wcss_apss_smd_med */
<0xff 175>, /* o_wcss_apss_smd_low */
@@ -230,6 +246,7 @@
<0xff 195>, /* lpass_irq_out_apcs(7) */
<0xff 196>, /* lpass_irq_out_apcs(8) */
<0xff 197>, /* lpass_irq_out_apcs(9) */
+ <0xff 198>, /* coresight-tmc-etr interrupt */
<0xff 200>, /* rpm_ipc(4) */
<0xff 201>, /* rpm_ipc(5) */
<0xff 202>, /* rpm_ipc(6) */
@@ -238,7 +255,10 @@
<0xff 205>, /* rpm_ipc(25) */
<0xff 206>, /* rpm_ipc(26) */
<0xff 207>, /* rpm_ipc(27) */
- <0xff 240>; /* summary_irq_kpss */
+ <0xff 240>, /* summary_irq_kpss */
+ <0xff 268>, /* bam_irq[1] */
+ <0xff 270>, /* bam_irq[0] */
+ <0xff 271>; /* bam_irq[0] */
qcom,gpio-parent = <&msmgpio>;
qcom,gpio-map = <3 102>,
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 8836975..eb3a48f 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -215,6 +215,9 @@
<50 172>, /* usb1_hs_async_wakeup_irq */
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <0xff 34>, /* APCC_qgicL2ErrorIrptReq */
+ <0xff 35>, /* WDT_barkInt */
+ <0xff 40>, /* qtimer_phy_irq */
<0xff 56>, /* modem_watchdog */
<0xff 57>, /* mss_to_apps_irq(0) */
<0xff 58>, /* mss_to_apps_irq(1) */
@@ -222,8 +225,21 @@
<0xff 60>, /* mss_to_apps_irq(3) */
<0xff 61>, /* mss_a2_bam_irq */
<0xff 70>, /* iommu_pmon_nonsecure_irq */
+ <0xff 74>, /* osmmu_CIrpt[1] */
+ <0xff 75>, /* osmmu_CIrpt[0] */
+ <0xff 77>, /* osmmu_CIrpt[0] */
+ <0xff 78>, /* osmmu_CIrpt[0] */
+ <0xff 79>, /* osmmu_CIrpt[0] */
+ <0xff 94>, /* osmmu_CIrpt[0] */
<0xff 97>, /* iommu_nonsecure_irq */
+ <0xff 99>, /* msm_iommu_pmon_nonsecure_irq */
+ <0xff 102>, /* osmmu_CIrpt[1] */
<0xff 105>, /* iommu_pmon_nonsecure_irq */
+ <0xff 109>, /* ocmem_dm_nonsec_irq */
+ <0xff 126>, /* bam_irq[0] */
+ <0xff 155>, /* sdcc_irq[0] */
+ <0xff 163>, /* usb30_ee1_irq */
+ <0xff 170>, /* sdcc_pwr_cmd_irq */
<0xff 173>, /* o_wcss_apss_smd_hi */
<0xff 174>, /* o_wcss_apss_smd_med */
<0xff 175>, /* o_wcss_apss_smd_low */
@@ -231,7 +247,6 @@
<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
<0xff 179>, /* o_wcss_apss_asic_intr */
-
<0xff 181>, /* wcnss watchdog */
<0xff 188>, /* lpass_irq_out_apcs(0) */
<0xff 189>, /* lpass_irq_out_apcs(1) */
@@ -243,6 +258,7 @@
<0xff 195>, /* lpass_irq_out_apcs(7) */
<0xff 196>, /* lpass_irq_out_apcs(8) */
<0xff 197>, /* lpass_irq_out_apcs(9) */
+ <0xff 198>, /* coresight-tmc-etr interrupt */
<0xff 200>, /* rpm_ipc(4) */
<0xff 201>, /* rpm_ipc(5) */
<0xff 202>, /* rpm_ipc(6) */
@@ -252,7 +268,10 @@
<0xff 206>, /* rpm_ipc(26) */
<0xff 207>, /* rpm_ipc(27) */
<0xff 211>, /* usb_dwc3_otg */
- <0xff 240>; /* summary_irq_kpss */
+ <0xff 240>, /* summary_irq_kpss */
+ <0xff 268>, /* bam_irq[1] */
+ <0xff 270>, /* bam_irq[0] */
+ <0xff 271>; /* bam_irq[0] */
qcom,gpio-parent = <&msmgpio>;
qcom,gpio-map = <3 102>,
diff --git a/arch/arm/boot/dts/msm8974pro-pm.dtsi b/arch/arm/boot/dts/msm8974pro-pm.dtsi
index 9e1f83f..5769446 100644
--- a/arch/arm/boot/dts/msm8974pro-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm.dtsi
@@ -205,6 +205,9 @@
<50 172>, /* usb1_hs_async_wakeup_irq */
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <0xff 34>, /* APCC_qgicL2ErrorIrptReq */
+ <0xff 35>, /* WDT_barkInt */
+ <0xff 40>, /* qtimer_phy_irq */
<0xff 56>, /* modem_watchdog */
<0xff 57>, /* mss_to_apps_irq(0) */
<0xff 58>, /* mss_to_apps_irq(1) */
@@ -212,8 +215,21 @@
<0xff 60>, /* mss_to_apps_irq(3) */
<0xff 61>, /* mss_a2_bam_irq */
<0xff 70>, /* iommu_pmon_nonsecure_irq */
+ <0xff 74>, /* osmmu_CIrpt[1] */
+ <0xff 75>, /* osmmu_CIrpt[0] */
+ <0xff 77>, /* osmmu_CIrpt[0] */
+ <0xff 78>, /* osmmu_CIrpt[0] */
+ <0xff 79>, /* osmmu_CIrpt[0] */
+ <0xff 94>, /* osmmu_CIrpt[0] */
<0xff 97>, /* iommu_nonsecure_irq */
+ <0xff 99>, /* msm_iommu_pmon_nonsecure_irq */
+ <0xff 102>, /* osmmu_CIrpt[1] */
<0xff 105>, /* iommu_pmon_nonsecure_irq */
+ <0xff 109>, /* ocmem_dm_nonsec_irq */
+ <0xff 126>, /* bam_irq[0] */
+ <0xff 155>, /* sdcc_irq[0] */
+ <0xff 163>, /* usb30_ee1_irq */
+ <0xff 170>, /* sdcc_pwr_cmd_irq */
<0xff 173>, /* o_wcss_apss_smd_hi */
<0xff 174>, /* o_wcss_apss_smd_med */
<0xff 175>, /* o_wcss_apss_smd_low */
@@ -233,6 +249,7 @@
<0xff 195>, /* lpass_irq_out_apcs(7) */
<0xff 196>, /* lpass_irq_out_apcs(8) */
<0xff 197>, /* lpass_irq_out_apcs(9) */
+ <0xff 198>, /* coresight-tmc-etr interrupt */
<0xff 200>, /* rpm_ipc(4) */
<0xff 201>, /* rpm_ipc(5) */
<0xff 202>, /* rpm_ipc(6) */
@@ -242,7 +259,10 @@
<0xff 206>, /* rpm_ipc(26) */
<0xff 207>, /* rpm_ipc(27) */
<0xff 211>, /* usb_dwc3_otg */
- <0xff 240>; /* summary_irq_kpss */
+ <0xff 240>, /* summary_irq_kpss */
+ <0xff 268>, /* bam_irq[1] */
+ <0xff 270>, /* bam_irq[0] */
+ <0xff 271>; /* bam_irq[0] */
qcom,gpio-parent = <&msmgpio>;
qcom,gpio-map = <3 102>,
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 45a6b89..89d462c 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -3040,10 +3040,12 @@
"fda00c00.qcom,csiphy"),
CLK_LOOKUP("csiphy_timer_clk", csi0phytimer_clk.c,
"fda00c00.qcom,csiphy"),
+ CLK_LOOKUP("csi_ahb_clk", csi_ahb_clk.c, "fda00c00.qcom,csiphy"),
CLK_LOOKUP("csiphy_timer_src_clk", csi1phytimer_clk_src.c,
"fda01000.qcom,csiphy"),
CLK_LOOKUP("csiphy_timer_clk", csi1phytimer_clk.c,
"fda01000.qcom,csiphy"),
+ CLK_LOOKUP("csi_ahb_clk", csi_ahb_clk.c, "fda01000.qcom,csiphy"),
/* CSID clocks */
CLK_LOOKUP("csi_clk", csi0_clk.c, "fda00000.qcom,csid"),
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index 7c06268..c480e56 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -112,8 +112,8 @@
continue;
state = &msm_cpuidle_driver.states[state_count];
- snprintf(state->name, CPUIDLE_NAME_LEN, cstate->name);
- snprintf(state->desc, CPUIDLE_DESC_LEN, cstate->desc);
+ snprintf(state->name, CPUIDLE_NAME_LEN, "%s", cstate->name);
+ snprintf(state->desc, CPUIDLE_DESC_LEN, "%s", cstate->desc);
state->flags = 0;
state->exit_latency = 0;
state->power_usage = 0;
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
index ff3da11..3973044 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
@@ -30,6 +30,7 @@
bool down_mix);
int (*get_audio_edid_blk) (struct platform_device *pdev,
struct msm_hdmi_audio_edid_blk *blk);
+ int (*hdmi_cable_status) (struct platform_device *pdev, u32 vote);
};
int msm_hdmi_register_audio_codec(struct platform_device *pdev,
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 110ab87..cb9697d 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -3243,7 +3243,7 @@
*/
void smd_set_edge_subsys_name(uint32_t edge, const char *subsys_name)
{
- if (edge <= ARRAY_SIZE(edge_to_pids))
+ if (edge < ARRAY_SIZE(edge_to_pids))
strlcpy(edge_to_pids[edge].subsys_name,
subsys_name, SMD_MAX_CH_NAME_LEN);
else
@@ -3258,7 +3258,7 @@
*/
void smd_set_edge_initialized(uint32_t edge)
{
- if (edge <= ARRAY_SIZE(edge_to_pids))
+ if (edge < ARRAY_SIZE(edge_to_pids))
edge_to_pids[edge].initialized = true;
else
pr_err("%s: Invalid edge type[%d]\n", __func__, edge);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 8af3890..4b68e66 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -1080,7 +1080,7 @@
msm_get_image_crm_version, msm_set_image_crm_version);
static struct device_attribute select_image =
- __ATTR(select_image, S_IRUGO | S_IWUGO,
+ __ATTR(select_image, S_IRUGO | S_IWUSR,
msm_get_image_number, msm_select_image);
static struct sysdev_class soc_sysdev_class = {
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 1d12b07..9a1a2eb 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -85,6 +85,7 @@
}
#ifdef CONFIG_SMP
thread->vfpstate.hard.cpu = NR_CPUS;
+ vfp_current_hw_state[cpu] = NULL;
#endif
}
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 70c1307..7282c2e 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -353,7 +353,7 @@
if (img->is_contain_build_info) {
img->firmware_id = extract_uint(data->firmware_id);
- img->package_id = (data->pkg_id_rev_msb << 8) |
+ img->package_id = (data->pkg_id_msb << 8) |
data->pkg_id_lsb;
img->package_revision_id = (data->pkg_id_rev_msb << 8) |
data->pkg_id_rev_lsb;
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
old mode 100644
new mode 100755
index 89016ec..de098c9
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -200,17 +200,17 @@
ispif->base + ISPIF_VFE_m_INTF_CMD_0(i));
msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY,
ispif->base + ISPIF_VFE_m_INTF_CMD_1(i));
-
+ pr_debug("%s: base %x", __func__, (unsigned int)ispif->base);
msm_camera_io_w(0, ispif->base +
ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0));
msm_camera_io_w(0, ispif->base +
ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 1));
msm_camera_io_w(0, ispif->base +
- ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0));
+ ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 0));
msm_camera_io_w(0, ispif->base +
- ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 1));
+ ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 1));
msm_camera_io_w(0, ispif->base +
- ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 2));
+ ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 2));
msm_camera_io_w(0, ispif->base +
ISPIF_VFE_m_PIX_INTF_n_CROP(i, 0));
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
old mode 100644
new mode 100755
index 9384a5b..d8608ae
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -177,6 +177,7 @@
static struct msm_cam_clk_info csiphy_8610_clk_info[] = {
{"csiphy_timer_src_clk", 200000000},
{"csiphy_timer_clk", -1},
+ {"csi_ahb_clk", -1},
};
static struct msm_cam_clk_info csiphy_8974_clk_info[] = {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 916df1d..c4516ec 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1251,7 +1251,7 @@
for (i = 0; i < num_entries; i++) {
rc = msm_iommu_map_contig_buffer(venus_qdss_entries[i][0],
- domain, 1 , venus_qdss_entries[i][1],
+ domain, partition, venus_qdss_entries[i][1],
SZ_4K, 0, &iova);
if (rc) {
dprintk(VIDC_ERR,
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index e0a99e2..5952e52 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -4466,8 +4466,8 @@
struct marimba_fm_platform_data *tavarua_pdata;
struct tavarua_device *radio;
- int retval;
- int i;
+ int retval = 0;
+ int i = 0, j = 0;
FMDBG("%s: probe called\n", __func__);
/* private data allocation */
radio = kzalloc(sizeof(struct tavarua_device), GFP_KERNEL);
@@ -4480,6 +4480,7 @@
tavarua_pdata = pdev->dev.platform_data;
radio->pdata = tavarua_pdata;
radio->dev = &pdev->dev;
+ radio->wqueue = NULL;
platform_set_drvdata(pdev, radio);
/* video device allocation */
@@ -4509,15 +4510,16 @@
if (kfifo_alloc_rc!=0) {
printk(KERN_ERR "%s: failed allocating buffers %d\n",
__func__, kfifo_alloc_rc);
- goto err_bufs;
+ retval = -ENOMEM;
+ goto err_all;
}
}
/* initializing the device count */
atomic_set(&radio->users, 1);
radio->xfr_in_progress = 0;
radio->xfr_bytes_left = 0;
- for (i = 0; i < TAVARUA_XFR_MAX; i++)
- radio->pending_xfrs[i] = 0;
+ for (j = 0; j < TAVARUA_XFR_MAX; j++)
+ radio->pending_xfrs[j] = 0;
/* init transmit data */
radio->tx_mode = TAVARUA_TX_RT;
@@ -4548,11 +4550,14 @@
/*Start the worker thread for event handling and register read_int_stat
as worker function*/
radio->wqueue = create_singlethread_workqueue("kfmradio");
- if (!radio->wqueue)
- return -ENOMEM;
+ if (!radio->wqueue) {
+ retval = -ENOMEM;
+ goto err_all;
+ }
/* register video device */
- if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
+ retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+ if (retval != 0) {
printk(KERN_WARNING DRIVER_NAME
": Could not register video device\n");
goto err_all;
@@ -4562,9 +4567,11 @@
err_all:
video_device_release(radio->videodev);
-err_bufs:
- for (; i > -1; i--)
+ if (radio->wqueue)
+ destroy_workqueue(radio->wqueue);
+ for (i--; i >= 0; i--) {
kfifo_free(&radio->data_buf[i]);
+ }
err_radio:
kfree(radio);
err_initial:
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 995d9e4..a296e48 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -61,6 +61,7 @@
/* Flushing a large amount of cached data may take a long time. */
#define MMC_FLUSH_REQ_TIMEOUT_MS 90000 /* msec */
+#define MMC_CACHE_DISBALE_TIMEOUT_MS 180000 /* msec */
static struct workqueue_struct *workqueue;
@@ -3393,14 +3394,14 @@
if (card->ext_csd.cache_ctrl ^ enable) {
if (!enable)
- timeout = MMC_FLUSH_REQ_TIMEOUT_MS;
+ timeout = MMC_CACHE_DISBALE_TIMEOUT_MS;
err = mmc_switch_ignore_timeout(card,
EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_CACHE_CTRL, enable, timeout);
if (err == -ETIMEDOUT && !enable) {
- pr_debug("%s:cache disable operation timeout\n",
+ pr_err("%s:cache disable operation timeout\n",
mmc_hostname(card->host));
rc = mmc_interrupt_hpi(card);
if (rc)
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 554cce8..97592c4 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -2288,8 +2288,12 @@
if (mdwc->otg_xceiv && !mdwc->ext_inuse &&
(mdwc->ext_xceiv.otg_capability || !init)) {
mdwc->ext_xceiv.bsv = val->intval;
+ /*
+ * set debouncing delay to 120msec. Otherwise battery
+ * charging CDP complaince test fails if delay > 120ms.
+ */
queue_delayed_work(system_nrt_wq,
- &mdwc->resume_work, 20);
+ &mdwc->resume_work, 12);
if (!init)
init = true;
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 9599936..cacd635 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -93,6 +93,19 @@
return 0;
}
+static void dwc3_otg_set_hsphy_auto_suspend(struct dwc3_otg *dotg, bool susp)
+{
+ struct dwc3 *dwc = dotg->dwc;
+ u32 reg;
+
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+ if (susp)
+ reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+ else
+ reg &= ~(DWC3_GUSB2PHYCFG_SUSPHY);
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+}
+
/**
* dwc3_otg_set_host_power - Enable port power control for host operation
*
@@ -194,6 +207,7 @@
* remove_hcd, But we may not use standard set_host method
* anymore.
*/
+ dwc3_otg_set_hsphy_auto_suspend(dotg, true);
dwc3_otg_set_host_regs(dotg);
/*
* FIXME If micro A cable is disconnected during system suspend,
@@ -242,6 +256,7 @@
ext_xceiv->ext_block_reset)
ext_xceiv->ext_block_reset(ext_xceiv, true);
+ dwc3_otg_set_hsphy_auto_suspend(dotg, false);
dwc3_otg_set_peripheral_regs(dotg);
/* re-init core and OTG registers as block reset clears these */
@@ -309,12 +324,14 @@
ext_xceiv->ext_block_reset)
ext_xceiv->ext_block_reset(ext_xceiv, false);
+ dwc3_otg_set_hsphy_auto_suspend(dotg, true);
dwc3_otg_set_peripheral_regs(dotg);
usb_gadget_vbus_connect(otg->gadget);
} else {
dev_dbg(otg->phy->dev, "%s: turn off gadget %s\n",
__func__, otg->gadget->name);
usb_gadget_vbus_disconnect(otg->gadget);
+ dwc3_otg_set_hsphy_auto_suspend(dotg, false);
}
return 0;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 99ba8d9..ad3a3a9 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2917,7 +2917,11 @@
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
- dwc3_gadget_usb2_phy_suspend(dwc, true);
+ /*
+ * Clear autosuspend bit in dwc3 register for USB2. It will be
+ * enabled before setting run/stop bit.
+ */
+ dwc3_gadget_usb2_phy_suspend(dwc, false);
dwc3_gadget_usb3_phy_suspend(dwc, true);
}
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index dcfa2bc..7e474f3 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -18,6 +18,7 @@
#include <linux/usb/usb_qdss.h>
#include <linux/usb/msm_hsusb.h>
+#include "gadget_chips.h"
#include "f_qdss.h"
#include "u_qdss.c"
@@ -395,7 +396,9 @@
goto fail;
}
}
- dwc3_tx_fifo_resize_request(qdss->data, true);
+
+ if (gadget_is_dwc3(gadget))
+ dwc3_tx_fifo_resize_request(qdss->data, true);
return 0;
fail:
@@ -408,12 +411,15 @@
static void qdss_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_qdss *qdss = func_to_qdss(f);
+ struct usb_gadget *gadget = c->cdev->gadget;
pr_debug("qdss_unbind\n");
- dwc3_tx_fifo_resize_request(qdss->data, false);
+ if (gadget_is_dwc3(gadget))
+ dwc3_tx_fifo_resize_request(qdss->data, false);
+
clear_eps(f);
- clear_desc(c->cdev->gadget, f);
+ clear_desc(gadget, f);
}
static void qdss_eps_disable(struct usb_function *f)
@@ -824,7 +830,8 @@
ch->app_conn = 0;
spin_unlock_irqrestore(&d_lock, flags);
- msm_dwc3_restart_usb_session(gadget);
+ if (gadget_is_dwc3(gadget))
+ msm_dwc3_restart_usb_session(gadget);
}
EXPORT_SYMBOL(usb_qdss_close);
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 7903764..aee7b58 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -379,13 +379,35 @@
struct sk_buff *skb)
{
struct sk_buff *skb2;
+ struct rndis_packet_msg_type *header = NULL;
+ struct f_rndis *rndis = func_to_rndis(&port->func);
- skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type));
- if (skb2)
- rndis_add_hdr(skb2);
+ if (rndis->port.multi_pkt_xfer) {
+ if (port->header) {
+ header = port->header;
+ memset(header, 0, sizeof(*header));
+ header->MessageType = cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
+ header->MessageLength = cpu_to_le32(skb->len +
+ sizeof(*header));
+ header->DataOffset = cpu_to_le32(36);
+ header->DataLength = cpu_to_le32(skb->len);
+ pr_debug("MessageLength:%d DataLength:%d\n",
+ header->MessageLength,
+ header->DataLength);
+ return skb;
+ } else {
+ pr_err("RNDIS header is NULL.\n");
+ return NULL;
+ }
+ } else {
+ skb2 = skb_realloc_headroom(skb,
+ sizeof(struct rndis_packet_msg_type));
+ if (skb2)
+ rndis_add_hdr(skb2);
- dev_kfree_skb_any(skb);
- return skb2;
+ dev_kfree_skb_any(skb);
+ return skb2;
+ }
}
static void rndis_response_available(void *_rndis)
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 9e789c5..734619f 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -197,6 +197,7 @@
}
static void rx_complete(struct usb_ep *ep, struct usb_request *req);
+static void tx_complete(struct usb_ep *ep, struct usb_request *req);
static int
rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
@@ -256,7 +257,6 @@
req->buf = skb->data;
req->length = size;
- req->complete = rx_complete;
req->context = skb;
retval = usb_ep_queue(out, req, gfp_flags);
@@ -349,6 +349,7 @@
{
unsigned i;
struct usb_request *req;
+ bool usb_in;
if (!n)
return -ENOMEM;
@@ -359,10 +360,22 @@
if (i-- == 0)
goto extra;
}
+
+ if (ep->desc->bEndpointAddress & USB_DIR_IN)
+ usb_in = true;
+ else
+ usb_in = false;
+
while (i--) {
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (!req)
return list_empty(list) ? -ENOMEM : 0;
+ /* update completion handler */
+ if (usb_in)
+ req->complete = tx_complete;
+ else
+ req->complete = rx_complete;
+
list_add(&req->list, list);
}
return 0;
@@ -479,7 +492,7 @@
static void tx_complete(struct usb_ep *ep, struct usb_request *req)
{
- struct sk_buff *skb = req->context;
+ struct sk_buff *skb;
struct eth_dev *dev;
struct net_device *net;
struct usb_request *new_req;
@@ -553,7 +566,6 @@
}
new_req->length = length;
- new_req->complete = tx_complete;
retval = usb_ep_queue(in, new_req, GFP_ATOMIC);
switch (retval) {
default:
@@ -585,6 +597,7 @@
spin_unlock(&dev->req_lock);
}
} else {
+ skb = req->context;
spin_unlock(&dev->req_lock);
dev_kfree_skb_any(skb);
}
@@ -613,7 +626,7 @@
list_for_each(act, &dev->tx_reqs) {
req = container_of(act, struct usb_request, list);
if (!req->buf)
- req->buf = kmalloc(dev->tx_req_bufsize,
+ req->buf = kzalloc(dev->tx_req_bufsize,
GFP_ATOMIC);
if (!req->buf)
goto free_buf;
@@ -626,6 +639,7 @@
list_for_each(act, &dev->tx_reqs) {
req = container_of(act, struct usb_request, list);
kfree(req->buf);
+ req->buf = NULL;
}
return -ENOMEM;
}
@@ -710,28 +724,37 @@
* or the hardware can't use skb buffers.
* or there's not enough space for extra headers we need
*/
+ spin_lock_irqsave(&dev->lock, flags);
if (dev->wrap) {
- unsigned long flags;
-
- spin_lock_irqsave(&dev->lock, flags);
if (dev->port_usb)
skb = dev->wrap(dev->port_usb, skb);
- spin_unlock_irqrestore(&dev->lock, flags);
- if (!skb)
+ if (!skb) {
+ spin_unlock_irqrestore(&dev->lock, flags);
goto drop;
+ }
}
- spin_lock_irqsave(&dev->req_lock, flags);
- dev->tx_skb_hold_count++;
- spin_unlock_irqrestore(&dev->req_lock, flags);
-
if (multi_pkt_xfer) {
+
+ pr_debug("req->length:%d header_len:%u\n"
+ "skb->len:%d skb->data_len:%d\n",
+ req->length, dev->header_len,
+ skb->len, skb->data_len);
+ /* Add RNDIS Header */
+ memcpy(req->buf + req->length, dev->port_usb->header,
+ dev->header_len);
+ /* Increment req length by header size */
+ req->length += dev->header_len;
+ spin_unlock_irqrestore(&dev->lock, flags);
+ /* Copy received IP data from SKB */
memcpy(req->buf + req->length, skb->data, skb->len);
- req->length = req->length + skb->len;
+ /* Increment req length by skb data length */
+ req->length += skb->len;
length = req->length;
dev_kfree_skb_any(skb);
spin_lock_irqsave(&dev->req_lock, flags);
+ dev->tx_skb_hold_count++;
if (dev->tx_skb_hold_count < dev->dl_max_pkts_per_xfer) {
if (dev->no_tx_req_used > TX_REQ_THRESHOLD) {
list_add(&req->list, &dev->tx_reqs);
@@ -741,19 +764,15 @@
}
dev->no_tx_req_used++;
- spin_unlock_irqrestore(&dev->req_lock, flags);
-
- spin_lock_irqsave(&dev->lock, flags);
dev->tx_skb_hold_count = 0;
- spin_unlock_irqrestore(&dev->lock, flags);
+ spin_unlock_irqrestore(&dev->req_lock, flags);
} else {
+ spin_unlock_irqrestore(&dev->lock, flags);
length = skb->len;
req->buf = skb->data;
req->context = skb;
}
- req->complete = tx_complete;
-
/* NCM requires no zlp if transfer is dwNtbInMaxSize */
if (dev->port_usb->is_fixed &&
length == dev->port_usb->fixed_in_len &&
@@ -806,7 +825,7 @@
spin_lock_irqsave(&dev->req_lock, flags);
if (list_empty(&dev->tx_reqs))
netif_start_queue(net);
- list_add(&req->list, &dev->tx_reqs);
+ list_add_tail(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->req_lock, flags);
}
success:
@@ -1085,6 +1104,14 @@
if (!dev)
return ERR_PTR(-EINVAL);
+ link->header = kzalloc(sizeof(struct rndis_packet_msg_type),
+ GFP_ATOMIC);
+ if (!link->header) {
+ pr_err("RNDIS header memory allocation failed.\n");
+ result = -ENOMEM;
+ goto fail;
+ }
+
link->in_ep->driver_data = dev;
result = usb_ep_enable(link->in_ep);
if (result != 0) {
@@ -1105,6 +1132,7 @@
result = alloc_requests(dev, link, qlen(dev->gadget));
if (result == 0) {
+
dev->zlp = link->is_zlp_ok;
DBG(dev, "qlen %d\n", qlen(dev->gadget));
@@ -1139,10 +1167,15 @@
fail1:
(void) usb_ep_disable(link->in_ep);
}
-fail0:
+
/* caller is responsible for cleanup on error */
- if (result < 0)
+ if (result < 0) {
+fail0:
+ kfree(link->header);
+fail:
return ERR_PTR(result);
+ }
+
return dev->net;
}
@@ -1184,11 +1217,16 @@
list_del(&req->list);
spin_unlock(&dev->req_lock);
- if (link->multi_pkt_xfer)
+ if (link->multi_pkt_xfer) {
kfree(req->buf);
+ req->buf = NULL;
+ }
usb_ep_free_request(link->in_ep, req);
spin_lock(&dev->req_lock);
}
+ /* Free rndis header buffer memory */
+ kfree(link->header);
+ link->header = NULL;
spin_unlock(&dev->req_lock);
link->in_ep->driver_data = NULL;
link->in_ep->desc = NULL;
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 05984d8..2c5da77 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -66,6 +66,8 @@
/* called on network open/close */
void (*open)(struct gether *);
void (*close)(struct gether *);
+ struct rndis_packet_msg_type *header;
+
};
#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
diff --git a/drivers/usb/gadget/u_qdss.c b/drivers/usb/gadget/u_qdss.c
index e241e29..23d4d06 100644
--- a/drivers/usb/gadget/u_qdss.c
+++ b/drivers/usb/gadget/u_qdss.c
@@ -14,6 +14,7 @@
#include <linux/device.h>
#include <linux/usb/msm_hsusb.h>
#include <mach/usb_bam.h>
+#include "gadget_chips.h"
struct usb_qdss_bam_connect_info {
u32 usb_bam_pipe_idx;
@@ -88,8 +89,11 @@
&bam_info.usb_bam_pipe_idx, &bam_info.peer_pipe_idx,
NULL, bam_info.data_fifo);
- msm_data_fifo_config(data_ep, bam_info.data_fifo->phys_base,
- bam_info.data_fifo->size, bam_info.usb_bam_pipe_idx);
+ if (gadget_is_dwc3(gadget))
+ msm_data_fifo_config(data_ep,
+ bam_info.data_fifo->phys_base,
+ bam_info.data_fifo->size,
+ bam_info.usb_bam_pipe_idx);
} else {
kfree(bam_info.data_fifo);
res = usb_bam_disconnect_pipe(idx);
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index 5c3960d..31e93a5 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -166,6 +166,9 @@
int tooff = 0, fromoff = 0;
int size;
+ if (!to || !from)
+ return -EINVAL;
+
if (to->start > from->start)
fromoff = to->start - from->start;
else
@@ -177,9 +180,12 @@
return -EINVAL;
size *= sizeof(u16);
- memcpy(to->red+tooff, from->red+fromoff, size);
- memcpy(to->green+tooff, from->green+fromoff, size);
- memcpy(to->blue+tooff, from->blue+fromoff, size);
+ if (from->red && to->red)
+ memcpy(to->red+tooff, from->red+fromoff, size);
+ if (from->green && to->green)
+ memcpy(to->green+tooff, from->green+fromoff, size);
+ if (from->blue && to->blue)
+ memcpy(to->blue+tooff, from->blue+fromoff, size);
if (from->transp && to->transp)
memcpy(to->transp+tooff, from->transp+fromoff, size);
return 0;
@@ -190,6 +196,9 @@
int tooff = 0, fromoff = 0;
int size;
+ if (!to || !from)
+ return -EINVAL;
+
if (to->start > from->start)
fromoff = to->start - from->start;
else
@@ -201,12 +210,15 @@
return -EINVAL;
size *= sizeof(u16);
- if (copy_to_user(to->red+tooff, from->red+fromoff, size))
- return -EFAULT;
- if (copy_to_user(to->green+tooff, from->green+fromoff, size))
- return -EFAULT;
- if (copy_to_user(to->blue+tooff, from->blue+fromoff, size))
- return -EFAULT;
+ if (from->red && to->red)
+ if (copy_to_user(to->red+tooff, from->red+fromoff, size))
+ return -EFAULT;
+ if (from->green && to->green)
+ if (copy_to_user(to->green+tooff, from->green+fromoff, size))
+ return -EFAULT;
+ if (from->blue && to->blue)
+ if (copy_to_user(to->blue+tooff, from->blue+fromoff, size))
+ return -EFAULT;
if (from->transp && to->transp)
if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
return -EFAULT;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index d6a664a..6b84107 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1113,6 +1113,10 @@
if (copy_from_user(&cmap, argp, sizeof(cmap)))
return -EFAULT;
ret = fb_set_user_cmap(&cmap, info);
+ if (ret) {
+ if (info)
+ fb_dealloc_cmap(&info->cmap);
+ }
break;
case FBIOGETCMAP:
if (copy_from_user(&cmap, argp, sizeof(cmap)))
diff --git a/drivers/video/msm/mdss/Kconfig b/drivers/video/msm/mdss/Kconfig
index 7682a49..b49e08e 100644
--- a/drivers/video/msm/mdss/Kconfig
+++ b/drivers/video/msm/mdss/Kconfig
@@ -20,3 +20,11 @@
Support the HDMI to MHL conversion.
MHL (Mobile High-Definition Link) technology
uses USB connector to output HDMI content
+
+config FB_MSM_MDSS_DSI_CTRL_STATUS
+ tristate "DSI controller status check feature"
+ ---help---
+ Check DSI controller status periodically (default period is 5
+ seconds) by sending Bus-Turn-Around (BTA) command. If DSI controller
+ fails to acknowledge the BTA command, it sends PANEL_ALIVE=0 status
+ to HAL layer to reset the controller.
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index ba14d67..8f5fa26 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -41,3 +41,5 @@
obj-$(CONFIG_FB_MSM_QPIC_ILI_QVGA_PANEL) += qpic_panel_ili_qvga.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o
+
+obj-$(CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS) += mdss_dsi_status.o
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 994e3e0..b123ccb 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -509,6 +509,9 @@
panel = mdp3_session->panel;
mutex_lock(&mdp3_session->lock);
+ if (panel && panel->set_backlight)
+ panel->set_backlight(panel, 0);
+
if (!mdp3_session->status) {
pr_debug("fb%d is off already", mfd->index);
goto off_error;
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 927cfa9..bb1f8ae 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -1305,6 +1305,7 @@
}
ctrl_pdata->panel_data.event_handler = mdss_dsi_event_handler;
+ ctrl_pdata->check_status = mdss_dsi_bta_status_check;
if (ctrl_pdata->bklt_ctrl == BL_PWM)
mdss_dsi_panel_pwm_cfg(ctrl_pdata);
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 13dad06..7202c62 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -118,6 +118,8 @@
#define DSI_INTR_ERROR_MASK BIT(25)
#define DSI_INTR_ERROR BIT(24)
+#define DSI_INTR_BTA_DONE_MASK BIT(21)
+#define DSI_INTR_BTA_DONE BIT(20)
#define DSI_INTR_VIDEO_DONE_MASK BIT(17)
#define DSI_INTR_VIDEO_DONE BIT(16)
#define DSI_INTR_CMD_MDP_DONE_MASK BIT(9)
@@ -133,6 +135,7 @@
#define DSI_VIDEO_TERM BIT(16)
#define DSI_MDP_TERM BIT(8)
+#define DSI_BTA_TERM BIT(1)
#define DSI_CMD_TERM BIT(0)
extern struct device dsi_dev;
@@ -315,6 +318,7 @@
int (*on) (struct mdss_panel_data *pdata);
int (*off) (struct mdss_panel_data *pdata);
int (*partial_update_fnc) (struct mdss_panel_data *pdata);
+ int (*check_status) (struct mdss_dsi_ctrl_pdata *pdata);
struct mdss_panel_data panel_data;
unsigned char *ctrl_base;
int reg_size;
@@ -360,6 +364,7 @@
struct completion dma_comp;
struct completion mdp_comp;
struct completion video_comp;
+ struct completion bta_comp;
spinlock_t irq_lock;
spinlock_t mdp_lock;
int mdp_busy;
@@ -428,6 +433,7 @@
struct dcs_cmd_req *cmdreq);
struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_cmdlist_kickoff(int intf);
+int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl);
int mdss_dsi_panel_init(struct device_node *node,
struct mdss_dsi_ctrl_pdata *ctrl_pdata,
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index bb2818b..750fbf3 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -49,6 +49,8 @@
#define DSI_EVENT_Q_MAX 4
+#define DSI_BTA_EVENT_TIMEOUT (HZ / 10)
+
/* event */
struct dsi_event_q {
struct mdss_dsi_ctrl_pdata *ctrl;
@@ -98,6 +100,7 @@
init_completion(&ctrl->dma_comp);
init_completion(&ctrl->mdp_comp);
init_completion(&ctrl->video_comp);
+ init_completion(&ctrl->bta_comp);
spin_lock_init(&ctrl->irq_lock);
spin_lock_init(&ctrl->mdp_lock);
mutex_init(&ctrl->mutex);
@@ -1107,14 +1110,14 @@
if (mode == DSI_VIDEO_MODE) {
dsi_ctrl |= 0x03;
- intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK;
+ intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_BTA_DONE_MASK;
} else { /* command mode */
dsi_ctrl |= 0x05;
if (pdata->panel_info.type == MIPI_VIDEO_PANEL)
dsi_ctrl |= 0x02;
intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK |
- DSI_INTR_CMD_MDP_DONE_MASK;
+ DSI_INTR_CMD_MDP_DONE_MASK | DSI_INTR_BTA_DONE_MASK;
}
if (ctrl_pdata->shared_pdata.broadcast_enable)
@@ -1160,6 +1163,45 @@
pr_debug("%s: BTA done, status = %d\n", __func__, status);
}
+int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+ int ret = 0;
+ unsigned long flag;
+
+ if (ctrl_pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+
+ /*
+ * This should not return error otherwise
+ * BTA status thread will treat it as dead panel scenario
+ * and request for blank/unblank
+ */
+ return 0;
+ }
+
+ pr_debug("%s: Checking BTA status\n", __func__);
+
+ mdss_dsi_clk_ctrl(ctrl_pdata, 1);
+ spin_lock_irqsave(&ctrl_pdata->mdp_lock, flag);
+ INIT_COMPLETION(ctrl_pdata->bta_comp);
+ mdss_dsi_enable_irq(ctrl_pdata, DSI_BTA_TERM);
+ spin_unlock_irqrestore(&ctrl_pdata->mdp_lock, flag);
+ MIPI_OUTP(ctrl_pdata->ctrl_base + 0x098, 0x01); /* trigger */
+ wmb();
+
+ ret = wait_for_completion_killable_timeout(&ctrl_pdata->bta_comp,
+ DSI_BTA_EVENT_TIMEOUT);
+ if (ret <= 0) {
+ mdss_dsi_disable_irq(ctrl_pdata, DSI_BTA_TERM);
+ pr_err("%s: DSI BTA error: %i\n", __func__, ret);
+ }
+
+ mdss_dsi_clk_ctrl(ctrl_pdata, 0);
+ pr_debug("%s: BTA done with ret: %d\n", __func__, ret);
+
+ return ret;
+}
+
static char set_tear_on[2] = {0x35, 0x00};
static struct dsi_cmd_desc dsi_tear_on_cmd = {
{DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on)}, set_tear_on};
@@ -2078,5 +2120,12 @@
spin_unlock(&ctrl->mdp_lock);
}
+ if (isr & DSI_INTR_BTA_DONE) {
+ spin_lock(&ctrl->mdp_lock);
+ mdss_dsi_disable_irq_nosync(ctrl, DSI_BTA_TERM);
+ complete(&ctrl->bta_comp);
+ spin_unlock(&ctrl->mdp_lock);
+ }
+
return IRQ_HANDLED;
}
diff --git a/drivers/video/msm/mdss/mdss_dsi_status.c b/drivers/video/msm/mdss/mdss_dsi_status.c
new file mode 100644
index 0000000..f0c4f4c
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi_status.c
@@ -0,0 +1,208 @@
+/* Copyright (c) 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/notifier.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/iopoll.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+
+#include "mdss_fb.h"
+#include "mdss_dsi.h"
+#include "mdss_panel.h"
+#include "mdss_mdp.h"
+
+#define STATUS_CHECK_INTERVAL 5000
+
+struct dsi_status_data {
+ struct notifier_block fb_notifier;
+ struct delayed_work check_status;
+ struct msm_fb_data_type *mfd;
+ uint32_t check_interval;
+};
+struct dsi_status_data *pstatus_data;
+static uint32_t interval = STATUS_CHECK_INTERVAL;
+
+/*
+ * check_dsi_ctrl_status() - Check DSI controller status periodically.
+ * @work : dsi controller status data
+ *
+ * This function calls check_status API on DSI controller to send the BTA
+ * command. If DSI controller fails to acknowledge the BTA command, it sends
+ * the PANEL_ALIVE=0 status to HAL layer.
+ */
+static void check_dsi_ctrl_status(struct work_struct *work)
+{
+ struct dsi_status_data *pdsi_status = NULL;
+ struct mdss_panel_data *pdata = NULL;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ struct mdss_overlay_private *mdp5_data = NULL;
+ struct mdss_mdp_ctl *ctl = NULL;
+ int ret = 0;
+
+ pdsi_status = container_of(to_delayed_work(work),
+ struct dsi_status_data, check_status);
+ if (!pdsi_status) {
+ pr_err("%s: DSI status data not available\n", __func__);
+ return;
+ }
+
+ pdata = dev_get_platdata(&pdsi_status->mfd->pdev->dev);
+ if (!pdata) {
+ pr_err("%s: Panel data not available\n", __func__);
+ return;
+ }
+
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+ if (!ctrl_pdata || !ctrl_pdata->check_status) {
+ pr_err("%s: DSI ctrl or status_check callback not available\n",
+ __func__);
+ return;
+ }
+
+ mdp5_data = mfd_to_mdp5_data(pdsi_status->mfd);
+ ctl = mfd_to_ctl(pdsi_status->mfd);
+
+ if (ctl->shared_lock)
+ mutex_lock(ctl->shared_lock);
+ mutex_lock(&mdp5_data->ov_lock);
+
+ /*
+ * For the command mode panels, we return pan display
+ * IOCTL on vsync interrupt. So, after vsync interrupt comes
+ * and when DMA_P is in progress, if the panel stops responding
+ * and if we trigger BTA before DMA_P finishes, then the DSI
+ * FIFO will not be cleared since the DSI data bus control
+ * doesn't come back to the host after BTA. This may cause the
+ * display reset not to be proper. Hence, wait for DMA_P done
+ * for command mode panels before triggering BTA.
+ */
+ if (ctl->wait_pingpong)
+ ctl->wait_pingpong(ctl, NULL);
+
+ pr_debug("%s: DSI ctrl wait for ping pong done\n", __func__);
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ ret = ctrl_pdata->check_status(ctrl_pdata);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+ mutex_unlock(&mdp5_data->ov_lock);
+ if (ctl->shared_lock)
+ mutex_unlock(ctl->shared_lock);
+
+ if ((pdsi_status->mfd->panel_power_on)) {
+ if (ret > 0) {
+ schedule_delayed_work(&pdsi_status->check_status,
+ msecs_to_jiffies(pdsi_status->check_interval));
+ } else {
+ char *envp[2] = {"PANEL_ALIVE=0", NULL};
+ pdata->panel_info.panel_dead = true;
+ ret = kobject_uevent_env(
+ &pdsi_status->mfd->fbi->dev->kobj,
+ KOBJ_CHANGE, envp);
+ pr_err("%s: Panel has gone bad, sending uevent - %s\n",
+ __func__, envp[0]);
+ }
+ }
+}
+
+/*
+ * fb_event_callback() - Call back function for the fb_register_client()
+ * notifying events
+ * @self : notifier block
+ * @event : The event that was triggered
+ * @data : Of type struct fb_event
+ *
+ * This function listens for FB_BLANK_UNBLANK and FB_BLANK_POWERDOWN events
+ * from frame buffer. DSI status check work is either scheduled again after
+ * PANEL_STATUS_CHECK_INTERVAL or cancelled based on the event.
+ */
+static int fb_event_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ struct dsi_status_data *pdata = container_of(self,
+ struct dsi_status_data, fb_notifier);
+ pdata->mfd = evdata->info->par;
+
+ if (event == FB_EVENT_BLANK && evdata) {
+ int *blank = evdata->data;
+ switch (*blank) {
+ case FB_BLANK_UNBLANK:
+ schedule_delayed_work(&pdata->check_status,
+ msecs_to_jiffies(pdata->check_interval));
+ break;
+ case FB_BLANK_POWERDOWN:
+ cancel_delayed_work(&pdata->check_status);
+ break;
+ }
+ }
+ return 0;
+}
+
+int __init mdss_dsi_status_init(void)
+{
+ int rc = 0;
+
+ pstatus_data = kzalloc(sizeof(struct dsi_status_data), GFP_KERNEL);
+ if (!pstatus_data) {
+ pr_err("%s: can't allocate memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ pstatus_data->fb_notifier.notifier_call = fb_event_callback;
+
+ rc = fb_register_client(&pstatus_data->fb_notifier);
+ if (rc < 0) {
+ pr_err("%s: fb_register_client failed, returned with rc=%d\n",
+ __func__, rc);
+ kfree(pstatus_data);
+ return -EPERM;
+ }
+
+ pstatus_data->check_interval = interval;
+ pr_info("%s: DSI status check interval:%d\n", __func__, interval);
+
+ INIT_DELAYED_WORK(&pstatus_data->check_status, check_dsi_ctrl_status);
+
+ pr_debug("%s: DSI ctrl status work queue initialized\n", __func__);
+
+ return rc;
+}
+
+void __exit mdss_dsi_status_exit(void)
+{
+ fb_unregister_client(&pstatus_data->fb_notifier);
+ cancel_delayed_work_sync(&pstatus_data->check_status);
+ kfree(pstatus_data);
+ pr_debug("%s: DSI ctrl status work queue removed\n", __func__);
+}
+
+module_param(interval, uint, 0);
+MODULE_PARM_DESC(interval,
+ "Duration in milliseconds to send BTA command for checking"
+ "DSI status periodically");
+
+module_init(mdss_dsi_status_init);
+module_exit(mdss_dsi_status_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 047c0f0..5edaeb2 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -107,9 +107,10 @@
static int mdss_fb_notify_update(struct msm_fb_data_type *mfd,
unsigned long *argp)
{
- int ret, notify, to_user;
+ int ret;
+ unsigned long notify = 0x0, to_user = 0x0;
- ret = copy_from_user(¬ify, argp, sizeof(int));
+ ret = copy_from_user(¬ify, argp, sizeof(unsigned long));
if (ret) {
pr_err("%s:ioctl failed\n", __func__);
return ret;
@@ -122,12 +123,12 @@
INIT_COMPLETION(mfd->update.comp);
ret = wait_for_completion_interruptible_timeout(
&mfd->update.comp, 4 * HZ);
- to_user = mfd->update.value;
+ to_user = (unsigned int)mfd->update.value;
} else if (notify == NOTIFY_UPDATE_STOP) {
INIT_COMPLETION(mfd->no_update.comp);
ret = wait_for_completion_interruptible_timeout(
&mfd->no_update.comp, 4 * HZ);
- to_user = mfd->no_update.value;
+ to_user = (unsigned int)mfd->no_update.value;
} else {
if (mfd->panel_power_on) {
INIT_COMPLETION(mfd->power_off_comp);
@@ -139,7 +140,7 @@
if (ret == 0)
ret = -ETIMEDOUT;
else if (ret > 0)
- ret = copy_to_user(argp, &to_user, sizeof(int));
+ ret = copy_to_user(argp, &to_user, sizeof(unsigned long));
return ret;
}
@@ -705,8 +706,10 @@
case FB_BLANK_UNBLANK:
if (!mfd->panel_power_on && mfd->mdp.on_fnc) {
ret = mfd->mdp.on_fnc(mfd);
- if (ret == 0)
+ if (ret == 0) {
mfd->panel_power_on = true;
+ mfd->panel_info->panel_dead = false;
+ }
mutex_lock(&mfd->update.lock);
mfd->update.type = NOTIFY_TYPE_UPDATE;
mutex_unlock(&mfd->update.lock);
@@ -1410,7 +1413,7 @@
u32 wait_for_finish = disp_commit->wait_for_finish;
int ret = 0;
- if ((!mfd->op_enable) || (!mfd->panel_power_on))
+ if (!mfd || (!mfd->op_enable) || (!mfd->panel_power_on))
return -EPERM;
if (var->xoffset > (info->var.xres_virtual - info->var.xres))
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index abb72ad..87b7526 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -372,6 +372,7 @@
static void hdmi_tx_wait_for_audio_engine(struct hdmi_tx_ctrl *hdmi_ctrl)
{
u32 status = 0;
+ u32 wait_for_vote = 50;
struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
@@ -385,6 +386,18 @@
return;
}
+ /*
+ * wait for 5 sec max for audio engine to acknowledge if hdmi tx core
+ * can be safely turned off. Sleep for a reasonable time to make sure
+ * vote_hdmi_core_on variable is updated properly by audio.
+ */
+ while (hdmi_ctrl->vote_hdmi_core_on && --wait_for_vote)
+ msleep(100);
+
+
+ if (!wait_for_vote)
+ DEV_ERR("%s: HDMI core still voted for power on\n", __func__);
+
if (readl_poll_timeout(io->base + HDMI_AUDIO_PKT_CTRL, status,
(status & BIT(0)) == 0, AUDIO_POLL_SLEEP_US,
AUDIO_POLL_TIMEOUT_US))
@@ -2238,6 +2251,29 @@
return 0;
}
+static int hdmi_tx_get_cable_status(struct platform_device *pdev, u32 vote)
+{
+ struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
+ unsigned long flags;
+ u32 hpd;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -ENODEV;
+ }
+
+ spin_lock_irqsave(&hdmi_ctrl->hpd_state_lock, flags);
+ hpd = hdmi_ctrl->hpd_state;
+ spin_unlock_irqrestore(&hdmi_ctrl->hpd_state_lock, flags);
+
+ hdmi_ctrl->vote_hdmi_core_on = false;
+
+ if (vote && hpd)
+ hdmi_ctrl->vote_hdmi_core_on = true;
+
+ return hpd;
+}
+
int msm_hdmi_register_audio_codec(struct platform_device *pdev,
struct msm_hdmi_audio_codec_ops *ops)
{
@@ -2250,6 +2286,7 @@
ops->audio_info_setup = hdmi_tx_audio_info_setup;
ops->get_audio_edid_blk = hdmi_tx_get_audio_edid_blk;
+ ops->hdmi_cable_status = hdmi_tx_get_cable_status;
return 0;
} /* hdmi_tx_audio_register */
@@ -2572,6 +2609,7 @@
{
int rc = 0;
struct dss_io_data *io = NULL;
+ unsigned long flags;
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -2611,7 +2649,10 @@
DEV_INFO("%s: Failed to disable hpd power. Error=%d\n",
__func__, rc);
+ spin_lock_irqsave(&hdmi_ctrl->hpd_state_lock, flags);
hdmi_ctrl->hpd_state = false;
+ spin_unlock_irqrestore(&hdmi_ctrl->hpd_state_lock, flags);
+
hdmi_ctrl->hpd_initialized = false;
} /* hdmi_tx_hpd_off */
@@ -2737,6 +2778,7 @@
{
struct dss_io_data *io = NULL;
struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)data;
+ unsigned long flags;
if (!hdmi_ctrl) {
DEV_WARN("%s: invalid input data, ISR ignored\n", __func__);
@@ -2751,8 +2793,10 @@
}
if (DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(0)) {
+ spin_lock_irqsave(&hdmi_ctrl->hpd_state_lock, flags);
hdmi_ctrl->hpd_state =
(DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
+ spin_unlock_irqrestore(&hdmi_ctrl->hpd_state_lock, flags);
/*
* Ack the current hpd interrupt and stop listening to
@@ -2851,6 +2895,8 @@
INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);
+ spin_lock_init(&hdmi_ctrl->hpd_state_lock);
+
hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index c4d0326..66071e9 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -58,6 +58,7 @@
struct switch_dev sdev;
struct switch_dev audio_sdev;
struct workqueue_struct *workq;
+ spinlock_t hpd_state_lock;
uint32_t video_resolution;
@@ -68,6 +69,7 @@
u32 hpd_off_pending;
u32 hpd_feature_on;
u32 hpd_initialized;
+ u32 vote_hdmi_core_on;
u8 timing_gen_on;
u32 mhl_max_pclk;
u8 mhl_hpd_on;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index 6056f21..d3e18ac 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -532,6 +532,7 @@
int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_cmd_ctx *ctx;
+ struct mdss_panel_info *pinfo;
unsigned long flags;
struct mdss_mdp_vsync_handler *tmp, *handle;
int need_wait = 0;
@@ -555,9 +556,23 @@
if (need_wait)
if (wait_for_completion_timeout(&ctx->stop_comp, STOP_TIMEOUT)
- <= 0)
+ <= 0) {
WARN(1, "stop cmd time out\n");
+ if (IS_ERR_OR_NULL(ctl->panel_data)) {
+ pr_err("no panel data\n");
+ } else {
+ pinfo = &ctl->panel_data->panel_info;
+
+ if (pinfo->panel_dead) {
+ mdss_mdp_irq_disable
+ (MDSS_MDP_IRQ_PING_PONG_RD_PTR,
+ ctx->pp_num);
+ ctx->rdptr_enabled = 0;
+ }
+ }
+ }
+
if (cancel_work_sync(&ctx->clk_work))
pr_debug("no pending clk work\n");
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index c565d98..f096f16 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1475,15 +1475,26 @@
static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl,
ktime_t t)
{
- struct msm_fb_data_type *mfd = ctl->mfd;
- struct mdss_overlay_private *mdp5_data;
+ struct msm_fb_data_type *mfd = NULL;
+ struct mdss_overlay_private *mdp5_data = NULL;
+ if (!ctl) {
+ pr_err("ctl is NULL\n");
+ return;
+ }
+
+ mfd = ctl->mfd;
if (!mfd || !mfd->mdp.private1) {
pr_warn("Invalid handle for vsync\n");
return;
}
mdp5_data = mfd_to_mdp5_data(mfd);
+ if (!mdp5_data) {
+ pr_err("mdp5_data is NULL\n");
+ return;
+ }
+
pr_debug("vsync on fb%d play_cnt=%d\n", mfd->index, ctl->play_cnt);
mdp5_data->vsync_time = t;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 779f74c..72c8759 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -728,7 +728,8 @@
dst = pipe->dst;
src = pipe->src;
- mdss_mdp_crop_rect(&src, &dst, &sci);
+ if (pipe->mixer->type == MDSS_MDP_MIXER_TYPE_INTF)
+ mdss_mdp_crop_rect(&src, &dst, &sci);
src_size = (src.h << 16) | src.w;
src_xy = (src.y << 16) | src.x;
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index c4e1956..d29323d3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -132,6 +132,16 @@
pr_debug("setting secure=%d\n", enable);
+ if (!ctl || !ctl->mdata) {
+ pr_err("%s : ctl is NULL", __func__);
+ return -EINVAL;
+ }
+
+ if (!wb) {
+ pr_err("unable to start, writeback is not initialized\n");
+ return -ENODEV;
+ }
+
ctl->is_secure = enable;
wb->is_secure = enable;
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 75fc095..b859598 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -299,6 +299,8 @@
struct ion_handle *splash_ihdl;
u32 panel_power_on;
+ uint32_t panel_dead;
+
struct lcd_panel_info lcdc;
struct fbc_panel_info fbc;
struct mipi_panel_info mipi;
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index bc02513..6dc2ec0 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -5975,6 +5975,10 @@
/* Set HPH Path to low power mode */
TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x55),
+
+ /* BUCK default */
+ TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x51),
+ TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
};
static const struct wcd9xxx_reg_mask_val taiko_1_0_reg_defaults[] = {
@@ -5983,13 +5987,9 @@
* Taiko 2.0 will have appropriate defaults for these registers.
*/
- /* BUCK default */
- TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x50),
-
/* Required defaults for class H operation */
TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xF4),
TAIKO_REG_VAL(TAIKO_A_BIAS_CURR_CTL_2, 0x08),
- TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_3, 0x60),
/* Choose max non-overlap time for NCP */
@@ -6040,7 +6040,7 @@
TAIKO_REG_VAL(TAIKO_A_CDC_TX_5_6_ADC_IB, 0x44),
TAIKO_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x8),
- TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x51),
+ TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_CCL_4, 0x51),
TAIKO_REG_VAL(TAIKO_A_NCP_DTEST, 0x10),
TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xA4),
TAIKO_REG_VAL(TAIKO_A_RX_HPH_OCP_CTL, 0x69),
@@ -6081,6 +6081,7 @@
TAIKO_REG_VAL(TAIKO_A_CDC_SPKR_CLIPDET_B1_CTL, 0x0),
TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B4_CTL, 0x37),
TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B5_CTL, 0x7f),
+ TAIKO_REG_VAL(TAIKO_A_CDC_COMP0_B5_CTL, 0x7f),
};
static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index 05f2191..b104a6b 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -22,12 +22,11 @@
#define CLSH_COMPUTE_HPH_L 0x02
#define CLSH_COMPUTE_HPH_R 0x03
+#define BUCK_VREF_0P494V 0x3F
#define BUCK_VREF_2V 0xFF
+#define BUCK_VREF_0P494V 0x3F
#define BUCK_VREF_1P8V 0xE6
-#define NCP_FCLK_LEVEL_8 0x08
-#define NCP_FCLK_LEVEL_5 0x05
-
#define BUCK_SETTLE_TIME_US 50
#define NCP_SETTLE_TIME_US 50
@@ -414,12 +413,16 @@
{32164, 22},
};
-static inline void wcd9xxx_enable_clsh_block(
- struct snd_soc_codec *codec,
- bool on)
+static inline void
+wcd9xxx_enable_clsh_block(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d, bool enable)
{
- snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLSH_B1_CTL,
- 0x01, on ? 0x01 : 0x00);
+ if ((enable && ++clsh_d->clsh_users == 1) ||
+ (!enable && --clsh_d->clsh_users == 0))
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLSH_B1_CTL,
+ 0x01, enable ? 0x01 : 0x00);
+ dev_dbg(codec->dev, "%s: clsh_users %d, enable %d", __func__,
+ clsh_d->clsh_users, enable);
}
static inline void wcd9xxx_enable_anc_delay(
@@ -430,64 +433,56 @@
0x02, on ? 0x02 : 0x00);
}
-static inline void wcd9xxx_enable_ncp(
- struct snd_soc_codec *codec,
- bool on)
+static inline void
+wcd9xxx_enable_buck(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d, bool enable)
{
- snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN,
- 0x01, on ? 0x01 : 0x00);
+ if ((enable && ++clsh_d->buck_users == 1) ||
+ (!enable && --clsh_d->buck_users == 0))
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
+ 0x80, enable ? 0x80 : 0x00);
+ dev_dbg(codec->dev, "%s: buck_users %d, enable %d", __func__,
+ clsh_d->buck_users, enable);
}
-static inline void wcd9xxx_enable_buck(
- struct snd_soc_codec *codec,
- bool on)
-{
- snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
- 0x80, on ? 0x80 : 0x00);
-}
+static void (*clsh_state_fp[NUM_CLSH_STATES])(struct snd_soc_codec *,
+ struct wcd9xxx_clsh_cdc_data *,
+ u8 req_state, bool req_type);
-static int cdc_lo_count;
-
-static void (*clsh_state_fp[NUM_CLSH_STATES])
- (struct snd_soc_codec *,
- struct wcd9xxx_clsh_cdc_data *,
- u8 req_state, bool req_type);
-
-static const char *state_to_str(u8 state)
-{
- if (state == WCD9XXX_CLSH_STATE_IDLE)
- return "STATE_IDLE";
- else if (state == WCD9XXX_CLSH_STATE_EAR)
- return "STATE_EAR";
- else if (state == WCD9XXX_CLSH_STATE_HPHL)
- return "STATE_HPH_L";
- else if (state == WCD9XXX_CLSH_STATE_HPHR)
- return "STATE_HPH_R";
- else if (state == (WCD9XXX_CLSH_STATE_HPHL
- | WCD9XXX_CLSH_STATE_HPHR))
- return "STATE_HPH_L_R";
- else if (state == WCD9XXX_CLSH_STATE_LO)
- return "STATE_LO";
-
- return "UNKNOWN_STATE";
-}
-
-static void wcd9xxx_cfg_clsh_buck(
- struct snd_soc_codec *codec)
+static const char *state_to_str(u8 state, char *buf, size_t buflen)
{
int i;
- const struct wcd9xxx_reg_mask_val reg_set[] = {
- {WCD9XXX_A_BUCK_CTRL_CCL_4, 0x0B, 0x00},
- {WCD9XXX_A_BUCK_CTRL_CCL_1, 0xF0, 0x50},
- {WCD9XXX_A_BUCK_CTRL_CCL_3, 0x03, 0x00},
- {WCD9XXX_A_BUCK_CTRL_CCL_3, 0x0B, 0x00},
+ int cnt = 0;
+ /*
+ * This array of strings should match with enum wcd9xxx_clsh_state_bit.
+ */
+ const char *states[] = {
+ "STATE_EAR",
+ "STATE_HPH_L",
+ "STATE_HPH_R",
+ "STATE_LO",
};
- for (i = 0; i < ARRAY_SIZE(reg_set); i++)
- snd_soc_update_bits(codec, reg_set[i].reg, reg_set[i].mask,
- reg_set[i].val);
+ if (state == WCD9XXX_CLSH_STATE_IDLE) {
+ snprintf(buf, buflen, "[STATE_IDLE]");
+ goto done;
+ }
- dev_dbg(codec->dev, "%s: Programmed buck parameters", __func__);
+ buf[0] = '\0';
+ for (i = 0; i < ARRAY_SIZE(states); i++) {
+ if (!(state & (1 << i)))
+ continue;
+ cnt = snprintf(buf, buflen - cnt - 1, "%s%s%s", buf,
+ buf[0] == '\0' ? "[" : "|",
+ states[i]);
+ }
+ if (cnt > 0)
+ strlcat(buf + cnt, "]", buflen);
+
+done:
+ if (buf[0] == '\0')
+ snprintf(buf, buflen, "[STATE_UNKNOWN]");
+ return buf;
}
static void wcd9xxx_cfg_clsh_param_common(
@@ -515,26 +510,25 @@
__func__);
}
-static void wcd9xxx_chargepump_request(
- struct snd_soc_codec *codec, bool on)
+static void wcd9xxx_chargepump_request(struct snd_soc_codec *codec, bool on)
{
static int cp_count;
if (on && (++cp_count == 1)) {
snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
- 0x01, 0x01);
+ 0x01, 0x01);
dev_dbg(codec->dev, "%s: Charge Pump enabled, count = %d\n",
- __func__, cp_count);
- }
-
- else if (!on) {
+ __func__, cp_count);
+ } else if (!on) {
if (--cp_count < 0) {
- dev_dbg(codec->dev, "%s: Unbalanced disable for charge pump\n",
+ dev_dbg(codec->dev,
+ "%s: Unbalanced disable for charge pump\n",
+ __func__);
+ if (snd_soc_read(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL) &
+ 0x01) {
+ dev_dbg(codec->dev,
+ "%s: Actual chargepump is ON\n",
__func__);
- if (snd_soc_read(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL)
- & 0x01) {
- dev_dbg(codec->dev, "%s: Actual chargepump is ON\n",
- __func__);
}
cp_count = 0;
WARN_ON(1);
@@ -542,9 +536,10 @@
if (cp_count == 0) {
snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
- 0x01, 0x00);
- dev_dbg(codec->dev, "%s: Charge pump disabled, count = %d\n",
- __func__, cp_count);
+ 0x01, 0x00);
+ dev_dbg(codec->dev,
+ "%s: Charge pump disabled, count = %d\n",
+ __func__, cp_count);
}
}
}
@@ -617,7 +612,6 @@
}
}
-
int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec,
struct list_head *list,
uint16_t reg, uint8_t mask,
@@ -657,18 +651,15 @@
}
EXPORT_SYMBOL(wcd9xxx_restore_registers);
-static void wcd9xxx_enable_buck_mode(struct snd_soc_codec *codec,
- u8 buck_vref)
+static void wcd9xxx_set_buck_mode(struct snd_soc_codec *codec, u8 buck_vref)
{
int i;
const struct wcd9xxx_reg_mask_val reg_set[] = {
- {WCD9XXX_A_BUCK_MODE_5, 0x02, 0x03},
+ {WCD9XXX_A_BUCK_MODE_5, 0x02, 0x02},
{WCD9XXX_A_BUCK_MODE_4, 0xFF, buck_vref},
{WCD9XXX_A_BUCK_MODE_1, 0x04, 0x04},
- {WCD9XXX_A_BUCK_MODE_1, 0x08, 0x00},
{WCD9XXX_A_BUCK_MODE_3, 0x04, 0x00},
{WCD9XXX_A_BUCK_MODE_3, 0x08, 0x00},
- {WCD9XXX_A_BUCK_MODE_1, 0x80, 0x80},
};
for (i = 0; i < ARRAY_SIZE(reg_set); i++)
@@ -704,25 +695,51 @@
}
-static void wcd9xxx_set_fclk_enable_ncp(struct snd_soc_codec *codec,
- u8 fclk_level)
+static void wcd9xxx_set_fclk_get_ncp(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ enum ncp_fclk_level fclk_level)
{
- int i;
- const struct wcd9xxx_reg_mask_val reg_set[] = {
- {WCD9XXX_A_NCP_STATIC, 0x20, 0x20},
- {WCD9XXX_A_NCP_EN, 0x01, 0x01},
- };
- snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
- 0x010, 0x00);
- snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
- 0x0F, fclk_level);
- for (i = 0; i < ARRAY_SIZE(reg_set); i++)
- snd_soc_update_bits(codec, reg_set[i].reg,
- reg_set[i].mask, reg_set[i].val);
+ clsh_d->ncp_users[fclk_level]++;
- usleep_range(NCP_SETTLE_TIME_US, NCP_SETTLE_TIME_US);
+ pr_debug("%s: enter ncp type %d users fclk8 %d, fclk5 %d\n", __func__,
+ fclk_level, clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
+ clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);
- dev_dbg(codec->dev, "%s: set ncp done\n", __func__);
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x10, 0x00);
+ /* fclk level 8 dominates level 5 */
+ if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] > 0)
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x08);
+ else if (clsh_d->ncp_users[NCP_FCLK_LEVEL_5] > 0)
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x05);
+ else
+ WARN_ONCE(1, "Unexpected users %d,%d\n",
+ clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
+ clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x20, 0x20);
+
+ /* enable NCP and wait until settles down */
+ if (snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN, 0x01, 0x01))
+ usleep_range(NCP_SETTLE_TIME_US, NCP_SETTLE_TIME_US);
+ pr_debug("%s: leave\n", __func__);
+}
+
+static void wcd9xxx_set_fclk_put_ncp(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ enum ncp_fclk_level fclk_level)
+{
+ clsh_d->ncp_users[fclk_level]--;
+
+ pr_debug("%s: enter ncp type %d users fclk8 %d, fclk5 %d\n", __func__,
+ fclk_level, clsh_d->ncp_users[NCP_FCLK_LEVEL_8],
+ clsh_d->ncp_users[NCP_FCLK_LEVEL_5]);
+
+ if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0 &&
+ clsh_d->ncp_users[NCP_FCLK_LEVEL_5] == 0)
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN, 0x01, 0x00);
+ else if (clsh_d->ncp_users[NCP_FCLK_LEVEL_8] == 0)
+ /* if dominating level 8 has gone, switch to 5 */
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC, 0x0F, 0x05);
+ pr_debug("%s: leave\n", __func__);
}
static void wcd9xxx_cfg_clsh_param_ear(struct snd_soc_codec *codec)
@@ -790,72 +807,30 @@
__func__);
}
-static void wcd9xxx_clsh_turnoff_postpa
- (struct snd_soc_codec *codec)
-{
-
- int i;
-
- const struct wcd9xxx_reg_mask_val reg_set[] = {
- {WCD9XXX_A_NCP_EN, 0x01, 0x00},
- {WCD9XXX_A_BUCK_MODE_1, 0x80, 0x00},
- {WCD9XXX_A_CDC_CLSH_B1_CTL, 0x10, 0x00},
- };
-
- wcd9xxx_chargepump_request(codec, false);
-
- for (i = 0; i < ARRAY_SIZE(reg_set); i++)
- snd_soc_update_bits(codec, reg_set[i].reg,
- reg_set[i].mask, reg_set[i].val);
-
- wcd9xxx_enable_clsh_block(codec, false);
-
- dev_dbg(codec->dev, "%s: Done\n", __func__);
-}
-
-static void wcd9xxx_clsh_state_idle(struct snd_soc_codec *codec,
- struct wcd9xxx_clsh_cdc_data *clsh_d,
- u8 req_state, bool is_enable)
-{
- if (is_enable) {
- dev_dbg(codec->dev, "%s: wrong transition, cannot enable IDLE state\n",
- __func__);
- } else {
- if (req_state == WCD9XXX_CLSH_STATE_EAR) {
- wcd9xxx_clsh_turnoff_postpa(codec);
- } else if (req_state == WCD9XXX_CLSH_STATE_HPHL) {
- wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L,
- false);
- wcd9xxx_clsh_turnoff_postpa(codec);
- } else if (req_state == WCD9XXX_CLSH_STATE_HPHR) {
- wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R,
- false);
- wcd9xxx_clsh_turnoff_postpa(codec);
- } else if (req_state == WCD9XXX_CLSH_STATE_LO) {
- wcd9xxx_enable_ncp(codec, false);
- wcd9xxx_enable_buck(codec, false);
- }
- }
-}
-
static void wcd9xxx_clsh_state_ear(struct snd_soc_codec *codec,
struct wcd9xxx_clsh_cdc_data *clsh_d,
u8 req_state, bool is_enable)
{
+ pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
if (is_enable) {
- wcd9xxx_cfg_clsh_buck(codec);
wcd9xxx_cfg_clsh_param_common(codec);
wcd9xxx_cfg_clsh_param_ear(codec);
- wcd9xxx_enable_clsh_block(codec, true);
+ wcd9xxx_enable_clsh_block(codec, clsh_d, true);
wcd9xxx_chargepump_request(codec, true);
wcd9xxx_enable_anc_delay(codec, true);
wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, true);
- wcd9xxx_enable_buck_mode(codec, BUCK_VREF_2V);
- wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_8);
+ wcd9xxx_set_buck_mode(codec, BUCK_VREF_2V);
+ wcd9xxx_enable_buck(codec, clsh_d, true);
+ wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
dev_dbg(codec->dev, "%s: Enabled ear mode class h\n", __func__);
} else {
dev_dbg(codec->dev, "%s: stub fallback to ear\n", __func__);
+ wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
+ wcd9xxx_enable_buck(codec, clsh_d, false);
+ wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_EAR, true);
+ wcd9xxx_chargepump_request(codec, false);
+ wcd9xxx_enable_clsh_block(codec, clsh_d, false);
}
}
@@ -863,26 +838,26 @@
struct wcd9xxx_clsh_cdc_data *clsh_d,
u8 req_state, bool is_enable)
{
+ pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
+
if (is_enable) {
- wcd9xxx_cfg_clsh_buck(codec);
wcd9xxx_cfg_clsh_param_common(codec);
wcd9xxx_cfg_clsh_param_hph(codec);
- wcd9xxx_enable_clsh_block(codec, true);
+ wcd9xxx_enable_clsh_block(codec, clsh_d, true);
wcd9xxx_chargepump_request(codec, true);
wcd9xxx_enable_anc_delay(codec, true);
wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L, true);
- wcd9xxx_enable_buck_mode(codec, BUCK_VREF_2V);
- wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_8);
+ wcd9xxx_set_buck_mode(codec, BUCK_VREF_0P494V);
+ wcd9xxx_enable_buck(codec, clsh_d, true);
+ wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
dev_dbg(codec->dev, "%s: Done\n", __func__);
} else {
- if (req_state == WCD9XXX_CLSH_STATE_HPHR) {
- wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R,
- false);
- } else {
- dev_dbg(codec->dev, "%s: stub fallback to hph_l\n",
- __func__);
- }
+ wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
+ wcd9xxx_enable_buck(codec, clsh_d, false);
+ wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L, false);
+ wcd9xxx_chargepump_request(codec, false);
+ wcd9xxx_enable_clsh_block(codec, clsh_d, false);
}
}
@@ -890,27 +865,26 @@
struct wcd9xxx_clsh_cdc_data *clsh_d,
u8 req_state, bool is_enable)
{
- if (is_enable) {
+ pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
- wcd9xxx_cfg_clsh_buck(codec);
+ if (is_enable) {
wcd9xxx_cfg_clsh_param_common(codec);
wcd9xxx_cfg_clsh_param_hph(codec);
- wcd9xxx_enable_clsh_block(codec, true);
+ wcd9xxx_enable_clsh_block(codec, clsh_d, true);
wcd9xxx_chargepump_request(codec, true);
wcd9xxx_enable_anc_delay(codec, true);
wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, true);
- wcd9xxx_enable_buck_mode(codec, BUCK_VREF_2V);
- wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_8);
+ wcd9xxx_set_buck_mode(codec, BUCK_VREF_0P494V);
+ wcd9xxx_enable_buck(codec, clsh_d, true);
+ wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
dev_dbg(codec->dev, "%s: Done\n", __func__);
} else {
- if (req_state == WCD9XXX_CLSH_STATE_HPHL) {
- wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L,
- false);
- } else {
- dev_dbg(codec->dev, "%s: stub fallback to hph_r\n",
- __func__);
- }
+ wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_8);
+ wcd9xxx_enable_buck(codec, clsh_d, false);
+ wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, false);
+ wcd9xxx_chargepump_request(codec, false);
+ wcd9xxx_enable_clsh_block(codec, clsh_d, false);
}
}
@@ -918,9 +892,11 @@
struct wcd9xxx_clsh_cdc_data *clsh_d,
u8 req_state, bool is_enable)
{
+ pr_debug("%s: enter %s\n", __func__, is_enable ? "enable" : "disable");
+
if (is_enable) {
wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_L, true);
- wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, true);
+ wcd9xxx_clsh_comp_req(codec, clsh_d, CLSH_COMPUTE_HPH_R, true);
} else {
dev_dbg(codec->dev, "%s: stub fallback to hph_st\n", __func__);
}
@@ -930,38 +906,36 @@
struct wcd9xxx_clsh_cdc_data *clsh_d,
u8 req_state, bool is_enable)
{
- if (is_enable) {
- if (++cdc_lo_count > 1)
- return;
+ pr_debug("%s: enter %s, buck_mv %d\n", __func__,
+ is_enable ? "enable" : "disable", clsh_d->buck_mv);
- wcd9xxx_enable_buck_mode(codec, BUCK_VREF_1P8V);
- wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_5);
+ if (is_enable) {
+ wcd9xxx_set_buck_mode(codec, BUCK_VREF_1P8V);
+ wcd9xxx_enable_buck(codec, clsh_d, true);
+ wcd9xxx_set_fclk_get_ncp(codec, clsh_d, NCP_FCLK_LEVEL_5);
if (clsh_d->buck_mv == WCD9XXX_CDC_BUCK_MV_1P8) {
- wcd9xxx_enable_buck(codec, false);
+ wcd9xxx_enable_buck(codec, clsh_d, false);
snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
- 0x20, 0x01);
- wcd9xxx_enable_ncp(codec, true);
+ 1 << 4, 1 << 4);
/* NCP settle time recommended by codec specification */
usleep_range(NCP_SETTLE_TIME_US,
- NCP_SETTLE_TIME_US + 10);
-
+ NCP_SETTLE_TIME_US + 10);
} else {
- snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN,
- 0x40, 0x00);
- wcd9xxx_enable_ncp(codec, true);
/* NCP settle time recommended by codec specification */
usleep_range(NCP_SETTLE_TIME_US,
- NCP_SETTLE_TIME_US + 10);
+ NCP_SETTLE_TIME_US + 10);
snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
- 0x01, 0x01);
+ 0x01, (0x01 & 0x03));
snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
- 0xFB, (0x02 << 2));
+ 0xFC, (0xFC & 0xB));
}
- snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
- 0x04, 0x00);
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1, 0x04, 0x00);
} else {
dev_dbg(codec->dev, "%s: stub fallback to lineout\n", __func__);
+ wcd9xxx_set_fclk_put_ncp(codec, clsh_d, NCP_FCLK_LEVEL_5);
+ if (clsh_d->buck_mv != WCD9XXX_CDC_BUCK_MV_1P8)
+ wcd9xxx_enable_buck(codec, clsh_d, false);
}
}
@@ -969,9 +943,12 @@
struct wcd9xxx_clsh_cdc_data *clsh_d,
u8 req_state, bool is_enable)
{
- dev_dbg(codec->dev, "%s Wrong request for class H state machine requested to %s %s"
- , __func__, is_enable ? "enable" : "disable",
- state_to_str(req_state));
+ char msg[128];
+
+ dev_dbg(codec->dev,
+ "%s Wrong request for class H state machine requested to %s %s",
+ __func__, is_enable ? "enable" : "disable",
+ state_to_str(req_state, msg, sizeof(msg)));
WARN_ON(1);
}
@@ -980,51 +957,45 @@
u8 req_state, bool req_type, u8 clsh_event)
{
u8 old_state, new_state;
+ char msg0[128], msg1[128];
switch (clsh_event) {
-
case WCD9XXX_CLSH_EVENT_PRE_DAC:
-
/* PRE_DAC event should be used only for Enable */
BUG_ON(req_type != WCD9XXX_CLSH_REQ_ENABLE);
old_state = cdc_clsh_d->state;
new_state = old_state | req_state;
- (*clsh_state_fp[new_state]) (codec, cdc_clsh_d,
- req_state, req_type);
+ (*clsh_state_fp[req_state]) (codec, cdc_clsh_d, req_state,
+ req_type);
cdc_clsh_d->state = new_state;
dev_dbg(codec->dev, "%s: ClassH state transition from %s to %s\n",
- __func__, state_to_str(old_state),
- state_to_str(cdc_clsh_d->state));
+ __func__, state_to_str(old_state, msg0, sizeof(msg0)),
+ state_to_str(cdc_clsh_d->state, msg1, sizeof(msg1)));
break;
-
case WCD9XXX_CLSH_EVENT_POST_PA:
-
if (req_type == WCD9XXX_CLSH_REQ_DISABLE) {
- if (req_state == WCD9XXX_CLSH_STATE_LO
- && --cdc_lo_count > 0)
- break;
-
old_state = cdc_clsh_d->state;
new_state = old_state & (~req_state);
if (new_state < NUM_CLSH_STATES) {
- (*clsh_state_fp[new_state]) (codec, cdc_clsh_d,
- req_state, req_type);
+ (*clsh_state_fp[req_state]) (codec, cdc_clsh_d,
+ req_state,
+ req_type);
cdc_clsh_d->state = new_state;
dev_dbg(codec->dev, "%s: ClassH state transition from %s to %s\n",
- __func__, state_to_str(old_state),
- state_to_str(cdc_clsh_d->state));
+ __func__, state_to_str(old_state, msg0,
+ sizeof(msg0)),
+ state_to_str(cdc_clsh_d->state, msg1,
+ sizeof(msg1)));
} else {
dev_dbg(codec->dev, "%s: wrong new state = %x\n",
__func__, new_state);
}
-
-
- } else if (req_state != WCD9XXX_CLSH_STATE_LO) {
+ } else if (!(cdc_clsh_d->state & WCD9XXX_CLSH_STATE_LO)) {
wcd9xxx_clsh_enable_post_pa(codec, cdc_clsh_d);
}
@@ -1044,7 +1015,6 @@
for (i = 0; i < NUM_CLSH_STATES; i++)
clsh_state_fp[i] = wcd9xxx_clsh_state_err;
- clsh_state_fp[WCD9XXX_CLSH_STATE_IDLE] = wcd9xxx_clsh_state_idle;
clsh_state_fp[WCD9XXX_CLSH_STATE_EAR] = wcd9xxx_clsh_state_ear;
clsh_state_fp[WCD9XXX_CLSH_STATE_HPHL] =
wcd9xxx_clsh_state_hph_l;
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 0239c86..324f6e9 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -63,11 +63,20 @@
u8 val;
};
+enum ncp_fclk_level {
+ NCP_FCLK_LEVEL_8,
+ NCP_FCLK_LEVEL_5,
+ NCP_FCLK_LEVEL_MAX,
+};
+
/* Class H data that the codec driver will maintain */
struct wcd9xxx_clsh_cdc_data {
u8 state;
int buck_mv;
bool is_dynamic_vdd_cp;
+ int clsh_users;
+ int buck_users;
+ int ncp_users[NCP_FCLK_LEVEL_MAX];
struct wcd9xxx_resmgr *resmgr;
};
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index a632644..bb926ec 100755
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -986,7 +986,7 @@
struct snd_dec_ddp *ddp =
&compr->info.codec_param.codec.options.ddp;
uint32_t params_length = ddp->params_length*sizeof(int);
- if(params_length > MAX_AC3_PARAM_SIZE) {
+ if (params_length > MAX_AC3_PARAM_SIZE) {
/*MAX is 36*sizeof(int) this should not happen*/
pr_err("params_length(%d) is greater than %d",
params_length, MAX_AC3_PARAM_SIZE);
@@ -1023,7 +1023,7 @@
struct snd_dec_ddp *ddp =
&compr->info.codec_param.codec.options.ddp;
uint32_t params_length = ddp->params_length*sizeof(int);
- if(params_length > MAX_AC3_PARAM_SIZE) {
+ if (params_length > MAX_AC3_PARAM_SIZE) {
/*MAX is 36*sizeof(int) this should not happen*/
pr_err("params_length(%d) is greater than %d",
params_length, MAX_AC3_PARAM_SIZE);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index d80ca19..0612805 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -40,8 +40,8 @@
#define MIN_CAPTURE_PERIOD_SIZE (128 * 2 * 4)
#define MAX_CAPTURE_PERIOD_SIZE (128 * 2 * 2 * 6 * 4)
-#define MIN_CAPTURE_NUM_PERIODS (32)
-#define MAX_CAPTURE_NUM_PERIODS (384)
+#define MIN_CAPTURE_NUM_PERIODS (32 * 4)
+#define MAX_CAPTURE_NUM_PERIODS (384 * 4)
static struct snd_pcm_hardware msm_afe_hardware_playback = {
.info = (SNDRV_PCM_INFO_MMAP |