Merge "crypto: msm: check potential integer overflow on AEAD req length"
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/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index e7eae76..714311e 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -86,6 +86,11 @@
for detection of dp line transition during VDD minimization.
- qcom,hsusb-otg-dmsehv-int: If present, indicates mpm interrupt to be configured
for detection of dm line transition during VDD minimization.
+- qcom,ahb-async-bridge-bypass: If present, indicates that enable AHB2AHB By Pass
+ mode with device controller for better throughput. With this mode, USB Core
+ runs using PNOC clock and synchronous to it. Hence it is must to have proper
+ "qcom,msm_bus,vectors" to have high bus frequency. User shouldn't try to
+ enable this feature without proper bus voting.
Example HSUSB OTG controller device node :
usb@f9690000 {
@@ -176,12 +181,19 @@
- qcom,android-usb-cdrom : if this property is present then device creates
a new LUN as CD-ROM
- qcom,android-usb-internal-ums : if this property is present then device
- creates a new LUN as internal usb mass storage
+ creates a new LUN as internal usb mass storage.
+- qcom,streaming-func : add list of usb function name. If mention usb function
+ is being enable as part of USB composition, streaming mode is enable with
+ usb device controller to get better throughput. NOTE: Inverted CRC and
+ turnaround timeout is observed on enabling streaming. Hence it is required
+ to see these errors and number of erros on enabling this at USB level to make
+ final decision to enable this feature or not.
Example Android USB device node :
android_usb@fc42b0c8 {
compatible = "qcom,android-usb";
reg = <0xfc42b0c8 0xc8>;
qcom,android-usb-swfi-latency = <1>;
+ qcom,streaming-func = "rndis","mtp";
};
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..a28bb94 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";
};
};
@@ -283,6 +283,7 @@
qcom,hsusb-otg-otg-control = <2>;
qcom,hsusb-otg-disable-reset;
qcom,dp-manual-pullup;
+ qcom,ahb-async-bridge-bypass;
qcom,msm-bus,name = "usb";
qcom,msm-bus,num-cases = <3>;
@@ -297,6 +298,7 @@
compatible = "qcom,android-usb";
reg = <0xfe8050c8 0xc8>;
qcom,android-usb-swfi-latency = <1>;
+ qcom,streaming-func = "rndis";
};
hsic_host: hsic@f9a00000 {
diff --git a/arch/arm/boot/dts/msm8610-v1-pm.dtsi b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
index 6296692..62aa0f4 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;
};
@@ -125,28 +128,29 @@
qcom,latency-us = <500>;
qcom,ss-power = <410>;
qcom,energy-overhead = <603400>;
- qcom,time-overhead = <1200>;
+ qcom,time-overhead = <1410>;
};
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 = <12700>;
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..e401f7a 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;
};
@@ -134,17 +137,27 @@
reg = <0x2>;
qcom,mode = "pc";
qcom,l2 = "l2_cache_gdhs";
- qcom,latency-us = <10700>;
- qcom,ss-power = <325>;
- qcom,energy-overhead = <441250>;
- qcom,time-overhead = <1020>;
+ qcom,latency-us = <11700>;
+ qcom,ss-power = <372>;
+ qcom,energy-overhead = <738750>;
+ qcom,time-overhead = <1410>;
};
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,latency-us = <12700>;
qcom,ss-power = <315>;
qcom,energy-overhead = <1027150>;
qcom,time-overhead = <2400>;
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..fc9e24a 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -239,6 +239,7 @@
qcom,hsusb-otg-otg-control = <2>;
qcom,hsusb-otg-disable-reset;
qcom,dp-manual-pullup;
+ qcom,ahb-async-bridge-bypass;
qcom,msm-bus,name = "usb2";
qcom,msm-bus,num-cases = <2>;
@@ -253,6 +254,7 @@
compatible = "qcom,android-usb";
reg = <0xfe8050c8 0xc8>;
qcom,android-usb-swfi-latency = <1>;
+ qcom,streaming-func = "rndis";
};
sdcc1: qcom,sdcc@f9824000 {
@@ -422,7 +424,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/kernel/signal.c b/arch/arm/kernel/signal.c
index e000e5e..edb73b4 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -440,12 +440,18 @@
*/
thumb = handler & 1;
+#if __LINUX_ARM_ARCH__ >= 7
+ /*
+ * Clear the If-Then Thumb-2 execution state
+ * ARM spec requires this to be all 000s in ARM mode
+ * Snapdragon S4/Krait misbehaves on a Thumb=>ARM
+ * signal transition without this.
+ */
+ cpsr &= ~PSR_IT_MASK;
+#endif
+
if (thumb) {
cpsr |= PSR_T_BIT;
-#if __LINUX_ARM_ARCH__ >= 7
- /* clear the If-Then Thumb-2 execution state */
- cpsr &= ~PSR_IT_MASK;
-#endif
} else
cpsr &= ~PSR_T_BIT;
}
diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
index 650d592..94b0650 100644
--- a/arch/arm/lib/memset.S
+++ b/arch/arm/lib/memset.S
@@ -14,27 +14,15 @@
.text
.align 5
- .word 0
-
-1: subs r2, r2, #4 @ 1 do we have enough
- blt 5f @ 1 bytes to align with?
- cmp r3, #2 @ 1
- strltb r1, [r0], #1 @ 1
- strleb r1, [r0], #1 @ 1
- strb r1, [r0], #1 @ 1
- add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
-/*
- * The pointer is now aligned and the length is adjusted. Try doing the
- * memset again.
- */
ENTRY(memset)
ands r3, r0, #3 @ 1 unaligned?
- bne 1b @ 1
+ mov ip, r0 @ preserve r0 as return value
+ bne 6f @ 1
/*
- * we know that the pointer in r0 is aligned to a word boundary.
+ * we know that the pointer in ip is aligned to a word boundary.
*/
- orr r1, r1, r1, lsl #8
+1: orr r1, r1, r1, lsl #8
orr r1, r1, r1, lsl #16
mov r3, r1
cmp r2, #16
@@ -43,29 +31,28 @@
#if ! CALGN(1)+0
/*
- * We need an extra register for this loop - save the return address and
- * use the LR
+ * We need 2 extra registers for this loop - use r8 and the LR
*/
- str lr, [sp, #-4]!
- mov ip, r1
+ stmfd sp!, {r8, lr}
+ mov r8, r1
mov lr, r1
2: subs r2, r2, #64
- stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time.
- stmgeia r0!, {r1, r3, ip, lr}
- stmgeia r0!, {r1, r3, ip, lr}
- stmgeia r0!, {r1, r3, ip, lr}
+ stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time.
+ stmgeia ip!, {r1, r3, r8, lr}
+ stmgeia ip!, {r1, r3, r8, lr}
+ stmgeia ip!, {r1, r3, r8, lr}
bgt 2b
- ldmeqfd sp!, {pc} @ Now <64 bytes to go.
+ ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go.
/*
* No need to correct the count; we're only testing bits from now on
*/
tst r2, #32
- stmneia r0!, {r1, r3, ip, lr}
- stmneia r0!, {r1, r3, ip, lr}
+ stmneia ip!, {r1, r3, r8, lr}
+ stmneia ip!, {r1, r3, r8, lr}
tst r2, #16
- stmneia r0!, {r1, r3, ip, lr}
- ldr lr, [sp], #4
+ stmneia ip!, {r1, r3, r8, lr}
+ ldmfd sp!, {r8, lr}
#else
@@ -74,54 +61,63 @@
* whole cache lines at once.
*/
- stmfd sp!, {r4-r7, lr}
+ stmfd sp!, {r4-r8, lr}
mov r4, r1
mov r5, r1
mov r6, r1
mov r7, r1
- mov ip, r1
+ mov r8, r1
mov lr, r1
cmp r2, #96
- tstgt r0, #31
+ tstgt ip, #31
ble 3f
- and ip, r0, #31
- rsb ip, ip, #32
- sub r2, r2, ip
- movs ip, ip, lsl #(32 - 4)
- stmcsia r0!, {r4, r5, r6, r7}
- stmmiia r0!, {r4, r5}
- tst ip, #(1 << 30)
- mov ip, r1
- strne r1, [r0], #4
+ and r8, ip, #31
+ rsb r8, r8, #32
+ sub r2, r2, r8
+ movs r8, r8, lsl #(32 - 4)
+ stmcsia ip!, {r4, r5, r6, r7}
+ stmmiia ip!, {r4, r5}
+ tst r8, #(1 << 30)
+ mov r8, r1
+ strne r1, [ip], #4
3: subs r2, r2, #64
- stmgeia r0!, {r1, r3-r7, ip, lr}
- stmgeia r0!, {r1, r3-r7, ip, lr}
+ stmgeia ip!, {r1, r3-r8, lr}
+ stmgeia ip!, {r1, r3-r8, lr}
bgt 3b
- ldmeqfd sp!, {r4-r7, pc}
+ ldmeqfd sp!, {r4-r8, pc}
tst r2, #32
- stmneia r0!, {r1, r3-r7, ip, lr}
+ stmneia ip!, {r1, r3-r8, lr}
tst r2, #16
- stmneia r0!, {r4-r7}
- ldmfd sp!, {r4-r7, lr}
+ stmneia ip!, {r4-r7}
+ ldmfd sp!, {r4-r8, lr}
#endif
4: tst r2, #8
- stmneia r0!, {r1, r3}
+ stmneia ip!, {r1, r3}
tst r2, #4
- strne r1, [r0], #4
+ strne r1, [ip], #4
/*
* When we get here, we've got less than 4 bytes to zero. We
* may have an unaligned pointer as well.
*/
5: tst r2, #2
- strneb r1, [r0], #1
- strneb r1, [r0], #1
+ strneb r1, [ip], #1
+ strneb r1, [ip], #1
tst r2, #1
- strneb r1, [r0], #1
+ strneb r1, [ip], #1
mov pc, lr
+
+6: subs r2, r2, #4 @ 1 do we have enough
+ blt 5b @ 1 bytes to align with?
+ cmp r3, #2 @ 1
+ strltb r1, [ip], #1 @ 1
+ strleb r1, [ip], #1 @ 1
+ strb r1, [ip], #1 @ 1
+ add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
+ b 1b
ENDPROC(memset)
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 60be20a..5117949 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -95,159 +95,7 @@
},
};
-static struct msm_bus_paths bw_level_tbl_v1[] __initdata = {
- [0] = BW_MBPS(600), /* At least 75 MHz on bus. */
- [1] = BW_MBPS(800), /* At least 100 MHz on bus. */
- [2] = BW_MBPS(1200), /* At least 150 MHz on bus. */
- [3] = BW_MBPS(1600), /* At least 200 MHz on bus. */
- [4] = BW_MBPS(2224), /* At least 278 MHz on bus. */
- [5] = BW_MBPS(3200), /* At least 400 MHz on bus. */
- [6] = BW_MBPS(4448), /* At least 556 MHz on bus. */
- [7] = BW_MBPS(6400), /* At least 800 MHz on bus. */
-};
-
-static struct l2_level l2_freq_tbl_v1[] __initdata = {
- [0] = { { 300000, PLL_0, 0, 0 }, LVL_LOW, 950000, 0 },
- [1] = { { 345600, HFPLL, 2, 36 }, LVL_NOM, 950000, 1 },
- [2] = { { 422400, HFPLL, 2, 44 }, LVL_NOM, 950000, 1 },
- [3] = { { 499200, HFPLL, 2, 52 }, LVL_NOM, 950000, 2 },
- [4] = { { 576000, HFPLL, 1, 30 }, LVL_NOM, 950000, 3 },
- [5] = { { 652800, HFPLL, 1, 34 }, LVL_NOM, 950000, 3 },
- [6] = { { 729600, HFPLL, 1, 38 }, LVL_NOM, 950000, 3 },
- [7] = { { 806400, HFPLL, 1, 42 }, LVL_HIGH, 1050000, 4 },
- [8] = { { 883200, HFPLL, 1, 46 }, LVL_HIGH, 1050000, 4 },
- [9] = { { 960000, HFPLL, 1, 50 }, LVL_HIGH, 1050000, 4 },
- [10] = { { 1036800, HFPLL, 1, 54 }, LVL_HIGH, 1050000, 5 },
- [11] = { { 1113600, HFPLL, 1, 58 }, LVL_HIGH, 1050000, 5 },
- [12] = { { 1190400, HFPLL, 1, 62 }, LVL_HIGH, 1050000, 6 },
- [13] = { { 1267200, HFPLL, 1, 66 }, LVL_HIGH, 1050000, 6 },
- [14] = { { 1344000, HFPLL, 1, 70 }, LVL_HIGH, 1050000, 7 },
- [15] = { { 1420800, HFPLL, 1, 74 }, LVL_HIGH, 1050000, 7 },
- [16] = { { 1497600, HFPLL, 1, 78 }, LVL_HIGH, 1050000, 7 },
- { }
-};
-
-static struct acpu_level acpu_freq_tbl_v1_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 73 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 85 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 104 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 124 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 144 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 165 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 186 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 835000, 208 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 845000, 229 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 860000, 252 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 880000, 275 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 905000, 298 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 920000, 321 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 940000, 346 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 960000, 371 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 980000, 397 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 995000, 423 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1015000, 450 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1030000, 477 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1050000, 506 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_v1_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 73 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 85 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 104 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 124 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 144 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 165 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 186 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 835000, 208 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 845000, 229 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 860000, 252 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 880000, 275 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 905000, 298 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 920000, 321 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 940000, 346 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 960000, 371 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 980000, 397 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 995000, 423 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1015000, 450 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1030000, 477 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1050000, 506 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_v1_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 73 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 85 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 104 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 124 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 144 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 165 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 186 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 825000, 208 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 229 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 835000, 252 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 855000, 275 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 875000, 298 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 895000, 321 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 915000, 346 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 930000, 371 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 945000, 397 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 960000, 423 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 975000, 450 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 990000, 477 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1000000, 506 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_v1_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 73 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 85 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 104 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 124 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 144 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 165 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 186 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 825000, 208 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 229 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 835000, 252 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 855000, 275 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 875000, 298 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 895000, 321 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 915000, 346 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 930000, 371 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 945000, 397 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 960000, 423 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 975000, 450 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 990000, 477 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1000000, 506 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_v1_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 73 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 85 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 104 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 124 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 144 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 165 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 186 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 825000, 208 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 229 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 825000, 252 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 825000, 275 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 835000, 298 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 855000, 321 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 870000, 346 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 885000, 371 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 900000, 397 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 423 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 925000, 450 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 940000, 477 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 950000, 506 },
- { 0, { 0 } }
-};
-
-static struct msm_bus_paths bw_level_tbl_v2[] __initdata = {
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
[0] = BW_MBPS(600), /* At least 75 MHz on bus. */
[1] = BW_MBPS(800), /* At least 100 MHz on bus. */
[2] = BW_MBPS(1200), /* At least 150 MHz on bus. */
@@ -259,7 +107,7 @@
[8] = BW_MBPS(7448), /* At least 931 MHz on bus. */
};
-static struct l2_level l2_freq_tbl_v2[] __initdata = {
+static struct l2_level l2_freq_tbl[] __initdata = {
[0] = { { 300000, PLL_0, 0, 0 }, LVL_LOW, 950000, 0 },
[1] = { { 345600, HFPLL, 2, 36 }, LVL_LOW, 950000, 1 },
[2] = { { 422400, HFPLL, 2, 44 }, LVL_LOW, 950000, 2 },
@@ -2440,15 +2288,6 @@
{ 0, { 0 } }
};
-static struct pvs_table pvs_v1[NUM_PVS_REVS][NUM_SPEED_BINS][NUM_PVS] __initdata = {
- /* 8974v1 1.7GHz Parts */
- [0][0][0] = { acpu_freq_tbl_v1_pvs0, sizeof(acpu_freq_tbl_v1_pvs0) },
- [0][0][1] = { acpu_freq_tbl_v1_pvs1, sizeof(acpu_freq_tbl_v1_pvs1) },
- [0][0][2] = { acpu_freq_tbl_v1_pvs2, sizeof(acpu_freq_tbl_v1_pvs2) },
- [0][0][3] = { acpu_freq_tbl_v1_pvs3, sizeof(acpu_freq_tbl_v1_pvs3) },
- [0][0][4] = { acpu_freq_tbl_v1_pvs4, sizeof(acpu_freq_tbl_v1_pvs4) },
-};
-
static struct pvs_table pvs_v2[NUM_PVS_REVS][NUM_SPEED_BINS][NUM_PVS] __initdata = {
/* 8974v2 2.0GHz Parts */
[0][0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
@@ -2560,8 +2399,8 @@
};
static struct msm_bus_scale_pdata bus_scale_data __initdata = {
- .usecase = bw_level_tbl_v2,
- .num_usecases = ARRAY_SIZE(bw_level_tbl_v2),
+ .usecase = bw_level_tbl,
+ .num_usecases = ARRAY_SIZE(bw_level_tbl),
.active_only = 1,
.name = "acpuclk-8974",
};
@@ -2570,68 +2409,23 @@
.scalable = scalable,
.scalable_size = sizeof(scalable),
.hfpll_data = &hfpll_data,
- .pvs_tables = pvs_v2,
- .l2_freq_tbl = l2_freq_tbl_v2,
- .l2_freq_tbl_size = sizeof(l2_freq_tbl_v2),
+ .l2_freq_tbl = l2_freq_tbl,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.pte_efuse_phys = 0xFC4B80B0,
.get_bin_info = get_krait_bin_format_b,
.stby_khz = 300000,
};
-static void __init apply_pro_bringup_workaround(void)
-{
- acpuclk_8974_params.pvs_tables = pvs_pro;
-}
-
-static void __init apply_v1_l2_workaround(void)
-{
- static struct l2_level resticted_l2_tbl[] __initdata = {
- [0] = { { 300000, PLL_0, 0, 0 }, LVL_LOW, 1050000, 0 },
- [1] = { { 1497600, HFPLL, 1, 78 }, LVL_HIGH, 1050000, 7 },
- { }
- };
- struct acpu_level *l;
- int s, p, r;
-
- for (r = 0; r < NUM_PVS_REVS; r++)
- for (s = 0; s < NUM_SPEED_BINS; s++)
- for (p = 0; p < NUM_PVS; p++) {
- l = pvs_v1[r][s][p].table;
- for (; l && l->speed.khz; l++)
- l->l2_level = l->l2_level > 5 ? 1 : 0;
- }
-
- acpuclk_8974_params.l2_freq_tbl = resticted_l2_tbl;
- acpuclk_8974_params.l2_freq_tbl_size = sizeof(resticted_l2_tbl);
-}
-
#define cpu_is_msm8974pro() (cpu_is_msm8974pro_aa() || cpu_is_msm8974pro_ab() \
|| cpu_is_msm8974pro_ac())
static int __init acpuclk_8974_probe(struct platform_device *pdev)
{
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1
- && cpu_is_msm8974()) {
- acpuclk_8974_params.pvs_tables = pvs_v1;
- acpuclk_8974_params.l2_freq_tbl = l2_freq_tbl_v1;
- bus_scale_data.usecase = bw_level_tbl_v1;
- bus_scale_data.num_usecases = ARRAY_SIZE(bw_level_tbl_v1);
- acpuclk_8974_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_v1);
-
- /*
- * 8974 hardware revisions older than v1.2 may experience L2
- * parity errors when running at some performance points between
- * 300MHz and 1497.6MHz (non-inclusive), or when vdd_mx is less
- * than 1.05V. Restrict L2 operation to safe performance points
- * on these devices.
- */
- if (SOCINFO_VERSION_MINOR(socinfo_get_version()) < 2)
- apply_v1_l2_workaround();
- }
-
if (cpu_is_msm8974pro())
- apply_pro_bringup_workaround();
+ acpuclk_8974_params.pvs_tables = pvs_pro;
+ else
+ acpuclk_8974_params.pvs_tables = pvs_v2;
return acpuclk_krait_init(&pdev->dev, &acpuclk_8974_params);
}
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/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index f8a32b4..2956bd6 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -180,6 +180,7 @@
mov r2, #1
and r1, r2, r1, ASR #30 /* Check if the cache is write back */
orr r1, r0, r1
+ and r1, r1, #1
cmp r1, #1
bne skip
bl v7_flush_dcache_all
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/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index a1463bc..5fa7b1b 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -179,6 +179,16 @@
pr_err("%s[%p]: pause cmd failed rc=%d\n",
__func__, audio, rc);
+ if (rc == 0) {
+ /* Send suspend only if pause was successful */
+ rc = q6asm_cmd(audio->ac, CMD_SUSPEND);
+ if (rc < 0)
+ pr_err("%s[%p]: suspend cmd failed rc=%d\n",
+ __func__, audio, rc);
+ } else
+ pr_err("%s[%p]: not sending suspend since pause failed\n",
+ __func__, audio);
+
} else
pr_err("%s[%p]: Driver not enabled\n", __func__, audio);
return rc;
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index 923e647..faf774f 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -1266,14 +1266,16 @@
{
struct device *dev = &pdev->dev;
struct rpm_regulator *reg;
+ struct rpm_vreg *rpm_vreg;
reg = platform_get_drvdata(pdev);
if (reg) {
- rpm_vreg_lock(reg->rpm_vreg);
+ rpm_vreg = reg->rpm_vreg;
+ rpm_vreg_lock(rpm_vreg);
regulator_unregister(reg->rdev);
list_del(®->list);
kfree(reg);
- rpm_vreg_unlock(reg->rpm_vreg);
+ rpm_vreg_unlock(rpm_vreg);
} else {
dev_err(dev, "%s: drvdata missing\n", __func__);
return -EINVAL;
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/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 19ff6f4..f7c0d24 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1485,26 +1485,25 @@
return err;
}
if (pkt_type == CALLBACK_DATA_TYPE) {
- if (payload_size > itemsize) {
+ if (payload_size > driver->itemsize) {
pr_err("diag: Dropping packet, packet payload size crosses 4KB limit. Current payload size %d\n",
payload_size);
driver->dropped_count++;
return -EBADMSG;
}
- mutex_lock(&driver->diagchar_mutex);
buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
if (!buf_copy) {
driver->dropped_count++;
- mutex_unlock(&driver->diagchar_mutex);
return -ENOMEM;
}
err = copy_from_user(buf_copy, buf + 4, payload_size);
if (err) {
pr_err("diag: copy failed for user space data\n");
- ret = -EIO;
- goto fail_free_copy;
+ diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+ buf_copy = NULL;
+ return -EIO;
}
/* Check for proc_type */
remote_proc = diag_get_remote(*(int *)buf_copy);
@@ -1513,7 +1512,9 @@
wait_event_interruptible(driver->wait_q,
(driver->in_busy_pktdata == 0));
ret = diag_process_apps_pkt(buf_copy, payload_size);
- goto fail_free_copy;
+ diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+ buf_copy = NULL;
+ return ret;
}
/* The packet is for the remote processor */
token_offset = 4;
@@ -1526,7 +1527,7 @@
1 + payload_size);
send.terminate = 1;
-
+ mutex_lock(&driver->diagchar_mutex);
if (!buf_hdlc)
buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
POOL_TYPE_HDLC);
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index b5945da..728e90c 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -772,6 +772,9 @@
#define SP0_ICL1_MISSES 0x1A
#define SP_FS_CFLOW_INSTRUCTIONS 0x0C
+/* COUNTABLE FOR TSE PERFCOUNTER */
+#define TSE_INPUT_PRIM_NUM 0x0
+
/* VBIF PERFCOUNTER ENA/CLR values */
#define VBIF_PERF_CNT_0 BIT(0)
#define VBIF_PERF_CNT_1 BIT(1)
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 8f48440..0ee54d0 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -362,7 +362,7 @@
unsigned int replay_for_snapshot;
};
-#define FT_DETECT_REGS_COUNT 12
+#define FT_DETECT_REGS_COUNT 14
struct log_field {
bool show;
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 5778e9e..f316664 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -3863,7 +3863,9 @@
* USP L1 instruction miss request.
* Set SP to count SP_FS_FULL_ALU_INSTRUCTIONS, it
* counts USP flow control instruction execution.
- * we will use this to augment our hang detection
+ * Set TSE to count TSE_INPUT_PRIM_NUM, it counts
+ * number of input primitives in TSE.
+ * we will use above countables for our hang detection
*/
if (adreno_dev->fast_hang_detect) {
adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
@@ -3878,6 +3880,10 @@
SP_FS_CFLOW_INSTRUCTIONS, &ft_detect_regs[10],
PERFCOUNTER_FLAG_KERNEL);
ft_detect_regs[11] = ft_detect_regs[10] + 1;
+ adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_TSE,
+ TSE_INPUT_PRIM_NUM, &ft_detect_regs[12],
+ PERFCOUNTER_FLAG_KERNEL);
+ ft_detect_regs[13] = ft_detect_regs[12] + 1;
}
adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 6cd1f68..2eb5300 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -59,6 +59,9 @@
struct sg_table *table;
};
+static void kgsl_put_process_private(struct kgsl_device *device,
+ struct kgsl_process_private *private);
+
static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry);
/**
@@ -409,14 +412,19 @@
*/
static int
kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
- struct kgsl_process_private *process)
+ struct kgsl_device_private *dev_priv)
{
int ret;
+ struct kgsl_process_private *process = dev_priv->process_priv;
+
+ ret = kref_get_unless_zero(&process->refcount);
+ if (!ret)
+ return -EBADF;
while (1) {
if (idr_pre_get(&process->mem_idr, GFP_KERNEL) == 0) {
ret = -ENOMEM;
- goto err;
+ goto err_put_proc_priv;
}
spin_lock(&process->mem_lock);
@@ -427,9 +435,10 @@
if (ret == 0)
break;
else if (ret != -EAGAIN)
- goto err;
+ goto err_put_proc_priv;
}
entry->priv = process;
+ entry->dev_priv = dev_priv;
spin_lock(&process->mem_lock);
ret = kgsl_mem_entry_track_gpuaddr(process, entry);
@@ -437,14 +446,17 @@
idr_remove(&process->mem_idr, entry->id);
spin_unlock(&process->mem_lock);
if (ret)
- goto err;
+ goto err_put_proc_priv;
/* map the memory after unlocking if gpuaddr has been assigned */
if (entry->memdesc.gpuaddr) {
ret = kgsl_mmu_map(process->pagetable, &entry->memdesc);
if (ret)
kgsl_mem_entry_detach_process(entry);
}
-err:
+ return ret;
+
+err_put_proc_priv:
+ kgsl_put_process_private(dev_priv->device, process);
return ret;
}
@@ -467,6 +479,7 @@
entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
spin_unlock(&entry->priv->mem_lock);
+ kgsl_put_process_private(entry->dev_priv->device, entry->priv);
entry->priv = NULL;
}
@@ -813,11 +826,6 @@
*/
static void kgsl_destroy_process_private(struct kref *kref)
{
-
- struct kgsl_mem_entry *entry = NULL;
- int next = 0;
-
-
struct kgsl_process_private *private = container_of(kref,
struct kgsl_process_private, refcount);
@@ -841,20 +849,6 @@
if (private->debug_root)
debugfs_remove_recursive(private->debug_root);
- while (1) {
- spin_lock(&private->mem_lock);
- entry = idr_get_next(&private->mem_idr, &next);
- spin_unlock(&private->mem_lock);
- if (entry == NULL)
- break;
- kgsl_mem_entry_put(entry);
- /*
- * Always start back at the beginning, to
- * ensure all entries are removed,
- * like list_for_each_entry_safe.
- */
- next = 0;
- }
idr_destroy(&private->mem_idr);
kgsl_mmu_putpagetable(private->pagetable);
@@ -1004,6 +998,7 @@
struct kgsl_process_private *private = dev_priv->process_priv;
struct kgsl_device *device = dev_priv->device;
struct kgsl_context *context;
+ struct kgsl_mem_entry *entry;
int next = 0;
filep->private_data = NULL;
@@ -1024,6 +1019,25 @@
next = next + 1;
}
+ next = 0;
+ while (1) {
+ spin_lock(&private->mem_lock);
+ entry = idr_get_next(&private->mem_idr, &next);
+ spin_unlock(&private->mem_lock);
+ if (entry == NULL)
+ break;
+ /*
+ * If the free pending flag is not set it means that user space
+ * did not free it's reference to this entry, in that case
+ * free a reference to this entry, other references are from
+ * within kgsl so they will be freed eventually by kgsl
+ */
+ if (entry->dev_priv == dev_priv && !entry->pending_free) {
+ entry->pending_free = 1;
+ kgsl_mem_entry_put(entry);
+ }
+ next = next + 1;
+ }
/*
* Clean up any to-be-freed entries that belong to this
* process and this device. This is done after the context
@@ -2246,7 +2260,7 @@
/* echo back flags */
param->flags = entry->memdesc.flags;
- result = kgsl_mem_entry_attach_process(entry, private);
+ result = kgsl_mem_entry_attach_process(entry, dev_priv);
if (result)
goto error_attach;
@@ -2534,7 +2548,7 @@
if (result)
return result;
- result = kgsl_mem_entry_attach_process(entry, private);
+ result = kgsl_mem_entry_attach_process(entry, dev_priv);
if (result != 0)
goto err;
@@ -2567,7 +2581,7 @@
if (result != 0)
goto err;
- result = kgsl_mem_entry_attach_process(entry, private);
+ result = kgsl_mem_entry_attach_process(entry, dev_priv);
if (result != 0)
goto err;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 42d3b3e..3f4dde7 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -197,6 +197,7 @@
struct kgsl_process_private *priv;
/* Initialized to 0, set to 1 when entry is marked for freeing */
int pending_free;
+ struct kgsl_device_private *dev_priv;
};
#ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index a325d54..91aa928 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -53,6 +53,7 @@
#define MMA8X5X_BUF_SIZE 7
#define MMA_SHUTTEDDOWN (1 << 31)
+#define MMA_STATE_MASK (~MMA_SHUTTEDDOWN)
struct sensor_regulator {
struct regulator *vreg;
@@ -349,7 +350,7 @@
struct input_polled_dev *poll_dev = pdata->poll_dev;
struct mma8x5x_data_axis data;
mutex_lock(&pdata->data_lock);
- if (pdata->active == MMA_STANDBY) {
+ if ((pdata->active & MMA_STATE_MASK) == MMA_STANDBY) {
poll_dev->poll_interval = POLL_STOP_TIME;
/* if standby ,set as 10s to slow the poll. */
goto out;
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index f366364..9a4301e 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -717,7 +717,9 @@
if (r_buf[0] != info.upgrade_id_1
|| r_buf[1] != info.upgrade_id_2) {
- dev_err(&client->dev, "Upgrade ID mismatch(%d)\n", i);
+ dev_err(&client->dev, "Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n",
+ i, r_buf[0], r_buf[1],
+ info.upgrade_id_1, info.upgrade_id_2);
} else
break;
}
@@ -743,6 +745,10 @@
else
is_5336_new_bootloader = FT_BLOADER_VERSION_LZ4;
+ dev_dbg(&client->dev, "bootloader type=%d, r_buf=0x%x, family_id=0x%x\n",
+ is_5336_new_bootloader, r_buf[0], ts_data->family_id);
+ /* is_5336_new_bootloader = FT_BLOADER_VERSION_GZF; */
+
/* erase app and panel paramenter area */
w_buf[0] = FT_ERASE_APP_REG;
ft5x06_i2c_write(client, w_buf, 1);
@@ -1537,7 +1543,7 @@
goto free_reset_gpio;
}
- data->family_id = reg_value;
+ data->family_id = pdata->family_id;
err = request_threaded_irq(client->irq, NULL,
ft5x06_ts_interrupt, pdata->irqflags,
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..8cd3889 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1057,30 +1057,32 @@
dprintk(VIDC_ERR, "cannot write to shared Q's");
goto err_q_null;
}
- mutex_lock(&device->clk_pwr_lock);
- result = venus_hfi_clk_gating_off(device);
- if (result) {
- dprintk(VIDC_ERR, "%s : Clock enable failed\n",
- __func__);
- goto err_q_write;
- }
- result = venus_hfi_scale_clocks(device, device->clk_load);
- if (result) {
- dprintk(VIDC_ERR, "Clock scaling failed\n");
- goto err_q_write;
- }
if (!venus_hfi_write_queue(q_info, (u8 *)pkt, &rx_req_is_set)) {
+ mutex_lock(&device->clk_pwr_lock);
+ result = venus_hfi_clk_gating_off(device);
+ if (result) {
+ dprintk(VIDC_ERR, "%s : Clock enable failed\n",
+ __func__);
+ mutex_unlock(&device->clk_pwr_lock);
+ goto err_q_write;
+ }
+ result = venus_hfi_scale_clocks(device, device->clk_load);
+ if (result) {
+ dprintk(VIDC_ERR, "Clock scaling failed\n");
+ mutex_unlock(&device->clk_pwr_lock);
+ goto err_q_write;
+ }
if (rx_req_is_set)
venus_hfi_write_register(
device,
VIDC_CPU_IC_SOFTINT,
1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
result = 0;
+ mutex_unlock(&device->clk_pwr_lock);
} else {
dprintk(VIDC_ERR, "venus_hfi_iface_cmdq_write:queue_full");
}
err_q_write:
- mutex_unlock(&device->clk_pwr_lock);
err_q_null:
mutex_unlock(&device->write_lock);
return result;
@@ -1104,26 +1106,27 @@
goto read_error_null;
}
q_info = &device->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
- mutex_lock(&device->clk_pwr_lock);
- rc = venus_hfi_clk_gating_off(device);
- if (rc) {
- dprintk(VIDC_ERR,
- "%s : Clock enable failed\n", __func__);
- goto read_error;
- }
if (!venus_hfi_read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
+ mutex_lock(&device->clk_pwr_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
+ mutex_unlock(&device->clk_pwr_lock);
+ goto read_error;
+ }
if (tx_req_is_set)
venus_hfi_write_register(
device,
VIDC_CPU_IC_SOFTINT,
1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
rc = 0;
+ mutex_unlock(&device->clk_pwr_lock);
} else {
dprintk(VIDC_INFO, "venus_hfi_iface_msgq_read:queue_empty");
rc = -ENODATA;
}
read_error:
- mutex_unlock(&device->clk_pwr_lock);
read_error_null:
mutex_unlock(&device->read_lock);
return rc;
@@ -1146,27 +1149,28 @@
rc = -ENODATA;
goto dbg_error_null;
}
- mutex_lock(&device->clk_pwr_lock);
- rc = venus_hfi_clk_gating_off(device);
- if (rc) {
- dprintk(VIDC_ERR,
- "%s : Clock enable failed\n", __func__);
- goto dbg_error;
- }
q_info = &device->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
if (!venus_hfi_read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
+ mutex_lock(&device->clk_pwr_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
+ mutex_unlock(&device->clk_pwr_lock);
+ goto dbg_error;
+ }
if (tx_req_is_set)
venus_hfi_write_register(
device,
VIDC_CPU_IC_SOFTINT,
1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
rc = 0;
+ mutex_unlock(&device->clk_pwr_lock);
} else {
dprintk(VIDC_INFO, "venus_hfi_iface_dbgq_read:queue_empty");
rc = -ENODATA;
}
dbg_error:
- mutex_unlock(&device->clk_pwr_lock);
dbg_error_null:
mutex_unlock(&device->read_lock);
return rc;
@@ -1251,7 +1255,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,
@@ -1567,20 +1571,59 @@
return 0;
}
+static int venus_hfi_is_cmd_pending(struct venus_hfi_device *dev)
+{
+ struct hfi_queue_header *queue;
+ struct vidc_iface_q_info *q_info;
+ u32 write_ptr, read_ptr;
+ u32 rc = 0;
+ q_info = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
+ if (!q_info)
+ dprintk(VIDC_ERR, "cannot read shared Q's");
+ queue = (struct hfi_queue_header *) q_info->q_hdr;
+ if (!queue) {
+ dprintk(VIDC_ERR, "queue not present");
+ return -ENOENT;
+ }
+ write_ptr = (u32)queue->qhdr_write_idx;
+ read_ptr = (u32)queue->qhdr_read_idx;
+ rc = read_ptr - write_ptr;
+ return rc;
+}
+
+static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device)
+{
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return;
+ }
+ if (!device->clocks_enabled) {
+ dprintk(VIDC_DBG, "Clocks are already disabled");
+ goto already_disabled;
+ }
+ venus_hfi_clk_disable(device);
+ if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work,
+ msecs_to_jiffies(msm_vidc_pwr_collapse_delay)))
+ dprintk(VIDC_DBG, "PM work already scheduled\n");
+already_disabled:
+ device->clocks_enabled = 0;
+}
+
static void venus_hfi_core_clear_interrupt(struct venus_hfi_device *device)
{
u32 intr_status = 0;
- int rc = 0;
+ int rc = 0, ctrl_status;
if (!device->callback)
return;
+
+ mutex_lock(&device->write_lock);
mutex_lock(&device->clk_pwr_lock);
rc = venus_hfi_clk_gating_off(device);
if (rc) {
dprintk(VIDC_ERR,
"%s : Clock enable failed\n", __func__);
- mutex_unlock(&device->clk_pwr_lock);
- return;
+ goto err_clk_gating_off;
}
intr_status = venus_hfi_read_register(
device,
@@ -1603,8 +1646,23 @@
VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
venus_hfi_write_register(device,
VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
- mutex_unlock(&device->clk_pwr_lock);
+ rc = venus_hfi_is_cmd_pending(device);
+ ctrl_status = venus_hfi_read_register(
+ device,
+ VIDC_CPU_CS_SCIACMDARG0);
+ dprintk(VIDC_INFO,
+ "CLEAR INTERRUPT - cmd_pending %d, ctrl_status 0x%x\n",
+ rc, ctrl_status);
+ if ((ctrl_status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK)
+ && !rc) {
+ dprintk(VIDC_DBG, "SYS_IDLE interrupt, disable clocks\n");
+ venus_hfi_clk_gating_on(device);
+ }
+
dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
+err_clk_gating_off:
+ mutex_unlock(&device->clk_pwr_lock);
+ mutex_unlock(&device->write_lock);
}
static int venus_hfi_core_set_resource(void *device,
@@ -2321,26 +2379,6 @@
device->callback(SYS_WATCHDOG_TIMEOUT, &cmd_done);
}
-static int venus_hfi_is_cmd_pending(struct venus_hfi_device *dev)
-{
- struct hfi_queue_header *queue;
- struct vidc_iface_q_info *q_info;
- u32 write_ptr, read_ptr;
- u32 rc = 0;
- q_info = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
- if (!q_info)
- dprintk(VIDC_ERR, "cannot read shared Q's");
- queue = (struct hfi_queue_header *) q_info->q_hdr;
- if (!queue) {
- dprintk(VIDC_ERR, "queue not present");
- return -ENOENT;
- }
- write_ptr = (u32)queue->qhdr_write_idx;
- read_ptr = (u32)queue->qhdr_read_idx;
- rc = read_ptr - write_ptr;
- return rc;
-}
-
static int venus_hfi_core_pc_prep(void *device)
{
struct hfi_cmd_sys_pc_prep_packet pkt;
@@ -2408,24 +2446,6 @@
mutex_unlock(&device->clk_pwr_lock);
}
-static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device)
-{
- if (!device) {
- dprintk(VIDC_ERR, "Invalid params: %p\n", device);
- return;
- }
- if (!device->clocks_enabled) {
- dprintk(VIDC_DBG, "Clocks are already disabled");
- goto already_disabled;
- }
- venus_hfi_clk_disable(device);
- if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work,
- msecs_to_jiffies(msm_vidc_pwr_collapse_delay)))
- dprintk(VIDC_DBG, "PM work already scheduled\n");
-already_disabled:
- device->clocks_enabled = 0;
-}
-
static int venus_hfi_try_clk_gating(struct venus_hfi_device *device)
{
int rc = 0;
@@ -2506,10 +2526,12 @@
(struct hfi_msg_sys_debug_packet *) packet;
dprintk(VIDC_FW, "FW-SAYS: %s", pkt->rg_msg_data);
}
- if (rc == HFI_MSG_SYS_IDLE)
+ if (rc == HFI_MSG_SYS_IDLE) {
+ dprintk(VIDC_DBG, "Received HFI_MSG_SYS_IDLE\n");
rc = venus_hfi_try_clk_gating(device);
- else if (rc == HFI_MSG_SYS_PC_PREP_DONE) {
- dprintk(VIDC_DBG, "Received HFI_MSG_SYS_PC_PREP_DONE");
+ } else if (rc == HFI_MSG_SYS_PC_PREP_DONE) {
+ dprintk(VIDC_DBG,
+ "Received HFI_MSG_SYS_PC_PREP_DONE\n");
rc = venus_hfi_try_clk_gating(device);
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/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index a243a05..078929b 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -155,7 +155,6 @@
struct tasklet_struct tlet;
struct msm_hs_sps_ep_conn_data prod;
};
-
enum buffer_states {
NONE_PENDING = 0x0,
FIFO_OVERRUN = 0x1,
@@ -219,6 +218,7 @@
struct msm_bus_scale_pdata *bus_scale_table;
bool rx_discard_flush_issued;
int rx_count_callback;
+ bool rx_bam_inprogress;
unsigned int *reg_ptr;
};
@@ -998,6 +998,14 @@
mutex_lock(&msm_uport->clk_mutex);
msm_hs_write(uport, UART_DM_IMR, 0);
+ /* Clear the Rx Ready Ctl bit - This ensures that
+ * flow control lines stop the other side from sending
+ * data while we change the parameters
+ */
+ data = msm_hs_read(uport, UART_DM_MR1);
+ data &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
+ msm_hs_write(uport, UART_DM_MR1, data);
+
/*
* Disable Rx channel of UARTDM
* DMA Rx Stall happens if enqueue and flush of Rx command happens
@@ -1071,18 +1079,6 @@
/* write parity/bits per char/stop bit configuration */
msm_hs_write(uport, UART_DM_MR2, data);
- /* Configure HW flow control */
- data = msm_hs_read(uport, UART_DM_MR1);
-
- data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
-
- if (c_cflag & CRTSCTS) {
- data |= UARTDM_MR1_CTS_CTL_BMSK;
- data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
- }
-
- msm_hs_write(uport, UART_DM_MR1, data);
-
uport->ignore_status_mask = termios->c_iflag & INPCK;
uport->ignore_status_mask |= termios->c_iflag & IGNPAR;
uport->ignore_status_mask |= termios->c_iflag & IGNBRK;
@@ -1106,6 +1102,10 @@
*/
mb();
if (is_blsp_uart(msm_uport)) {
+ if (msm_uport->rx_bam_inprogress)
+ ret = wait_event_timeout(msm_uport->rx.wait,
+ msm_uport->rx_bam_inprogress == false,
+ RX_FLUSH_COMPLETE_TIMEOUT);
ret = sps_disconnect(sps_pipe_handle);
if (ret)
pr_err("%s(): sps_disconnect failed\n",
@@ -1127,6 +1127,20 @@
}
}
+ /* Configure HW flow control
+ * UART Core would see status of CTS line when it is sending data
+ * to remote uart to confirm that it can receive or not.
+ * UART Core would trigger RFR if it is not having any space with
+ * RX FIFO.
+ */
+ data = msm_hs_read(uport, UART_DM_MR1);
+ data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
+ if (c_cflag & CRTSCTS) {
+ data |= UARTDM_MR1_CTS_CTL_BMSK;
+ data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
+ }
+ msm_hs_write(uport, UART_DM_MR1, data);
+
msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
mb();
mutex_unlock(&msm_uport->clk_mutex);
@@ -1358,10 +1372,13 @@
msm_uport->rx.flush = FLUSH_NONE;
if (is_blsp_uart(msm_uport)) {
+ msm_uport->rx_bam_inprogress = true;
sps_pipe_handle = rx->prod.pipe_handle;
/* Queue transfer request to SPS */
sps_transfer_one(sps_pipe_handle, rx->rbuffer,
UARTDM_RX_BUF_SIZE, msm_uport, flags);
+ msm_uport->rx_bam_inprogress = false;
+ wake_up(&msm_uport->rx.wait);
} else {
msm_dmov_enqueue_cmd(msm_uport->dma_rx_channel,
&msm_uport->rx.xfer);
@@ -1531,10 +1548,13 @@
if (!msm_uport->rx.buffer_pending) {
if (is_blsp_uart(msm_uport)) {
msm_uport->rx.flush = FLUSH_NONE;
+ msm_uport->rx_bam_inprogress = true;
sps_pipe_handle = rx->prod.pipe_handle;
/* Queue transfer request to SPS */
sps_transfer_one(sps_pipe_handle, rx->rbuffer,
UARTDM_RX_BUF_SIZE, msm_uport, sps_flags);
+ msm_uport->rx_bam_inprogress = false;
+ wake_up(&msm_uport->rx.wait);
} else {
msm_hs_start_rx_locked(uport);
}
@@ -2832,9 +2852,9 @@
/* Now save the sps pipe handle */
ep->pipe_handle = sps_pipe_handle;
pr_debug("msm_serial_hs: success !! %s: pipe_handle=0x%x\n"
- "desc_fifo.phys_base=0x%x\n",
+ "desc_fifo.phys_base=0x%llx\n",
is_producer ? "READ" : "WRITE",
- (u32)sps_pipe_handle, sps_config->desc.phys_base);
+ (u32) sps_pipe_handle, (u64) sps_config->desc.phys_base);
return 0;
get_config_err:
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 38c4b86..ad3a3a9 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2623,13 +2623,10 @@
}
}
- /*
- * Notify suspend only to gadget driver, but not resume. Resume is
- * notified as part of wakeup event in dwc3_gadget_wakeup_interrupt().
- */
if (next == DWC3_LINK_STATE_U0) {
if (dwc->link_state == DWC3_LINK_STATE_U3) {
dbg_event(0xFF, "RESUME", 0);
+ dwc->gadget_driver->resume(&dwc->gadget);
}
} else if (next == DWC3_LINK_STATE_U3) {
dbg_event(0xFF, "SUSPEND", 0);
@@ -2920,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/android.c b/drivers/usb/gadget/android.c
index 6765078..c65ed25 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2181,6 +2181,22 @@
}
}
+static inline void check_streaming_func(struct usb_gadget *gadget,
+ struct android_usb_platform_data *pdata,
+ char *name)
+{
+ int i;
+
+ for (i = 0; i < pdata->streaming_func_count; i++) {
+ if (!strcmp(name,
+ pdata->streaming_func[i])) {
+ pr_debug("set streaming_enabled to true\n");
+ gadget->streaming_enabled = true;
+ break;
+ }
+ }
+}
+
static int android_enable_function(struct android_dev *dev,
struct android_configuration *conf,
char *name)
@@ -2188,6 +2204,9 @@
struct android_usb_function **functions = dev->functions;
struct android_usb_function *f;
struct android_usb_function_holder *f_holder;
+ struct android_usb_platform_data *pdata = dev->pdata;
+ struct usb_gadget *gadget = dev->cdev->gadget;
+
while ((f = *functions++)) {
if (!strcmp(name, f->name)) {
if (f->android_dev && f->android_dev != dev)
@@ -2205,6 +2224,13 @@
f_holder->f = f;
list_add_tail(&f_holder->enabled_list,
&conf->enabled_functions);
+ pr_debug("func:%s is enabled.\n", f->name);
+ /*
+ * compare enable function with streaming func
+ * list and based on the same request streaming.
+ */
+ check_streaming_func(gadget, pdata, f->name);
+
return 0;
}
}
@@ -2577,6 +2603,10 @@
{
struct android_dev *dev = cdev_to_android_dev(c->cdev);
+ if (c->cdev->gadget->streaming_enabled) {
+ c->cdev->gadget->streaming_enabled = false;
+ pr_debug("setting streaming_enabled to false.\n");
+ }
android_unbind_enabled_functions(dev, c);
}
@@ -2745,8 +2775,10 @@
unsigned long flags;
spin_lock_irqsave(&cdev->lock, flags);
- dev->suspended = 1;
- schedule_work(&dev->work);
+ if (!dev->suspended) {
+ dev->suspended = 1;
+ schedule_work(&dev->work);
+ }
spin_unlock_irqrestore(&cdev->lock, flags);
composite_suspend(gadget);
@@ -2759,8 +2791,10 @@
unsigned long flags;
spin_lock_irqsave(&cdev->lock, flags);
- dev->suspended = 0;
- schedule_work(&dev->work);
+ if (dev->suspended) {
+ dev->suspended = 0;
+ schedule_work(&dev->work);
+ }
spin_unlock_irqrestore(&cdev->lock, flags);
composite_resume(gadget);
@@ -2895,7 +2929,7 @@
struct android_usb_platform_data *pdata;
struct android_dev *android_dev;
struct resource *res;
- int ret = 0;
+ int ret = 0, i, len = 0;
if (pdev->dev.of_node) {
dev_dbg(&pdev->dev, "device tree enabled\n");
@@ -2912,6 +2946,33 @@
"qcom,android-usb-cdrom");
pdata->internal_ums = of_property_read_bool(pdev->dev.of_node,
"qcom,android-usb-internal-ums");
+ len = of_property_count_strings(pdev->dev.of_node,
+ "qcom,streaming-func");
+ if (len > MAX_STREAMING_FUNCS) {
+ pr_err("Invalid number of functions used.\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < len; i++) {
+ const char *name = NULL;
+
+ of_property_read_string_index(pdev->dev.of_node,
+ "qcom,streaming-func", i, &name);
+ if (!name)
+ continue;
+
+ if (sizeof(name) > FUNC_NAME_LEN) {
+ pr_err("Function name is bigger than allowed.\n");
+ continue;
+ }
+
+ strlcpy(pdata->streaming_func[i], name,
+ sizeof(pdata->streaming_func[i]));
+ pr_debug("name of streaming function:%s\n",
+ pdata->streaming_func[i]);
+ }
+
+ pdata->streaming_func_count = len;
} else {
pdata = pdev->dev.platform_data;
}
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index a9c073b..f1e4220 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -271,6 +271,10 @@
1 << (pdata->log2_itc-1);
is_l1_supported = pdata->l1_supported;
+ /* Set ahb2ahb bypass flag if it is requested. */
+ if (pdata->enable_ahb2ahb_bypass)
+ ci13xxx_msm_udc_driver.flags |=
+ CI13XXX_ENABLE_AHB2AHB_BYPASS;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 3f8d924..6a92684 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -70,10 +70,6 @@
#include <mach/usb_trace.h>
#include "ci13xxx_udc.h"
-/* Turns on streaming. overrides CI13XXX_DISABLE_STREAMING */
-static unsigned int streaming;
-module_param(streaming, uint, S_IRUGO | S_IWUSR);
-
/******************************************************************************
* DEFINE
*****************************************************************************/
@@ -392,20 +388,32 @@
static int hw_device_state(u32 dma)
{
struct ci13xxx *udc = _udc;
+ struct usb_gadget *gadget = &udc->gadget;
if (dma) {
- if (streaming || !(udc->udc_driver->flags &
- CI13XXX_DISABLE_STREAMING))
+ if (gadget->streaming_enabled || !(udc->udc_driver->flags &
+ CI13XXX_DISABLE_STREAMING)) {
hw_cwrite(CAP_USBMODE, USBMODE_SDIS, 0);
- else
+ pr_debug("%s(): streaming mode is enabled. USBMODE:%x\n",
+ __func__, hw_cread(CAP_USBMODE, ~0));
+ } else {
hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
-
+ pr_debug("%s(): streaming mode is disabled. USBMODE:%x\n",
+ __func__, hw_cread(CAP_USBMODE, ~0));
+ }
hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);
if (udc->udc_driver->notify_event)
udc->udc_driver->notify_event(udc,
CI13XXX_CONTROLLER_CONNECT_EVENT);
+ /* Set BIT(31) to enable AHB2AHB Bypass functionality */
+ if (udc->udc_driver->flags & CI13XXX_ENABLE_AHB2AHB_BYPASS) {
+ hw_awrite(ABS_AHBMODE, AHB2AHB_BYPASS, AHB2AHB_BYPASS);
+ pr_debug("%s(): ByPass Mode is enabled. AHBMODE:%x\n",
+ __func__, hw_aread(ABS_AHBMODE, ~0));
+ }
+
/* interrupt, error, port change, reset, sleep/suspend */
hw_cwrite(CAP_USBINTR, ~0,
USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
@@ -413,6 +421,12 @@
} else {
hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
hw_cwrite(CAP_USBINTR, ~0, 0);
+ /* Clear BIT(31) to disable AHB2AHB Bypass functionality */
+ if (udc->udc_driver->flags & CI13XXX_ENABLE_AHB2AHB_BYPASS) {
+ hw_awrite(ABS_AHBMODE, AHB2AHB_BYPASS, 0);
+ pr_debug("%s(): ByPass Mode is disabled. AHBMODE:%x\n",
+ __func__, hw_aread(ABS_AHBMODE, ~0));
+ }
}
return 0;
}
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index f90ea86..47fe138 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -136,6 +136,7 @@
#define CI13XXX_DISABLE_STREAMING BIT(3)
#define CI13XXX_ZERO_ITC BIT(4)
#define CI13XXX_IS_OTG BIT(5)
+#define CI13XXX_ENABLE_AHB2AHB_BYPASS BIT(6)
#define CI13XXX_CONTROLLER_RESET_EVENT 0
#define CI13XXX_CONTROLLER_CONNECT_EVENT 1
@@ -197,6 +198,9 @@
/* TESTMODE */
#define TESTMODE_FORCE BIT(0)
+/* AHB_MODE */
+#define AHB2AHB_BYPASS BIT(31)
+
/* USBCMD */
#define USBCMD_RS BIT(0)
#define USBCMD_RST BIT(1)
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/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 276bbb0..45fbfa8 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -470,6 +470,20 @@
int ret;
struct msm_otg_platform_data *pdata = motg->pdata;
+ /*
+ * AHB2AHB Bypass mode shouldn't be enable before doing
+ * async clock reset. If it is enable, disable the same.
+ */
+ val = readl_relaxed(USB_AHBMODE);
+ if (val & AHB2AHB_BYPASS) {
+ pr_err("%s(): AHB2AHB_BYPASS SET: AHBMODE:%x\n",
+ __func__, val);
+ val &= ~AHB2AHB_BYPASS_BIT_MASK;
+ writel_relaxed(val | AHB2AHB_BYPASS_CLEAR, USB_AHBMODE);
+ pr_err("%s(): AHBMODE: %x\n", __func__,
+ readl_relaxed(USB_AHBMODE));
+ }
+
ret = msm_otg_link_clk_reset(motg, 1);
if (ret)
return ret;
@@ -1275,7 +1289,8 @@
else if (motg->chg_type == USB_CDP_CHARGER)
charger_type = POWER_SUPPLY_TYPE_USB_CDP;
else if (motg->chg_type == USB_DCP_CHARGER ||
- motg->chg_type == USB_PROPRIETARY_CHARGER)
+ motg->chg_type == USB_PROPRIETARY_CHARGER ||
+ motg->chg_type == USB_FLOATED_CHARGER)
charger_type = POWER_SUPPLY_TYPE_USB_DCP;
else if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
motg->chg_type == USB_ACA_A_CHARGER ||
@@ -3834,6 +3849,8 @@
ci_pdata.log2_itc = otg_pdata->log2_itc;
ci_pdata.usb_core_id = 0;
ci_pdata.l1_supported = otg_pdata->l1_supported;
+ ci_pdata.enable_ahb2ahb_bypass =
+ otg_pdata->enable_ahb2ahb_bypass;
retval = platform_device_add_data(pdev, &ci_pdata,
sizeof(ci_pdata));
if (retval)
@@ -4164,6 +4181,8 @@
pdata->l1_supported = of_property_read_bool(node,
"qcom,hsusb-l1-supported");
+ pdata->enable_ahb2ahb_bypass = of_property_read_bool(node,
+ "qcom,ahb-async-bridge-bypass");
return pdata;
}
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.c b/drivers/video/msm/mdss/mdp3.c
index fe8c528..d642093 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -1726,7 +1726,7 @@
rc = (status == 0x080000);
}
- mdp3_res->splash_mem_addr = MDP3_REG_READ(MDP3_REG_DMA_S_IBUF_ADDR);
+ mdp3_res->splash_mem_addr = MDP3_REG_READ(MDP3_REG_DMA_P_IBUF_ADDR);
mdp3_clk_update(MDP3_CLK_AHB, 0);
mdp3_clk_update(MDP3_CLK_CORE, 0);
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..81473db 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -98,8 +98,10 @@
void mdss_fb_no_update_notify_timer_cb(unsigned long data)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
- if (!mfd)
+ if (!mfd) {
pr_err("%s mfd NULL\n", __func__);
+ return;
+ }
mfd->no_update.value = NOTIFY_TYPE_NO_UPDATE;
complete(&mfd->no_update.comp);
}
@@ -107,9 +109,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 +125,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 +142,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 +708,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 +1415,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.h b/drivers/video/msm/mdss/mdss_mdp.h
index a9667a4..f36e3c5 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -37,7 +37,6 @@
#define MAX_IMG_HEIGHT 0x3FFF
#define MAX_DST_W MAX_MIXER_WIDTH
#define MAX_DST_H MAX_MIXER_HEIGHT
-#define MAX_PLANES 4
#define MAX_DOWNSCALE_RATIO 4
#define MAX_UPSCALE_RATIO 20
#define MAX_DECIMATION 4
@@ -52,6 +51,11 @@
/* wait for at most 2 vsync for lowest refresh rate (24hz) */
#define KOFF_TIMEOUT msecs_to_jiffies(84)
+#define OVERFETCH_DISABLE_TOP BIT(0)
+#define OVERFETCH_DISABLE_BOTTOM BIT(1)
+#define OVERFETCH_DISABLE_LEFT BIT(2)
+#define OVERFETCH_DISABLE_RIGHT BIT(3)
+
#ifdef MDSS_MDP_DEBUG_REG
static inline void mdss_mdp_reg_write(u32 addr, u32 val)
{
@@ -341,9 +345,6 @@
u8 vert_deci;
struct mdss_mdp_img_rect src;
struct mdss_mdp_img_rect dst;
- u32 phase_step_x;
- u32 phase_step_y;
-
struct mdss_mdp_format_params *src_fmt;
struct mdss_mdp_plane_sizes src_planes;
@@ -370,6 +371,9 @@
struct mdp_overlay_pp_params pp_cfg;
struct mdss_pipe_pp_res pp_res;
+ struct mdp_scale_data scale;
+ u8 chroma_sample_h;
+ u8 chroma_sample_v;
};
struct mdss_mdp_writeback_arg {
@@ -629,6 +633,7 @@
int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd,
struct mdp_mixer_cfg *mixer_cfg);
+int mdss_mdp_pipe_program_pixel_extn(struct mdss_mdp_pipe *pipe);
#define mfd_to_mdp5_data(mfd) (mfd->mdp.private1)
#define mfd_to_mdata(mfd) (((struct mdss_overlay_private *)\
(mfd->mdp.private1))->mdata)
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index c8af903..52ca42c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -201,6 +201,9 @@
#define MDSS_MDP_REG_SSPP_CURRENT_SRC2_ADDR 0x0AC
#define MDSS_MDP_REG_SSPP_CURRENT_SRC3_ADDR 0x0B0
#define MDSS_MDP_REG_SSPP_DECIMATION_CONFIG 0x0B4
+#define MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_LR 0x100
+#define MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_TB 0x104
+#define MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_REQ_PIXELS 0x108
#define MDSS_MDP_REG_VIG_OP_MODE 0x200
#define MDSS_MDP_REG_VIG_QSEED2_CONFIG 0x204
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..121b9e5 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -282,7 +282,12 @@
int rc;
src = pipe->src.w >> pipe->horz_deci;
- rc = mdss_mdp_calc_phase_step(src, pipe->dst.w, &pipe->phase_step_x);
+
+ if (pipe->scale.enable_pxl_ext)
+ return 0;
+ memset(&pipe->scale, 0, sizeof(struct mdp_scale_data));
+ rc = mdss_mdp_calc_phase_step(src, pipe->dst.w,
+ &pipe->scale.phase_step_x[0]);
if (rc) {
pr_err("Horizontal scaling calculation failed=%d! %d->%d\n",
rc, src, pipe->dst.w);
@@ -290,16 +295,43 @@
}
src = pipe->src.h >> pipe->vert_deci;
- rc = mdss_mdp_calc_phase_step(src, pipe->dst.h, &pipe->phase_step_y);
+ rc = mdss_mdp_calc_phase_step(src, pipe->dst.h,
+ &pipe->scale.phase_step_y[0]);
if (rc) {
pr_err("Vertical scaling calculation failed=%d! %d->%d\n",
rc, src, pipe->dst.h);
return rc;
}
-
+ pipe->scale.init_phase_x[0] = (pipe->scale.phase_step_x[0] -
+ (1 << PHASE_STEP_SHIFT)) / 2;
+ pipe->scale.init_phase_y[0] = (pipe->scale.phase_step_y[0] -
+ (1 << PHASE_STEP_SHIFT)) / 2;
return 0;
}
+static inline void __mdss_mdp_overlay_set_chroma_sample(
+ struct mdss_mdp_pipe *pipe)
+{
+ pipe->chroma_sample_v = pipe->chroma_sample_h = 0;
+
+ switch (pipe->src_fmt->chroma_sample) {
+ case MDSS_MDP_CHROMA_H1V2:
+ pipe->chroma_sample_v = 1;
+ break;
+ case MDSS_MDP_CHROMA_H2V1:
+ pipe->chroma_sample_h = 1;
+ break;
+ case MDSS_MDP_CHROMA_420:
+ pipe->chroma_sample_v = 1;
+ pipe->chroma_sample_h = 1;
+ break;
+ }
+ if (pipe->horz_deci)
+ pipe->chroma_sample_h = 0;
+ if (pipe->vert_deci)
+ pipe->chroma_sample_v = 0;
+}
+
static int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
struct mdp_overlay *req,
struct mdss_mdp_pipe **ppipe)
@@ -442,7 +474,10 @@
pipe->dst.h = req->dst_rect.h;
pipe->horz_deci = req->horz_deci;
pipe->vert_deci = req->vert_deci;
+
+ memcpy(&pipe->scale, &req->scale, sizeof(struct mdp_scale_data));
pipe->src_fmt = fmt;
+ __mdss_mdp_overlay_set_chroma_sample(pipe);
pipe->mixer_stage = req->z_order;
pipe->is_fg = req->is_fg;
@@ -458,8 +493,17 @@
pr_debug("Unintended blend_op %d on layer with no alpha plane\n",
pipe->blend_op);
- pipe->overfetch_disable = fmt->is_yuv &&
- !(pipe->flags & MDP_SOURCE_ROTATED_90);
+ if (fmt->is_yuv && !(pipe->flags & MDP_SOURCE_ROTATED_90) &&
+ !pipe->scale.enable_pxl_ext) {
+ pipe->overfetch_disable = OVERFETCH_DISABLE_BOTTOM;
+
+ if (!(pipe->flags & MDSS_MDP_DUAL_PIPE) ||
+ (pipe->flags & MDSS_MDP_RIGHT_MIXER))
+ pipe->overfetch_disable |= OVERFETCH_DISABLE_RIGHT;
+ pr_debug("overfetch flags=%x\n", pipe->overfetch_disable);
+ } else {
+ pipe->overfetch_disable = 0;
+ }
req->id = pipe->ndx;
pipe->req_data = *req;
@@ -516,7 +560,7 @@
}
}
- if (pipe->flags & MDP_DEINTERLACE) {
+ if ((pipe->flags & MDP_DEINTERLACE) && !pipe->scale.enable_pxl_ext) {
if (pipe->flags & MDP_SOURCE_ROTATED_90) {
pipe->src.w /= 2;
pipe->img_width /= 2;
@@ -539,6 +583,12 @@
!mdp5_data->mdata->has_wfd_blk)
mdss_mdp_smp_release(pipe);
+ /*
+ * Clear previous SMP reservations and reserve according to the
+ * latest configuration
+ */
+ mdss_mdp_smp_unreserve(pipe);
+
ret = mdss_mdp_smp_reserve(pipe);
if (ret) {
pr_debug("mdss_mdp_smp_reserve failed. ret=%d\n", ret);
@@ -1475,15 +1525,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;
@@ -2105,7 +2166,7 @@
u32 cmd, void __user *argp)
{
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
- struct mdp_overlay req;
+ struct mdp_overlay *req = NULL;
int val, ret = -ENOSYS;
struct msmfb_metadata metadata;
@@ -2121,12 +2182,15 @@
break;
case MSMFB_OVERLAY_GET:
- ret = copy_from_user(&req, argp, sizeof(req));
+ req = kmalloc(sizeof(struct mdp_overlay), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+ ret = copy_from_user(req, argp, sizeof(*req));
if (!ret) {
- ret = mdss_mdp_overlay_get(mfd, &req);
+ ret = mdss_mdp_overlay_get(mfd, req);
if (!IS_ERR_VALUE(ret))
- ret = copy_to_user(argp, &req, sizeof(req));
+ ret = copy_to_user(argp, req, sizeof(*req));
}
if (ret)
@@ -2134,12 +2198,15 @@
break;
case MSMFB_OVERLAY_SET:
- ret = copy_from_user(&req, argp, sizeof(req));
+ req = kmalloc(sizeof(struct mdp_overlay), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+ ret = copy_from_user(req, argp, sizeof(*req));
if (!ret) {
- ret = mdss_mdp_overlay_set(mfd, &req);
+ ret = mdss_mdp_overlay_set(mfd, req);
if (!IS_ERR_VALUE(ret))
- ret = copy_to_user(argp, &req, sizeof(req));
+ ret = copy_to_user(argp, req, sizeof(*req));
}
if (ret)
pr_debug("OVERLAY_SET failed (%d)\n", ret);
@@ -2224,6 +2291,7 @@
break;
}
+ kfree(req);
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 779f74c..25cb9dd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -581,6 +581,8 @@
mdss_mdp_smp_free(pipe);
pipe->flags = 0;
pipe->bwc_mode = 0;
+ memset(&pipe->scale, 0, sizeof(struct mdp_scale_data));
+
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
return 0;
@@ -728,24 +730,43 @@
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;
dst_size = (dst.h << 16) | dst.w;
dst_xy = (dst.y << 16) | dst.x;
- img_size = (height << 16) | width;
-
ystride0 = (pipe->src_planes.ystride[0]) |
(pipe->src_planes.ystride[1] << 16);
ystride1 = (pipe->src_planes.ystride[2]) |
(pipe->src_planes.ystride[3] << 16);
- if (pipe->overfetch_disable) {
- img_size = src_size;
- src_xy = 0;
+ /*
+ * Software overfetch is used when scalar pixel extension is
+ * not enabled
+ */
+ if (pipe->overfetch_disable && !pipe->scale.enable_pxl_ext) {
+ if (pipe->overfetch_disable & OVERFETCH_DISABLE_BOTTOM) {
+ height = pipe->src.h;
+ if (!(pipe->overfetch_disable & OVERFETCH_DISABLE_TOP))
+ height += pipe->src.y;
+ }
+ if (pipe->overfetch_disable & OVERFETCH_DISABLE_RIGHT) {
+ width = pipe->src.w;
+ if (!(pipe->overfetch_disable & OVERFETCH_DISABLE_LEFT))
+ width += pipe->src.x;
+ }
+ if (pipe->overfetch_disable & OVERFETCH_DISABLE_LEFT)
+ src_xy &= ~0xFFFF;
+ if (pipe->overfetch_disable & OVERFETCH_DISABLE_TOP)
+ src_xy &= ~(0xFFFF << 16);
+
+ pr_debug("overfetch w=%d/%d h=%d/%d src_xy=0x%08x\n", width,
+ pipe->img_width, height, pipe->img_height, src_xy);
}
+ img_size = (height << 16) | width;
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_IMG_SIZE, img_size);
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_SIZE, src_size);
@@ -812,6 +833,9 @@
mdss_mdp_pipe_sspp_setup(pipe, &opmode);
+ if (pipe->scale.enable_pxl_ext)
+ opmode |= (1 << 31);
+
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT, src_format);
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN, unpack);
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_OP_MODE, opmode);
@@ -843,33 +867,42 @@
}
static int mdss_mdp_src_addr_setup(struct mdss_mdp_pipe *pipe,
- struct mdss_mdp_data *data)
+ struct mdss_mdp_data *src_data)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ struct mdss_mdp_data data = *src_data;
int ret = 0;
pr_debug("pnum=%d\n", pipe->num);
- data->bwc_enabled = pipe->bwc_mode;
+ data.bwc_enabled = pipe->bwc_mode;
- ret = mdss_mdp_data_check(data, &pipe->src_planes);
+ ret = mdss_mdp_data_check(&data, &pipe->src_planes);
if (ret)
return ret;
- if (pipe->overfetch_disable)
- mdss_mdp_data_calc_offset(data, pipe->src.x, pipe->src.y,
+ if (pipe->overfetch_disable && !pipe->scale.enable_pxl_ext) {
+ u32 x = 0, y = 0;
+
+ if (pipe->overfetch_disable & OVERFETCH_DISABLE_LEFT)
+ x = pipe->src.x;
+ if (pipe->overfetch_disable & OVERFETCH_DISABLE_TOP)
+ y = pipe->src.y;
+
+ mdss_mdp_data_calc_offset(&data, x, y,
&pipe->src_planes, pipe->src_fmt);
+ }
/* planar format expects YCbCr, swap chroma planes if YCrCb */
if (mdata->mdp_rev < MDSS_MDP_HW_REV_102 &&
(pipe->src_fmt->fetch_planes == MDSS_MDP_PLANE_PLANAR)
&& (pipe->src_fmt->element[0] == C1_B_Cb))
- swap(data->p[1].addr, data->p[2].addr);
+ swap(data.p[1].addr, data.p[2].addr);
- mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC0_ADDR, data->p[0].addr);
- mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC1_ADDR, data->p[1].addr);
- mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC2_ADDR, data->p[2].addr);
- mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC3_ADDR, data->p[3].addr);
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC0_ADDR, data.p[0].addr);
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC1_ADDR, data.p[1].addr);
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC2_ADDR, data.p[2].addr);
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC3_ADDR, data.p[3].addr);
return 0;
}
@@ -900,8 +933,9 @@
struct mdss_mdp_data *src_data)
{
int ret = 0;
- u32 params_changed, opmode;
struct mdss_mdp_ctl *ctl;
+ u32 params_changed;
+ u32 opmode = 0;
if (!pipe) {
pr_err("pipe not setup properly for queue\n");
@@ -982,3 +1016,53 @@
{
return (pipe == pipe->mixer->stage_pipe[pipe->mixer_stage]);
}
+
+static inline void __mdss_mdp_pipe_program_pixel_extn_helper(
+ struct mdss_mdp_pipe *pipe, u32 plane, u32 off)
+{
+ u32 src_h = pipe->src.h >> pipe->vert_deci;
+ u32 mask = 0xFF;
+
+ /*
+ * CB CR plane required pxls need to be accounted
+ * for chroma decimation.
+ */
+ if (plane == 1)
+ src_h >>= pipe->chroma_sample_v;
+ writel_relaxed(((pipe->scale.right_ftch[plane] & mask) << 24)|
+ ((pipe->scale.right_rpt[plane] & mask) << 16)|
+ ((pipe->scale.left_ftch[plane] & mask) << 8)|
+ (pipe->scale.left_rpt[plane] & mask), pipe->base +
+ MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_LR + off);
+ writel_relaxed(((pipe->scale.btm_ftch[plane] & mask) << 24)|
+ ((pipe->scale.btm_rpt[plane] & mask) << 16)|
+ ((pipe->scale.top_ftch[plane] & mask) << 8)|
+ (pipe->scale.top_rpt[plane] & mask), pipe->base +
+ MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_TB + off);
+ mask = 0xFFFF;
+ writel_relaxed((((src_h + pipe->scale.num_ext_pxls_top[plane] +
+ pipe->scale.num_ext_pxls_btm[plane]) & mask) << 16) |
+ ((pipe->scale.roi_w[plane] +
+ pipe->scale.num_ext_pxls_left[plane] +
+ pipe->scale.num_ext_pxls_right[plane]) & mask), pipe->base +
+ MDSS_MDP_REG_SSPP_SW_PIX_EXT_C0_REQ_PIXELS + off);
+}
+
+/**
+ * mdss_mdp_pipe_program_pixel_extn - Program the source pipe's
+ * sw pixel extension
+ * @pipe: Source pipe struct containing pixel extn values
+ *
+ * Function programs the pixel extn values calculated during
+ * scale setup.
+ */
+int mdss_mdp_pipe_program_pixel_extn(struct mdss_mdp_pipe *pipe)
+{
+ /* Y plane pixel extn */
+ __mdss_mdp_pipe_program_pixel_extn_helper(pipe, 0, 0);
+ /* CB CR plane pixel extn */
+ __mdss_mdp_pipe_program_pixel_extn_helper(pipe, 1, 16);
+ /* Alpha plane pixel extn */
+ __mdss_mdp_pipe_program_pixel_extn_helper(pipe, 3, 32);
+ return 0;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index b31f6c1..dc7b8b3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -629,7 +629,7 @@
}
}
- *op = opmode;
+ *op |= opmode;
return 0;
}
@@ -637,12 +637,15 @@
static int mdss_mdp_scale_setup(struct mdss_mdp_pipe *pipe)
{
u32 scale_config = 0;
- u32 phasex_step = 0, phasey_step = 0;
+ int init_phasex = 0, init_phasey = 0;
+ int phasex_step = 0, phasey_step = 0;
u32 chroma_sample;
u32 filter_mode;
struct mdss_data_type *mdata;
u32 src_w, src_h;
+ pr_debug("pipe=%d, change pxl ext=%d\n", pipe->num,
+ pipe->scale.enable_pxl_ext);
mdata = mdss_mdp_get_mdata();
if (mdata->mdp_rev >= MDSS_MDP_HW_REV_102 && pipe->src_fmt->is_yuv)
filter_mode = MDSS_MDP_SCALE_FILTER_CA;
@@ -689,7 +692,8 @@
if ((src_h != pipe->dst.h) ||
(pipe->pp_res.pp_sts.sharp_sts & PP_STS_ENABLE) ||
(chroma_sample == MDSS_MDP_CHROMA_420) ||
- (chroma_sample == MDSS_MDP_CHROMA_H1V2)) {
+ (chroma_sample == MDSS_MDP_CHROMA_H1V2) ||
+ pipe->scale.enable_pxl_ext) {
pr_debug("scale y - src_h=%d dst_h=%d\n", src_h, pipe->dst.h);
if ((src_h / MAX_DOWNSCALE_RATIO) > pipe->dst.h) {
@@ -699,7 +703,8 @@
}
scale_config |= MDSS_MDP_SCALEY_EN;
- phasey_step = pipe->phase_step_y;
+ phasey_step = pipe->scale.phase_step_y[0];
+ init_phasey = pipe->scale.init_phase_y[0];
if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG) {
u32 chroma_shift = 0;
@@ -708,11 +713,11 @@
(chroma_sample == MDSS_MDP_CHROMA_H1V2)))
chroma_shift = 1; /* 2x upsample chroma */
- if (src_h <= pipe->dst.h) {
+ if (src_h <= pipe->dst.h)
scale_config |= /* G/Y, A */
(filter_mode << 10) |
(MDSS_MDP_SCALE_FILTER_BIL << 18);
- } else
+ else
scale_config |= /* G/Y, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 10) |
(MDSS_MDP_SCALE_FILTER_PCMN << 18);
@@ -724,6 +729,8 @@
scale_config |= /* CrCb */
(MDSS_MDP_SCALE_FILTER_PCMN << 14);
+ writel_relaxed(init_phasey, pipe->base +
+ MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEY);
writel_relaxed(phasey_step >> chroma_shift, pipe->base +
MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPY);
} else {
@@ -741,7 +748,8 @@
if ((src_w != pipe->dst.w) ||
(pipe->pp_res.pp_sts.sharp_sts & PP_STS_ENABLE) ||
(chroma_sample == MDSS_MDP_CHROMA_420) ||
- (chroma_sample == MDSS_MDP_CHROMA_H2V1)) {
+ (chroma_sample == MDSS_MDP_CHROMA_H2V1) ||
+ pipe->scale.enable_pxl_ext) {
pr_debug("scale x - src_w=%d dst_w=%d\n", src_w, pipe->dst.w);
if ((src_w / MAX_DOWNSCALE_RATIO) > pipe->dst.w) {
@@ -751,7 +759,8 @@
}
scale_config |= MDSS_MDP_SCALEX_EN;
- phasex_step = pipe->phase_step_x;
+ init_phasex = pipe->scale.init_phase_x[0];
+ phasex_step = pipe->scale.phase_step_x[0];
if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG) {
u32 chroma_shift = 0;
@@ -761,11 +770,11 @@
(chroma_sample == MDSS_MDP_CHROMA_H2V1)))
chroma_shift = 1; /* 2x upsample chroma */
- if (src_w <= pipe->dst.w) {
+ if (src_w <= pipe->dst.w)
scale_config |= /* G/Y, A */
(filter_mode << 8) |
(MDSS_MDP_SCALE_FILTER_BIL << 16);
- } else
+ else
scale_config |= /* G/Y, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 8) |
(MDSS_MDP_SCALE_FILTER_PCMN << 16);
@@ -777,6 +786,8 @@
scale_config |= /* CrCb */
(MDSS_MDP_SCALE_FILTER_PCMN << 12);
+ writel_relaxed(init_phasex, pipe->base +
+ MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEX);
writel_relaxed(phasex_step >> chroma_shift, pipe->base +
MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPX);
} else {
@@ -791,12 +802,44 @@
}
}
+ if (pipe->scale.enable_pxl_ext &&
+ pipe->type == MDSS_MDP_PIPE_TYPE_VIG) {
+
+ /*program x,y initial phase and phase step*/
+ writel_relaxed(pipe->scale.init_phase_x[0],
+ pipe->base + MDSS_MDP_REG_VIG_QSEED2_C03_INIT_PHASEX);
+ writel_relaxed(pipe->scale.phase_step_x[0],
+ pipe->base + MDSS_MDP_REG_VIG_QSEED2_C03_PHASESTEPX);
+ writel_relaxed(pipe->scale.init_phase_x[1],
+ pipe->base + MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEX);
+ writel_relaxed(pipe->scale.phase_step_x[1],
+ pipe->base + MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPX);
+
+ writel_relaxed(pipe->scale.init_phase_y[0],
+ pipe->base + MDSS_MDP_REG_VIG_QSEED2_C03_INIT_PHASEY);
+ writel_relaxed(pipe->scale.phase_step_y[0],
+ pipe->base + MDSS_MDP_REG_VIG_QSEED2_C03_PHASESTEPY);
+ writel_relaxed(pipe->scale.init_phase_y[1],
+ pipe->base + MDSS_MDP_REG_VIG_QSEED2_C12_INIT_PHASEY);
+ writel_relaxed(pipe->scale.phase_step_y[1],
+ pipe->base + MDSS_MDP_REG_VIG_QSEED2_C12_PHASESTEPY);
+
+ /*program pixel extn values for the SSPP*/
+ mdss_mdp_pipe_program_pixel_extn(pipe);
+ } else {
+ writel_relaxed(phasex_step, pipe->base +
+ MDSS_MDP_REG_SCALE_PHASE_STEP_X);
+ writel_relaxed(phasey_step, pipe->base +
+ MDSS_MDP_REG_SCALE_PHASE_STEP_Y);
+ writel_relaxed(init_phasex, pipe->base +
+ MDSS_MDP_REG_SCALE_INIT_PHASE_X);
+ writel_relaxed(init_phasey, pipe->base +
+ MDSS_MDP_REG_SCALE_INIT_PHASE_Y);
+ }
+
writel_relaxed(scale_config, pipe->base +
MDSS_MDP_REG_SCALE_CONFIG);
- writel_relaxed(phasex_step, pipe->base +
- MDSS_MDP_REG_SCALE_PHASE_STEP_X);
- writel_relaxed(phasey_step, pipe->base +
- MDSS_MDP_REG_SCALE_PHASE_STEP_Y);
+
return 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 1170d1e..b680823 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -592,7 +592,7 @@
return -EINVAL;
unit = 1 << PHASE_STEP_SHIFT;
- *out_phase = mult_frac(src, unit, dst);
+ *out_phase = mult_frac(unit, src, dst);
/* check if overflow is possible */
if (src > dst) {
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/include/linux/kref.h b/include/linux/kref.h
index 9c07dce..aa5acc26 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -93,4 +93,26 @@
{
return kref_sub(kref, 1, release);
}
+
+
+/**
+ * kref_get_unless_zero - Increment refcount for object unless it is zero.
+ * @kref: object.
+ *
+ * Return non-zero if the increment succeeded. Otherwise return 0.
+ *
+ * This function is intended to simplify locking around refcounting for
+ * objects that can be looked up from a lookup structure, and which are
+ * removed from that lookup structure in the object destructor.
+ * Operations on such objects require at least a read lock around
+ * lookup + kref_get, and a write lock around kref_put + remove from lookup
+ * structure. Furthermore, RCU implementations become extremely tricky.
+ * With a lookup followed by a kref_get_unless_zero *with return value check*
+ * locking in the kref_put path can be deferred to the actual removal from
+ * the lookup structure and RCU lookups become trivial.
+ */
+static inline int __must_check kref_get_unless_zero(struct kref *kref)
+{
+ return atomic_add_unless(&kref->refcount, 1, 0);
+}
#endif /* _KREF_H_ */
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index 227fd3e..9a584c0 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -2,6 +2,7 @@
#define LINUX_MM_INLINE_H
#include <linux/huge_mm.h>
+#include <linux/swap.h>
/**
* page_is_file_cache - should the page be on a file LRU or anon LRU?
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 7539e03..381fff5 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -375,7 +375,6 @@
* free areas of different sizes
*/
spinlock_t lock;
- int all_unreclaimable; /* All pages pinned */
#if defined CONFIG_COMPACTION || defined CONFIG_CMA
/* Set to true when the PG_migrate_skip bits should be cleared */
bool compact_blockskip_flush;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 0c08421..e6b7f69 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -156,6 +156,7 @@
#define MDSS_MDP_ROT_ONLY 0x80
#define MDSS_MDP_RIGHT_MIXER 0x100
+#define MDSS_MDP_DUAL_PIPE 0x200
/* mdp_blit_req flag values */
#define MDP_ROT_NOP 0
@@ -442,6 +443,33 @@
BLEND_OP_MAX,
};
+#define MAX_PLANES 4
+struct mdp_scale_data {
+ uint8_t enable_pxl_ext;
+
+ int init_phase_x[MAX_PLANES];
+ int phase_step_x[MAX_PLANES];
+ int init_phase_y[MAX_PLANES];
+ int phase_step_y[MAX_PLANES];
+
+ int num_ext_pxls_left[MAX_PLANES];
+ int num_ext_pxls_right[MAX_PLANES];
+ int num_ext_pxls_top[MAX_PLANES];
+ int num_ext_pxls_btm[MAX_PLANES];
+
+ int left_ftch[MAX_PLANES];
+ int left_rpt[MAX_PLANES];
+ int right_ftch[MAX_PLANES];
+ int right_rpt[MAX_PLANES];
+
+ int top_rpt[MAX_PLANES];
+ int btm_rpt[MAX_PLANES];
+ int top_ftch[MAX_PLANES];
+ int btm_ftch[MAX_PLANES];
+
+ uint32_t roi_w[MAX_PLANES];
+};
+
struct mdp_overlay {
struct msmfb_img src;
struct mdp_rect src_rect;
@@ -457,6 +485,7 @@
uint8_t horz_deci;
uint8_t vert_deci;
struct mdp_overlay_pp_params overlay_pp_cfg;
+ struct mdp_scale_data scale;
};
struct msmfb_overlay_3d {
diff --git a/include/linux/usb/android.h b/include/linux/usb/android.h
index e17e978..8d5e51b 100644
--- a/include/linux/usb/android.h
+++ b/include/linux/usb/android.h
@@ -19,12 +19,16 @@
#include <linux/usb/composite.h>
+#define MAX_STREAMING_FUNCS 3
+#define FUNC_NAME_LEN 10
struct android_usb_platform_data {
int (*update_pid_and_serial_num)(uint32_t, const char *);
u32 swfi_latency;
u8 usb_core_id;
bool cdrom;
bool internal_ums;
+ char streaming_func[MAX_STREAMING_FUNCS][FUNC_NAME_LEN];
+ int streaming_func_count;
};
#ifndef CONFIG_TARGET_CORE
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index fea832e..3844f41 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -508,6 +508,7 @@
* @dev: Driver model state for this abstract device.
* @usb_core_id: Identifies the usb core controlled by this usb_gadget.
* Used in case of more then one core operates concurrently.
+ * @streaming_enabled: Enable streaming mode with usb core.
*
* Gadgets have a mostly-portable "gadget driver" implementing device
* functions, handling all usb configurations and interfaces. Gadget
@@ -546,6 +547,7 @@
struct device dev;
u8 usb_core_id;
bool l1_supported;
+ bool streaming_enabled;
};
static inline void set_gadget_data(struct usb_gadget *gadget, void *data)
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 07f9b90..9eb9cd8 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -229,7 +229,9 @@
* between 1 to 7.
* @l1_supported: enable link power management support.
* @dpdm_pulldown_added: Indicates whether pull down resistors are
- connected on data lines or not.
+ * connected on data lines or not.
+ * @enable_ahb2ahb_bypass: Indicates whether enable AHB2AHB BYPASS
+ * mode with controller in device mode.
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -258,6 +260,7 @@
int log2_itc;
bool l1_supported;
bool dpdm_pulldown_added;
+ bool enable_ahb2ahb_bypass;
};
/* phy related flags */
@@ -462,6 +465,7 @@
int log2_itc;
void *prv_data;
bool l1_supported;
+ bool enable_ahb2ahb_bypass;
};
/**
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 58ab4eb..2a5ebd4 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -49,6 +49,10 @@
#define L1_CONFIG_PHY_LPM BIT(10)
#define L1_CONFIG_PLL BIT(11)
+#define AHB2AHB_BYPASS BIT(31)
+#define AHB2AHB_BYPASS_BIT_MASK BIT(31)
+#define AHB2AHB_BYPASS_CLEAR (0 << 31)
+
#define PORTSC_PHCD (1 << 23) /* phy suspend mode */
#define PORTSC_PTS_MASK (3 << 30)
#define PORTSC_PTS_ULPI (3 << 30)
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 1d10474..2d59889 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -140,7 +140,6 @@
}
extern unsigned long global_reclaimable_pages(void);
-extern unsigned long zone_reclaimable_pages(struct zone *zone);
#ifdef CONFIG_NUMA
/*
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4ecadd8..eafb5fd 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2691,6 +2691,30 @@
extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
/**
+ * regulatory_hint_user - hint to the wireless core a regulatory domain
+ * which the driver has received from an application
+ * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain
+ * should be in. If @rd is set this should be NULL. Note that if you
+ * set this to NULL you should still set rd->alpha2 to some accepted
+ * alpha2.
+ *
+ * Wireless drivers can use this function to hint to the wireless core
+ * the current regulatory domain as specified by trusted applications,
+ * it is the driver's responsibilty to estbalish which applications it
+ * trusts.
+ *
+ * The wiphy should be registered to cfg80211 prior to this call.
+ * For cfg80211 drivers this means you must first use wiphy_register(),
+ * for mac80211 drivers you must first use ieee80211_register_hw().
+ *
+ * Drivers should check the return value, its possible you can get
+ * an -ENOMEM or an -EINVAL.
+ *
+ * Return: 0 on success. -ENOMEM, -EINVAL.
+ */
+extern int regulatory_hint_user(const char *alpha2);
+
+/**
* wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
* @wiphy: the wireless device we want to process the regulatory domain on
* @regd: the custom regulatory domain to use for this wiphy
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index bbda72e..104f86e 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -3676,6 +3676,7 @@
} __packed;
#define ASM_SESSION_CMD_PAUSE 0x00010BD3
+#define ASM_SESSION_CMD_SUSPEND 0x00010DEC
#define ASM_SESSION_CMD_GET_SESSIONTIME_V3 0x00010D9D
#define ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS 0x00010BD5
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 0dd1f1c..65ca46f 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -54,6 +54,7 @@
#define CMD_EOS 0x0003
#define CMD_CLOSE 0x0004
#define CMD_OUT_FLUSH 0x0005
+#define CMD_SUSPEND 0x0006
/* bit 0:1 represents priority of stream */
#define STREAM_PRIORITY_NORMAL 0x0000
diff --git a/mm/internal.h b/mm/internal.h
index 3439ef4..f5369cc 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -90,6 +90,8 @@
*/
extern int isolate_lru_page(struct page *page);
extern void putback_lru_page(struct page *page);
+extern unsigned long zone_reclaimable_pages(struct zone *zone);
+extern bool zone_reclaimable(struct zone *zone);
/*
* in mm/page_alloc.c
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 26adea8..a5e8dc2 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -34,8 +34,11 @@
#include <linux/syscalls.h>
#include <linux/buffer_head.h> /* __set_page_dirty_buffers */
#include <linux/pagevec.h>
+#include <linux/mm_inline.h>
#include <trace/events/writeback.h>
+#include "internal.h"
+
/*
* Sleep at most 200ms at a time in balance_dirty_pages().
*/
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 46ccd2f..a1e4f77 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -57,6 +57,7 @@
#include <linux/ftrace_event.h>
#include <linux/memcontrol.h>
#include <linux/prefetch.h>
+#include <linux/mm_inline.h>
#include <linux/migrate.h>
#include <linux/page-debug-flags.h>
@@ -647,7 +648,6 @@
int mt = 0;
spin_lock(&zone->lock);
- zone->all_unreclaimable = 0;
zone->pages_scanned = 0;
while (to_free) {
@@ -693,7 +693,6 @@
int migratetype)
{
spin_lock(&zone->lock);
- zone->all_unreclaimable = 0;
zone->pages_scanned = 0;
__free_one_page(page, zone, order, migratetype);
@@ -2997,7 +2996,7 @@
K(zone_page_state(zone, NR_FREE_CMA_PAGES)),
K(zone_page_state(zone, NR_WRITEBACK_TEMP)),
zone->pages_scanned,
- (zone->all_unreclaimable ? "yes" : "no")
+ (!zone_reclaimable(zone) ? "yes" : "no")
);
printk("lowmem_reserve[]:");
for (i = 0; i < MAX_NR_ZONES; i++)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 22c215d..9e95109 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -158,8 +158,28 @@
return &mz->zone->reclaim_stat;
}
+unsigned long zone_reclaimable_pages(struct zone *zone)
+{
+ int nr;
+
+ nr = zone_page_state(zone, NR_ACTIVE_FILE) +
+ zone_page_state(zone, NR_INACTIVE_FILE);
+
+ if (get_nr_swap_pages() > 0)
+ nr += zone_page_state(zone, NR_ACTIVE_ANON) +
+ zone_page_state(zone, NR_INACTIVE_ANON);
+
+ return nr;
+}
+
+bool zone_reclaimable(struct zone *zone)
+{
+ return zone->pages_scanned < zone_reclaimable_pages(zone) * 6;
+}
+
static unsigned long zone_nr_lru_pages(struct mem_cgroup_zone *mz,
enum lru_list lru)
+
{
if (!mem_cgroup_disabled())
return mem_cgroup_zone_nr_lru_pages(mz->mem_cgroup,
@@ -1648,7 +1668,7 @@
* latencies, so it's better to scan a minimum amount there as
* well.
*/
- if (current_is_kswapd() && mz->zone->all_unreclaimable)
+ if (current_is_kswapd() && !zone_reclaimable(mz->zone))
force_scan = true;
if (!global_reclaim(sc))
force_scan = true;
@@ -1995,8 +2015,8 @@
if (global_reclaim(sc)) {
if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
continue;
- if (zone->all_unreclaimable &&
- sc->priority != DEF_PRIORITY)
+ if (sc->priority != DEF_PRIORITY &&
+ !zone_reclaimable(zone))
continue; /* Let kswapd poll it */
if (COMPACTION_BUILD) {
/*
@@ -2034,11 +2054,6 @@
return aborted_reclaim;
}
-static bool zone_reclaimable(struct zone *zone)
-{
- return zone->pages_scanned < zone_reclaimable_pages(zone) * 6;
-}
-
/* All zones in zonelist are unreclaimable? */
static bool all_unreclaimable(struct zonelist *zonelist,
struct scan_control *sc)
@@ -2052,7 +2067,7 @@
continue;
if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
continue;
- if (!zone->all_unreclaimable)
+ if (zone_reclaimable(zone))
return false;
}
@@ -2377,7 +2392,7 @@
* they must be considered balanced here as well if kswapd
* is to sleep
*/
- if (zone->all_unreclaimable) {
+ if (!zone_reclaimable(zone)) {
balanced += zone->present_pages;
continue;
}
@@ -2470,8 +2485,8 @@
if (!populated_zone(zone))
continue;
- if (zone->all_unreclaimable &&
- sc.priority != DEF_PRIORITY)
+ if (sc.priority != DEF_PRIORITY &&
+ !zone_reclaimable(zone))
continue;
/*
@@ -2525,8 +2540,8 @@
if (!populated_zone(zone))
continue;
- if (zone->all_unreclaimable &&
- sc.priority != DEF_PRIORITY)
+ if (sc.priority != DEF_PRIORITY &&
+ !zone_reclaimable(zone))
continue;
sc.nr_scanned = 0;
@@ -2576,8 +2591,6 @@
sc.nr_reclaimed += reclaim_state->reclaimed_slab;
total_scanned += sc.nr_scanned;
- if (nr_slab == 0 && !zone_reclaimable(zone))
- zone->all_unreclaimable = 1;
}
/*
@@ -2589,7 +2602,7 @@
total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2)
sc.may_writepage = 1;
- if (zone->all_unreclaimable) {
+ if (!zone_reclaimable(zone)) {
if (end_zone && end_zone == i)
end_zone--;
continue;
@@ -2919,20 +2932,6 @@
return nr;
}
-unsigned long zone_reclaimable_pages(struct zone *zone)
-{
- int nr;
-
- nr = zone_page_state(zone, NR_ACTIVE_FILE) +
- zone_page_state(zone, NR_INACTIVE_FILE);
-
- if (nr_swap_pages > 0)
- nr += zone_page_state(zone, NR_ACTIVE_ANON) +
- zone_page_state(zone, NR_INACTIVE_ANON);
-
- return nr;
-}
-
#ifdef CONFIG_HIBERNATION
/*
* Try to free `nr_to_reclaim' of memory, system-wide, and return the number of
@@ -3227,7 +3226,7 @@
zone_page_state(zone, NR_SLAB_RECLAIMABLE) <= zone->min_slab_pages)
return ZONE_RECLAIM_FULL;
- if (zone->all_unreclaimable)
+ if (!zone_reclaimable(zone))
return ZONE_RECLAIM_FULL;
/*
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 959a558..9559032 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -19,6 +19,9 @@
#include <linux/math64.h>
#include <linux/writeback.h>
#include <linux/compaction.h>
+#include <linux/mm_inline.h>
+
+#include "internal.h"
#ifdef CONFIG_VM_EVENT_COUNTERS
DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
@@ -1027,7 +1030,7 @@
"\n all_unreclaimable: %u"
"\n start_pfn: %lu"
"\n inactive_ratio: %u",
- zone->all_unreclaimable,
+ !zone_reclaimable(zone),
zone->zone_start_pfn,
zone->inactive_ratio);
seq_putc(m, '\n');
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index b96094c..a216f8e 100755
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1648,6 +1648,7 @@
return 0;
}
+EXPORT_SYMBOL(regulatory_hint_user);
/* Driver hints */
int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index e2aaaf5..017880c 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -22,8 +22,6 @@
bool reg_is_valid_request(const char *alpha2);
bool reg_supported_dfs_region(u8 dfs_region);
-int regulatory_hint_user(const char *alpha2);
-
int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env);
void reg_device_remove(struct wiphy *wiphy);
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 6785fe1..52af21c 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -3007,10 +3007,21 @@
return NULL;
}
+static int msm8x10_wcd_device_down(struct snd_soc_codec *codec)
+{
+ dev_dbg(codec->dev, "%s: device down!\n", __func__);
+
+ snd_soc_card_change_online_state(codec->card, 0);
+ return 0;
+}
static int msm8x10_wcd_device_up(struct snd_soc_codec *codec)
{
- pr_debug("%s: device up!\n", __func__);
+ dev_dbg(codec->dev, "%s: device up!\n", __func__);
+
+ snd_soc_card_change_online_state(codec->card, 1);
+ /* delay is required to make sure sound card state updated */
+ usleep_range(5000, 5100);
mutex_lock(&codec->mutex);
@@ -3029,7 +3040,9 @@
bool timedout;
unsigned long timeout;
- if (value == SUBSYS_AFTER_POWERUP) {
+ if (value == SUBSYS_BEFORE_SHUTDOWN)
+ msm8x10_wcd_device_down(registered_codec);
+ else if (value == SUBSYS_AFTER_POWERUP) {
pr_debug("%s: ADSP is about to power up. bring up codec\n",
__func__);
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 |
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 7c4547e..7a5efb0 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1225,6 +1225,7 @@
data->payload_size))
break;
case ASM_SESSION_CMD_PAUSE:
+ case ASM_SESSION_CMD_SUSPEND:
case ASM_DATA_CMD_EOS:
case ASM_STREAM_CMD_CLOSE:
case ASM_STREAM_CMD_FLUSH:
@@ -3870,6 +3871,11 @@
hdr.opcode = ASM_SESSION_CMD_PAUSE;
state = &ac->cmd_state;
break;
+ case CMD_SUSPEND:
+ pr_debug("%s:CMD_SUSPEND\n", __func__);
+ hdr.opcode = ASM_SESSION_CMD_SUSPEND;
+ state = &ac->cmd_state;
+ break;
case CMD_FLUSH:
pr_debug("%s:CMD_FLUSH\n", __func__);
hdr.opcode = ASM_STREAM_CMD_FLUSH;