Merge "mmc: core : fix arbitrary read/write to user space"
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 99de826..3a293a3 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -198,16 +198,21 @@
- qti,cpr-uplift-speed-bin: The speed bin value corresponding to one type of processor which needs to apply the
pvs voltage uplift workaround.
This is required if cpr-fuse-uplift-disable-sel is present.
-- qti,cpr-quot-adjust-table: Array of 4-tuples in which each 4-tuple indicates the speed bin
- of the CPU, the frequency of the CPU, the quotient adjustment and the voltage corner to use.
- The 4 elements in one 4-tuple are:
- [0]: => the speed bin of the CPU;
- [1]: => the frequency in kHz of the CPU;
- [2]: => the quotient adjustment of the corresponding frequency;
- [3]: => the voltage corner to use.
- If the speed bin in a tuple is eqaul to the speed bin of the CPU, then the quotient
- adjustment would be subtracted from the quotient value of the voltage corner
- when the CPU is running at that frequency.
+- qti,cpr-quot-adjust-table: Array of triples in which each triple indicates the speed bin of the CPU, the virtual
+ corner to use and the quotient adjustment.
+ The 3 elements in one triple are:
+ [0]: => the speed bin of the CPU.
+ [1]: => the virtual voltage corner to use.
+ [2]: => the quotient adjustment for the corresponding virtual corner.
+ If the speed bin in a triple is equal to the speed bin of the CPU, the adjustment would
+ be subtracted from the quotient value of the voltage corner when the CPU is running at
+ that virtual corner. Each virtual corner value must be in the range 1 to the number of
+ elements in qti,cpr-corner-map.
+- qti,cpr-corner-map: Array of elements of fuse corner value for each virtual corner.
+ The location or 1-based index of an element in the list corresponds to
+ the virtual corner value. For example, the first element in the list is the fuse corner
+ value that virtual corner 1 maps to.
+ This is required if qti,cpr-quot-adjust-table is present.
Example:
apc_vreg_corner: regulator@f9018000 {
@@ -270,9 +275,10 @@
qti,cpr-uplift-max-volt = <1350000>;
qti,cpr-uplift-speed-bin = <1>;
qti,speed-bin-fuse-sel = <22 0 3 0>;
- qti,cpr-quot-adjust-table = <1 998400 450 3>,
- <1 1094400 375 3>, <1 1190400 300 3>,
- <1 1305600 225 3>, <1 1344000 187 3>,
- <1 1401600 150 3>, <1 1497600 75 3>;
+ qti,cpr-corner-map = <1 1 2 2 3 3 3 3 3 3 3 3>;
+ qti,cpr-quot-adjust-table = <1 1 0>, <1 2 0>, <1 3 0>,
+ <1 4 0>, <1 5 450>, <1 6 375>,
+ <1 7 300>, <1 8 225>, <1 9 187>,
+ <1 10 150>, <1 11 75>, <1 12 0>;
};
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 0e236f2..113ded8 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -142,6 +142,8 @@
0 = default value.
- qcom,mdss-dsi-bl-max-level: Specifies the max backlight level supported by the panel.
255 = default value.
+- qcom,mdss-brightness-max-level: Specifies the max brightness level supported.
+ 255 = default value.
- qcom,mdss-dsi-interleave-mode: Specifies interleave mode.
0 = default value.
- qcom,mdss-dsi-panel-type: Specifies the panel operating mode.
diff --git a/Documentation/devicetree/bindings/fb/mdss-edp.txt b/Documentation/devicetree/bindings/fb/mdss-edp.txt
index 2070c64..fd8d14f 100644
--- a/Documentation/devicetree/bindings/fb/mdss-edp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-edp.txt
@@ -26,6 +26,8 @@
Optional properties:
- qcom,cont-splash-enabled: Boolean used to enable continuous splash mode.
+- qcom,mdss-brightness-max-level: Specifies the max brightness level supported.
+ 255 = default value.
Example:
mdss_edp: qcom,mdss_edp@fd923400 {
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index a77b5ff..6277054 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -4,23 +4,29 @@
Required properties:
- - compatible : "qcom,msm-pcm-dsp"
+ - compatible : "qti,msm-pcm-dsp"
- - qcom,msm-pcm-dsp-id : device node id
+ - qti,msm-pcm-dsp-id : device node id
* msm-pcm-low-latency
Required properties:
- - compatible : "qcom,msm-pcm-dsp"
+ - compatible : "qti,msm-pcm-dsp"
- - qcom,msm-pcm-dsp-id : device node id
+ - qti,msm-pcm-dsp-id : device node id
Optional properties
- - qcom,msm-pcm-low-latency : Flag indicating whether
+ - qti,msm-pcm-low-latency : Flag indicating whether
the device node is of type low latency.
+ - qti,latency-level : Flag indicating whether the device node
+ is of type regular low latency or ultra
+ low latency.
+ regular : regular low latency stream
+ ultra : ultra low latency stream
+
* msm-pcm-routing
Required properties:
@@ -226,16 +232,16 @@
Example:
- qcom,msm-pcm {
- compatible = "qcom,msm-pcm-dsp";
- qcom,msm-pcm-dsp-id = <0>;
+ qti,msm-pcm {
+ compatible = "qti,msm-pcm-dsp";
+ qti,msm-pcm-dsp-id = <0>;
};
- qcom,msm-pcm-low-latency {
- compatible = "qcom,msm-pcm-dsp";
- qcom,msm-pcm-dsp-id = <1>;
- qcom,msm-pcm-low-latency;
- };
+ qti,msm-pcm-low-latency {
+ compatible = "qti,msm-pcm-dsp";
+ qti,msm-pcm-dsp-id = <1>;
+ qti,msm-pcm-low-latency;
+ };
qcom,msm-pcm-routing {
compatible = "qcom,msm-pcm-routing";
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 63da606..dbeaa97 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -36,7 +36,7 @@
interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
- regulator-max-microvolt = <3>;
+ regulator-max-microvolt = <12>;
qti,pvs-fuse-redun-sel = <22 24 3 2 0>;
qti,pvs-fuse = <22 6 5 0>;
@@ -91,13 +91,15 @@
qti,cpr-uplift-max-volt = <1350000>;
qti,cpr-uplift-speed-bin = <1>;
qti,speed-bin-fuse-sel = <22 0 3 0>;
- qti,cpr-quot-adjust-table = <1 300000 0 1>,
- <1 384000 0 1>, <1 600000 0 2>,
- <1 787200 0 2>, <1 998400 450 3>,
- <1 1094400 375 3>, <1 1190400 300 3>,
- <1 1305600 225 3>, <1 1344000 187 3>,
- <1 1401600 150 3>, <1 1497600 75 3>,
- <1 1593600 0 3>;
+ qti,cpr-corner-map = <1 1 2 2 3 3 3 3 3 3 3 3>;
+ qti,cpr-quot-adjust-table =
+ <1 5 450>,
+ <1 6 375>,
+ <1 7 300>,
+ <1 8 225>,
+ <1 9 187>,
+ <1 10 150>,
+ <1 11 75>;
};
};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index fc00411..baa81cc 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -429,19 +429,20 @@
qcom,tapan-codec-9302;
};
- qcom,msm-pcm {
- compatible = "qcom,msm-pcm-dsp";
- qcom,msm-pcm-dsp-id = <0>;
+ qti,msm-pcm {
+ compatible = "qti,msm-pcm-dsp";
+ qti,msm-pcm-dsp-id = <0>;
};
qcom,msm-pcm-routing {
compatible = "qcom,msm-pcm-routing";
};
- qcom,msm-pcm-low-latency {
- compatible = "qcom,msm-pcm-dsp";
- qcom,msm-pcm-dsp-id = <1>;
- qcom,msm-pcm-low-latency;
+ qti,msm-pcm-low-latency {
+ compatible = "qti,msm-pcm-dsp";
+ qti,msm-pcm-dsp-id = <1>;
+ qti,msm-pcm-low-latency;
+ qti,latency-level = "regular";
};
qcom,msm-pcm-lpa {
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 543f59e..51a9516 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -36,7 +36,7 @@
interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
- regulator-max-microvolt = <3>;
+ regulator-max-microvolt = <12>;
qti,pvs-fuse-redun-sel = <53 25 3 2 1>;
qti,pvs-fuse = <23 6 5 1>;
@@ -83,6 +83,7 @@
qti,cpr-fuse-redun-bp-scheme = <25>;
qti,cpr-fuse-redun-target-quot = <32 12 0>;
qti,cpr-fuse-redun-ro-sel = <44 26 29>;
+ qti,cpr-corner-map = <1 1 2 2 3 3 3 3 3 3 3 3>;
qti,cpr-enable;
};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 94a9db0..03ef738 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -615,15 +615,16 @@
qcom,model = "msm8x10-snd-card";
};
- qcom,msm-pcm {
- compatible = "qcom,msm-pcm-dsp";
- qcom,msm-pcm-dsp-id = <0>;
+ qti,msm-pcm {
+ compatible = "qti,msm-pcm-dsp";
+ qti,msm-pcm-dsp-id = <0>;
};
- qcom,msm-pcm-low-latency {
- compatible = "qcom,msm-pcm-dsp";
- qcom,msm-pcm-dsp-id = <1>;
- qcom,msm-pcm-low-latency;
+ qti,msm-pcm-low-latency {
+ compatible = "qti,msm-pcm-dsp";
+ qti,msm-pcm-dsp-id = <1>;
+ qti,msm-pcm-low-latency;
+ qti,latency-level = "ultra";
};
qcom,msm-pcm-routing {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index b4a3e55..a912da8 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1628,15 +1628,16 @@
compatible = "qcom,msm-audio-ion";
};
- qcom,msm-pcm {
- compatible = "qcom,msm-pcm-dsp";
- qcom,msm-pcm-dsp-id = <0>;
+ qti,msm-pcm {
+ compatible = "qti,msm-pcm-dsp";
+ qti,msm-pcm-dsp-id = <0>;
};
- qcom,msm-pcm-low-latency {
- compatible = "qcom,msm-pcm-dsp";
- qcom,msm-pcm-dsp-id = <1>;
- qcom,msm-pcm-low-latency;
+ qti,msm-pcm-low-latency {
+ compatible = "qti,msm-pcm-dsp";
+ qti,msm-pcm-dsp-id = <1>;
+ qti,msm-pcm-low-latency;
+ qti,latency-level = "regular";
};
qcom,msm-pcm-routing {
diff --git a/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts b/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
index fa313bf..6b62391 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
@@ -22,5 +22,5 @@
};
&sdhc_1 {
- qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+ qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
};
diff --git a/arch/arm/boot/dts/msm8974pro-pm.dtsi b/arch/arm/boot/dts/msm8974pro-pm.dtsi
index 938a2cc..63cb68b 100644
--- a/arch/arm/boot/dts/msm8974pro-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm.dtsi
@@ -214,6 +214,9 @@
<50 172>, /* usb1_hs_async_wakeup_irq */
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <0xff 18>, /* APCx_qgicQTmrSecPhysIrptReq */
+ <0xff 19>, /* APCx_qgicQTmrSecPhysIrptReq */
+ <0xff 25>, /* APCx_qgicExtFaultIrptReq */
<0xff 33>, /*l2_perf_mon*/
<0xff 34>, /* APCC_qgicL2ErrorIrptReq */
<0xff 35>, /* WDT_barkInt */
@@ -237,7 +240,10 @@
<0xff 105>, /* iommu_pmon_nonsecure_irq */
<0xff 109>, /* ocmem_dm_nonsec_irq */
<0xff 126>, /* bam_irq[0] */
+ <0xff 140>, /* uart_dm_intr */
<0xff 155>, /* sdcc_irq[0] */
+ <0xff 157>, /* sdcc_irq[0] */
+ <0xff 159>, /* sdcc_irq[0] */
<0xff 163>, /* usb30_ee1_irq */
<0xff 170>, /* sdcc_pwr_cmd_irq */
<0xff 173>, /* o_wcss_apss_smd_hi */
@@ -270,6 +276,8 @@
<0xff 207>, /* rpm_ipc(27) */
<0xff 211>, /* usb_dwc3_otg */
<0xff 240>, /* summary_irq_kpss */
+ <0xff 253>, /* sdcc_pwr_cmd_irq */
+ <0xff 256>, /* sdcc_pwr_cmd_irq */
<0xff 268>, /* bam_irq[1] */
<0xff 270>, /* bam_irq[0] */
<0xff 271>; /* bam_irq[0] */
diff --git a/arch/arm/boot/dts/msm8974pro-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
index 2c06c3c..2783ffd 100644
--- a/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
@@ -60,6 +60,10 @@
vdd_cx-supply = <&pm8841_s2_corner>;
};
+&pm8841_s2_corner {
+ qcom,init-smps-mode = <0>; /* Allow AUTO mode for VDD_CX. */
+};
+
&krait_regulator_pmic {
status = "ok";
diff --git a/arch/arm/boot/dts/msm8974pro-pma8084.dtsi b/arch/arm/boot/dts/msm8974pro-pma8084.dtsi
index 71fbeae..c06ebf8 100644
--- a/arch/arm/boot/dts/msm8974pro-pma8084.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pma8084.dtsi
@@ -191,6 +191,10 @@
vdd_cx-supply = <&pma8084_s2_corner>;
};
+&pma8084_s2_corner {
+ qcom,init-smps-mode = <0>; /* Allow AUTO mode for VDD_CX. */
+};
+
&krait_regulator_pmic {
status = "ok";
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 0e7baf1..dee1f68 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -686,9 +686,9 @@
qcom,adsp-state = <2>;
};
- qcom,msm-pcm {
- compatible = "qcom,msm-pcm-dsp";
- qcom,msm-pcm-dsp-id = <0>;
+ qti,msm-pcm {
+ compatible = "qti,msm-pcm-dsp";
+ qti,msm-pcm-dsp-id = <0>;
};
qcom,msm-pcm-routing {
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index da3cfba..d42e798 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -60,64 +60,64 @@
};
static struct clkctl_acpu_speed acpu_freq_tbl_8226_1p1[] = {
- { 1, 300000, PLL0, 4, 2, CPR_CORNER_SVS, 0, 4 },
- { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_SVS, 0, 4 },
- { 1, 600000, PLL0, 4, 0, CPR_CORNER_NORMAL, 0, 6 },
- { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_NORMAL, 0, 6 },
- { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1094400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 0, 1190400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 300000, PLL0, 4, 2, CPR_CORNER_2, 0, 4 },
+ { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_2, 0, 4 },
+ { 1, 600000, PLL0, 4, 0, CPR_CORNER_4, 0, 6 },
+ { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_4, 0, 6 },
+ { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
+ { 1, 1094400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
+ { 0, 1190400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
{ 0 }
};
static struct clkctl_acpu_speed acpu_freq_tbl_8226_1p2[] = {
- { 1, 300000, PLL0, 4, 2, CPR_CORNER_SVS, 0, 4 },
- { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_SVS, 0, 4 },
- { 1, 600000, PLL0, 4, 0, CPR_CORNER_NORMAL, 0, 6 },
- { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_NORMAL, 0, 6 },
- { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1094400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1190400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 300000, PLL0, 4, 2, CPR_CORNER_2, 0, 4 },
+ { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_2, 0, 4 },
+ { 1, 600000, PLL0, 4, 0, CPR_CORNER_4, 0, 6 },
+ { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_4, 0, 6 },
+ { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
+ { 1, 1094400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
+ { 1, 1190400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
{ 0 }
};
static struct clkctl_acpu_speed acpu_freq_tbl_8226_1p4[] = {
- { 1, 300000, PLL0, 4, 2, CPR_CORNER_SVS, 0, 4 },
- { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_SVS, 0, 4 },
- { 1, 600000, PLL0, 4, 0, CPR_CORNER_NORMAL, 0, 6 },
- { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_NORMAL, 0, 6 },
- { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1094400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1190400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1305600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1344000, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1401600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 300000, PLL0, 4, 2, CPR_CORNER_2, 0, 4 },
+ { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_2, 0, 4 },
+ { 1, 600000, PLL0, 4, 0, CPR_CORNER_4, 0, 6 },
+ { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_4, 0, 6 },
+ { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
+ { 1, 1094400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
+ { 1, 1190400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
+ { 1, 1305600, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
+ { 1, 1344000, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
+ { 1, 1401600, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
{ 0 }
};
static struct clkctl_acpu_speed acpu_freq_tbl_8226_1p6[] = {
- { 1, 300000, PLL0, 4, 2, CPR_CORNER_SVS, 0, 4 },
- { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_SVS, 0, 4 },
- { 1, 600000, PLL0, 4, 0, CPR_CORNER_NORMAL, 0, 6 },
- { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_NORMAL, 0, 6 },
- { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1094400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1190400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1305600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1344000, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1401600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1497600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- { 1, 1593600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 300000, PLL0, 4, 2, CPR_CORNER_2, 0, 4 },
+ { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_2, 0, 4 },
+ { 1, 600000, PLL0, 4, 0, CPR_CORNER_4, 0, 6 },
+ { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_4, 0, 6 },
+ { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_5, 0, 7 },
+ { 1, 1094400, ACPUPLL, 5, 0, CPR_CORNER_6, 0, 7 },
+ { 1, 1190400, ACPUPLL, 5, 0, CPR_CORNER_7, 0, 7 },
+ { 1, 1305600, ACPUPLL, 5, 0, CPR_CORNER_8, 0, 7 },
+ { 1, 1344000, ACPUPLL, 5, 0, CPR_CORNER_9, 0, 7 },
+ { 1, 1401600, ACPUPLL, 5, 0, CPR_CORNER_10, 0, 7 },
+ { 1, 1497600, ACPUPLL, 5, 0, CPR_CORNER_11, 0, 7 },
+ { 1, 1593600, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 7 },
{ 0 }
};
static struct clkctl_acpu_speed acpu_freq_tbl_8610[] = {
- { 1, 300000, PLL0, 4, 2, CPR_CORNER_SVS, 0, 3 },
- { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_SVS, 0, 3 },
- { 1, 600000, PLL0, 4, 0, CPR_CORNER_NORMAL, 0, 4 },
- { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_NORMAL, 0, 4 },
- { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 5 },
- { 1, 1190400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 5 },
+ { 1, 300000, PLL0, 4, 2, CPR_CORNER_2, 0, 3 },
+ { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_2, 0, 3 },
+ { 1, 600000, PLL0, 4, 0, CPR_CORNER_4, 0, 4 },
+ { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_4, 0, 4 },
+ { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 5 },
+ { 1, 1190400, ACPUPLL, 5, 0, CPR_CORNER_12, 0, 5 },
{ 0 }
};
@@ -135,7 +135,7 @@
.freq_tbl = acpu_freq_tbl_8226_1p1,
.pvs_tables = pvs_tables_8226,
.bus_scale = &bus_client_pdata,
- .vdd_max_cpu = CPR_CORNER_TURBO,
+ .vdd_max_cpu = CPR_CORNER_12,
.src_clocks = {
[PLL0].name = "gpll0",
[ACPUPLL].name = "a7sspll",
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 0051578..6ae909b 100755
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -579,17 +579,6 @@
| BVAL(10, 8, s##_mm_source_val), \
}
-#define F_HDMI(f, s, div, m, n) \
- { \
- .freq_hz = (f), \
- .src_clk = &s##_clk_src, \
- .m_val = (m), \
- .n_val = ~((n)-(m)) * !!(n), \
- .d_val = ~(n),\
- .div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
- | BVAL(10, 8, s##_mm_source_val), \
- }
-
#define F_EDP(f, s, div, m, n) \
{ \
.freq_hz = (f), \
@@ -3267,60 +3256,19 @@
},
};
-static int hdmi_pll_clk_enable(struct clk *c)
-{
- return hdmi_pll_enable();
-}
-
-static void hdmi_pll_clk_disable(struct clk *c)
-{
- hdmi_pll_disable();
-}
-
-static int hdmi_pll_clk_set_rate(struct clk *c, unsigned long rate)
-{
- return hdmi_pll_set_rate(rate);
-}
-
-static struct clk_ops clk_ops_hdmi_pll = {
- .enable = hdmi_pll_clk_enable,
- .disable = hdmi_pll_clk_disable,
- .set_rate = hdmi_pll_clk_set_rate,
-};
-
-static struct clk hdmipll_clk_src = {
- .parent = &cxo_clk_src.c,
- .dbg_name = "hdmipll_clk_src",
- .ops = &clk_ops_hdmi_pll,
- CLK_INIT(hdmipll_clk_src),
-};
-
static struct clk_freq_tbl ftbl_mdss_extpclk_clk[] = {
- /*
- * The zero rate is required since suspend/resume wipes out the HDMI PHY
- * registers. This entry allows the HDMI driver to switch the cached
- * rate to zero before suspend and back to the real rate after resume.
- */
- F_HDMI( 0, hdmipll, 1, 0, 0),
- F_HDMI( 25200000, hdmipll, 1, 0, 0),
- F_HDMI( 27000000, hdmipll, 1, 0, 0),
- F_HDMI( 27030000, hdmipll, 1, 0, 0),
- F_HDMI( 65000000, hdmipll, 1, 0, 0),
- F_HDMI( 74250000, hdmipll, 1, 0, 0),
- F_HDMI(108000000, hdmipll, 1, 0, 0),
- F_HDMI(148500000, hdmipll, 1, 0, 0),
- F_HDMI(268500000, hdmipll, 1, 0, 0),
- F_HDMI(297000000, hdmipll, 1, 0, 0),
+ F_MM(148500000, hdmipll, 1, 0, 0),
F_END
};
static struct rcg_clk extpclk_clk_src = {
.cmd_rcgr_reg = EXTPCLK_CMD_RCGR,
.freq_tbl = ftbl_mdss_extpclk_clk,
- .current_freq = &rcg_dummy_freq,
+ .current_freq = ftbl_mdss_extpclk_clk,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "extpclk_clk_src",
+ .parent = &hdmipll_clk_src.c,
.ops = &clk_ops_rcg_hdmi,
VDD_DIG_FMAX_MAP2(LOW, 148500000, NOMINAL, 297000000),
CLK_INIT(extpclk_clk_src.c),
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index cc6f290..e3693ee 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -843,23 +843,16 @@
*/
static int rcg_clk_set_rate_hdmi(struct clk *c, unsigned long rate)
{
- struct clk_freq_tbl *nf;
struct rcg_clk *rcg = to_rcg_clk(c);
+ struct clk_freq_tbl *nf = rcg->freq_tbl;
int rc;
- for (nf = rcg->freq_tbl; nf->freq_hz != rate; nf++)
- if (nf->freq_hz == FREQ_END) {
- rc = -EINVAL;
- goto out;
- }
-
rc = clk_set_rate(nf->src_clk, rate);
if (rc < 0)
goto out;
set_rate_hid(rcg, nf);
rcg->current_freq = nf;
- c->parent = nf->src_clk;
out:
return rc;
}
@@ -870,12 +863,6 @@
struct clk *clk;
struct clk_freq_tbl *freq;
uint32_t rate;
- u32 cmd_rcgr_regval;
-
- /* Is there a pending configuration? */
- cmd_rcgr_regval = readl_relaxed(CMD_RCGR_REG(rcg));
- if (cmd_rcgr_regval & CMD_RCGR_CONFIG_DIRTY_MASK)
- return NULL;
/* Figure out what rate the rcg is running at */
for (freq = rcg->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
@@ -895,6 +882,21 @@
return freq->src_clk;
}
+static struct clk *rcg_hdmi_clk_get_parent(struct clk *c)
+{
+ struct rcg_clk *rcg = to_rcg_clk(c);
+ struct clk_freq_tbl *freq = rcg->freq_tbl;
+ u32 cmd_rcgr_regval;
+
+ /* Is there a pending configuration? */
+ cmd_rcgr_regval = readl_relaxed(CMD_RCGR_REG(rcg));
+ if (cmd_rcgr_regval & CMD_RCGR_CONFIG_DIRTY_MASK)
+ return NULL;
+
+ rcg->current_freq->freq_hz = clk_get_rate(c->parent);
+
+ return freq->src_clk;
+}
static DEFINE_SPINLOCK(mux_reg_lock);
@@ -1007,7 +1009,7 @@
.list_rate = rcg_clk_list_rate,
.round_rate = rcg_clk_round_rate,
.handoff = rcg_clk_handoff,
- .get_parent = rcg_clk_get_parent,
+ .get_parent = rcg_hdmi_clk_get_parent,
};
struct clk_ops clk_ops_rcg_edp = {
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index b500e1d..d1b1885 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -171,23 +171,71 @@
(!(readl_relaxed(gdsc_base) & BIT(0)));
}
-void hdmi_pll_disable(void)
+/* Auto PLL calibaration */
+static int mdss_ahb_clk_enable(int enable)
{
- clk_enable(mdss_ahb_clk);
+ int rc = 0;
+
+ /* todo: Ideally, we should enable/disable GDSC whenever we are
+ * attempting to enable/disable MDSS AHB clock.
+ * For now, just return error if GDSC is not enabled.
+ */
+ if (!mdss_gdsc_enabled()) {
+ pr_err("%s: mdss GDSC is not enabled\n", __func__);
+ return -EPERM;
+ }
+
+ if (enable)
+ rc = clk_prepare_enable(mdss_ahb_clk);
+ else
+ clk_disable_unprepare(mdss_ahb_clk);
+
+ return rc;
+}
+
+static void hdmi_vco_disable(struct clk *c)
+{
+ u32 rc;
+
+ if (!mdss_gdsc_enabled()) {
+ pr_err("%s: mdss GDSC is not enabled\n", __func__);
+ return;
+ }
+
+ rc = clk_enable(mdss_ahb_clk);
+ if (rc) {
+ pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
+ __func__, rc);
+ return;
+ }
+
REG_W(0x0, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
udelay(5);
REG_W(0x0, hdmi_phy_base + HDMI_PHY_GLB_CFG);
+
clk_disable(mdss_ahb_clk);
hdmi_pll_on = 0;
-} /* hdmi_pll_disable */
+} /* hdmi_vco_disable */
-int hdmi_pll_enable(void)
+static int hdmi_vco_enable(struct clk *c)
{
u32 status;
+ u32 rc;
u32 max_reads, timeout_us;
- clk_enable(mdss_ahb_clk);
+ if (!mdss_gdsc_enabled()) {
+ pr_err("%s: mdss GDSC is not enabled\n", __func__);
+ return -EPERM;
+ }
+
+ rc = clk_enable(mdss_ahb_clk);
+ if (rc) {
+ pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
/* Global Enable */
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
/* Power up power gen */
@@ -212,7 +260,7 @@
status, ((status & BIT(0)) == 1), max_reads, timeout_us)) {
pr_err("%s: hdmi phy pll status=%x failed to Lock\n",
__func__, status);
- hdmi_pll_disable();
+ hdmi_vco_disable(c);
clk_disable(mdss_ahb_clk);
return -EINVAL;
}
@@ -226,7 +274,7 @@
status, ((status & BIT(0)) == 1), max_reads, timeout_us)) {
pr_err("%s: hdmi phy status=%x failed to Lock\n",
__func__, status);
- hdmi_pll_disable();
+ hdmi_vco_disable(c);
clk_disable(mdss_ahb_clk);
return -EINVAL;
}
@@ -236,25 +284,173 @@
hdmi_pll_on = 1;
return 0;
-} /* hdmi_pll_enable */
+} /* hdmi_vco_enable */
-int hdmi_pll_set_rate(unsigned long rate)
+static inline struct hdmi_pll_vco_clk *to_hdmi_vco_clk(struct clk *clk)
+{
+ return container_of(clk, struct hdmi_pll_vco_clk, c);
+}
+
+static void hdmi_phy_pll_calculator(u32 vco_freq)
+{
+ u32 ref_clk = 19200000;
+ u32 sdm_mode = 1;
+ u32 ref_clk_multiplier = sdm_mode == 1 ? 2 : 1;
+ u32 int_ref_clk_freq = ref_clk * ref_clk_multiplier;
+ u32 fbclk_pre_div = 1;
+ u32 ssc_mode = 0;
+ u32 kvco = 270;
+ u32 vdd = 95;
+ u32 ten_power_six = 1000000;
+ u32 ssc_ds_ppm = ssc_mode ? 5000 : 0;
+ u32 sdm_res = 16;
+ u32 ssc_tri_step = 32;
+ u32 ssc_freq = 2;
+ u64 ssc_ds = vco_freq * ssc_ds_ppm;
+ u32 div_in_freq = vco_freq / fbclk_pre_div;
+ u64 dc_offset = (div_in_freq / int_ref_clk_freq - 1) *
+ ten_power_six * 10;
+ u32 ssc_kdiv = (int_ref_clk_freq / ssc_freq) -
+ ten_power_six;
+ u64 sdm_freq_seed;
+ u32 ssc_tri_inc;
+ u64 fb_div_n;
+
+ u32 val;
+
+ pr_debug("%s: vco_freq = %u\n", __func__, vco_freq);
+
+ do_div(ssc_ds, (u64)ten_power_six);
+
+ fb_div_n = (u64)div_in_freq * (u64)ten_power_six * 10;
+ do_div(fb_div_n, int_ref_clk_freq);
+
+ sdm_freq_seed = ((fb_div_n - dc_offset - ten_power_six * 10) *
+ (1 << sdm_res) * 10) + 5;
+ do_div(sdm_freq_seed, ((u64)ten_power_six * 100));
+
+ ssc_tri_inc = (u32)ssc_ds;
+ ssc_tri_inc = (ssc_tri_inc / int_ref_clk_freq) * (1 << 16) /
+ ssc_tri_step;
+
+ val = (ref_clk_multiplier == 2 ? 1 : 0) +
+ ((fbclk_pre_div == 2 ? 1 : 0) * 16);
+ pr_debug("%s: HDMI_UNI_PLL_REFCLK_CFG = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
+
+ REG_W(0x02, hdmi_phy_pll_base + HDMI_UNI_PLL_CHFPUMP_CFG);
+ REG_W(0x19, hdmi_phy_pll_base + HDMI_UNI_PLL_VCOLPF_CFG);
+ REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_VREG_CFG);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_PWRGEN_CFG);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
+ REG_W(0x0E, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFR_CFG);
+ REG_W(0x20, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC1_CFG);
+ REG_W(0x0D, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC2_CFG);
+
+ do_div(dc_offset, (u64)ten_power_six * 10);
+ val = sdm_mode == 0 ? 64 + dc_offset : 0;
+ pr_debug("%s: HDMI_UNI_PLL_SDM_CFG0 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG0);
+
+ val = 64 + dc_offset;
+ pr_debug("%s: HDMI_UNI_PLL_SDM_CFG1 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG1);
+
+ val = sdm_freq_seed & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_SDM_CFG2 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG2);
+
+ val = (sdm_freq_seed >> 8) & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_SDM_CFG3 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG3);
+
+ val = (sdm_freq_seed >> 16) & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_SDM_CFG4 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG4);
+
+ val = (ssc_mode == 0 ? 128 : 0) + (ssc_kdiv / ten_power_six);
+ pr_debug("%s: HDMI_UNI_PLL_SSC_CFG0 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SSC_CFG0);
+
+ val = ssc_tri_inc & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_SSC_CFG1 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SSC_CFG1);
+
+ val = (ssc_tri_inc >> 8) & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_SSC_CFG2 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SSC_CFG2);
+
+ pr_debug("%s: HDMI_UNI_PLL_SSC_CFG3 = 0x%x\n", __func__, ssc_tri_step);
+ REG_W(ssc_tri_step, hdmi_phy_pll_base + HDMI_UNI_PLL_SSC_CFG3);
+
+ REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
+ REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
+ REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
+ REG_W(0x0A, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG0);
+ REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG1);
+ REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG3);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG4);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG5);
+
+ val = (kvco * vdd * 10000) / 6;
+ val += 500000;
+ val /= ten_power_six;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG6 = 0x%x\n", __func__, val);
+ REG_W(val & 0xFF, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG6);
+
+ val = (kvco * vdd * 10000) / 6;
+ val -= ten_power_six;
+ val /= ten_power_six;
+ val = (val >> 8) & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG7 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG7);
+
+ val = (ref_clk * 5) / ten_power_six;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG8 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG8);
+
+ val = ((ref_clk * 5) / ten_power_six) >> 8;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG9 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG9);
+
+ vco_freq /= ten_power_six;
+ val = vco_freq & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG10 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG10);
+
+ val = vco_freq >> 8;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG11 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG11);
+} /* hdmi_phy_pll_calculator */
+
+static int hdmi_vco_set_rate(struct clk *c, unsigned long rate)
{
unsigned int set_power_dwn = 0;
+ int rc = 0;
+
+ struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c);
if (hdmi_pll_on) {
- hdmi_pll_disable();
+ hdmi_vco_disable(c);
set_power_dwn = 1;
}
- clk_enable(mdss_ahb_clk);
+ rc = mdss_ahb_clk_enable(1);
+ if (rc) {
+ pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
pr_debug("%s: rate=%ld\n", __func__, rate);
+
switch (rate) {
case 0:
- /* This case is needed for suspend/resume. */
- break;
+ break;
- case 25200000:
+ case 756000000:
/* 640x480p60 */
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
@@ -271,7 +467,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x03, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -299,7 +494,7 @@
udelay(200);
break;
- case 27000000:
+ case 810000000:
/* 576p50/576i50 case */
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
@@ -316,7 +511,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0X1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x03, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -344,7 +538,7 @@
udelay(200);
break;
- case 27030000:
+ case 810900000:
/* 480p60/480i60 case */
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
@@ -361,7 +555,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x03, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -388,7 +581,7 @@
REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
udelay(200);
break;
- case 65000000:
+ case 650000000:
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
@@ -404,7 +597,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -431,7 +623,7 @@
REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
udelay(200);
break;
- case 74250000:
+ case 742500000:
/*
* 720p60/720p50/1080i60/1080i50
* 1080p24/1080p30/1080p25 case
@@ -451,7 +643,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -479,7 +670,7 @@
udelay(200);
break;
- case 108000000:
+ case 1080000000:
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
@@ -495,7 +686,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -523,51 +713,7 @@
udelay(200);
break;
- case 148500000:
- REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
- REG_W(0x19, hdmi_phy_pll_base + HDMI_UNI_PLL_VCOLPF_CFG);
- REG_W(0x0E, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFR_CFG);
- REG_W(0x20, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC1_CFG);
- REG_W(0x0D, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC2_CFG);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG0);
- REG_W(0x52, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG1);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG2);
- REG_W(0x56, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG3);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG4);
- REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
- REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
- REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
- REG_W(0x60, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG8);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG9);
- REG_W(0xE6, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG10);
- REG_W(0x02, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG11);
- REG_W(0x1F, hdmi_phy_base + HDMI_PHY_PD_CTRL0);
- udelay(50);
-
- REG_W(0x0F, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
- REG_W(0x00, hdmi_phy_base + HDMI_PHY_PD_CTRL1);
- REG_W(0x10, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
- REG_W(0xDB, hdmi_phy_base + HDMI_PHY_ANA_CFG0);
- REG_W(0x43, hdmi_phy_base + HDMI_PHY_ANA_CFG1);
- REG_W(0x02, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
- REG_W(0x00, hdmi_phy_base + HDMI_PHY_ANA_CFG3);
- REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_VREG_CFG);
- REG_W(0xD0, hdmi_phy_base + HDMI_PHY_DCC_CFG0);
- REG_W(0x1A, hdmi_phy_base + HDMI_PHY_DCC_CFG1);
- REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG0);
- REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG1);
- REG_W(0x02, hdmi_phy_base + HDMI_PHY_TXCAL_CFG2);
- REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
- udelay(200);
- break;
-
- case 268500000:
+ case 1342500000:
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
@@ -583,7 +729,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -611,7 +756,7 @@
udelay(200);
break;
- case 297000000:
+ case 1485000000:
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
@@ -627,7 +772,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -656,40 +800,68 @@
break;
default:
- pr_err("%s: not supported rate=%ld\n", __func__, rate);
+ pr_debug("%s: Use pll settings calculator for rate=%ld\n",
+ __func__, rate);
+
+ REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
+ hdmi_phy_pll_calculator(rate);
+ REG_W(0x1F, hdmi_phy_base + HDMI_PHY_PD_CTRL0);
+ udelay(50);
+
+ REG_W(0x0F, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_PD_CTRL1);
+ REG_W(0x10, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+ REG_W(0xDB, hdmi_phy_base + HDMI_PHY_ANA_CFG0);
+ REG_W(0x43, hdmi_phy_base + HDMI_PHY_ANA_CFG1);
+
+ if (rate < 825000000) {
+ REG_W(0x01, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_ANA_CFG3);
+ } else if (rate >= 825000000 && rate < 1342500000) {
+ REG_W(0x05, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+ REG_W(0x03, hdmi_phy_base + HDMI_PHY_ANA_CFG3);
+ } else {
+ REG_W(0x06, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+ REG_W(0x03, hdmi_phy_base + HDMI_PHY_ANA_CFG3);
+ }
+
+ REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_VREG_CFG);
+ REG_W(0xD0, hdmi_phy_base + HDMI_PHY_DCC_CFG0);
+ REG_W(0x1A, hdmi_phy_base + HDMI_PHY_DCC_CFG1);
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG0);
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG1);
+
+ if (rate < 825000000)
+ REG_W(0x01, hdmi_phy_base + HDMI_PHY_TXCAL_CFG2);
+ else
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG2);
+
+ REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
+ REG_W(0x62, hdmi_phy_base + HDMI_PHY_BIST_PATN0);
+ REG_W(0x03, hdmi_phy_base + HDMI_PHY_BIST_PATN1);
+ REG_W(0x69, hdmi_phy_base + HDMI_PHY_BIST_PATN2);
+ REG_W(0x02, hdmi_phy_base + HDMI_PHY_BIST_PATN3);
+
+ udelay(200);
+
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_BIST_CFG1);
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_BIST_CFG0);
}
/* Make sure writes complete before disabling iface clock */
mb();
- clk_disable(mdss_ahb_clk);
+ mdss_ahb_clk_enable(0);
if (set_power_dwn)
- hdmi_pll_enable();
+ hdmi_vco_enable(c);
+
+ vco->rate = rate;
+ vco->rate_set = true;
return 0;
} /* hdmi_pll_set_rate */
-/* Auto PLL calibaration */
-int mdss_ahb_clk_enable(int enable)
-{
- int rc = 0;
-
- /* todo: Ideally, we should enable/disable GDSC whenever we are
- * attempting to enable/disable MDSS AHB clock.
- * For now, just return error if GDSC is not enabled.
- */
- if (!mdss_gdsc_enabled())
- return -EPERM;
-
- if (enable)
- rc = clk_prepare_enable(mdss_ahb_clk);
- else
- clk_disable_unprepare(mdss_ahb_clk);
-
- return rc;
-}
-
int set_byte_mux_sel(struct mux_clk *clk, int sel)
{
pr_debug("%s: byte mux set to %s mode\n", __func__,
@@ -2126,6 +2298,291 @@
},
};
+/* HDMI PLL DIV CLK */
+
+static unsigned long hdmi_vco_get_rate(struct clk *c)
+{
+ unsigned long freq = 0;
+
+ if (mdss_ahb_clk_enable(1)) {
+ pr_err("%s: Failed to enable mdss ahb clock\n", __func__);
+ return freq;
+ }
+
+ freq = DSS_REG_R(hdmi_phy_pll_base, HDMI_UNI_PLL_CAL_CFG11) << 8 |
+ DSS_REG_R(hdmi_phy_pll_base, HDMI_UNI_PLL_CAL_CFG10);
+
+ switch (freq) {
+ case 742:
+ freq = 742500000;
+ break;
+ case 810:
+ if (DSS_REG_R(hdmi_phy_pll_base, HDMI_UNI_PLL_SDM_CFG3) == 0x18)
+ freq = 810000000;
+ else
+ freq = 810900000;
+ break;
+ case 1342:
+ freq = 1342500000;
+ break;
+ default:
+ freq *= 1000000;
+ }
+
+ mdss_ahb_clk_enable(0);
+
+ return freq;
+}
+
+static long hdmi_vco_round_rate(struct clk *c, unsigned long rate)
+{
+ unsigned long rrate = rate;
+ struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c);
+
+ if (rate < vco->min_rate)
+ rrate = vco->min_rate;
+ if (rate > vco->max_rate)
+ rrate = vco->max_rate;
+
+ pr_debug("%s: rrate=%ld\n", __func__, rrate);
+
+ return rrate;
+}
+
+static int hdmi_vco_prepare(struct clk *c)
+{
+ struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c);
+ int ret = 0;
+
+ pr_debug("%s: rate=%ld\n", __func__, vco->rate);
+
+ if (!vco->rate_set && vco->rate)
+ ret = hdmi_vco_set_rate(c, vco->rate);
+
+ if (!ret)
+ ret = clk_prepare(mdss_ahb_clk);
+
+ return ret;
+}
+
+static void hdmi_vco_unprepare(struct clk *c)
+{
+ struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c);
+
+ vco->rate_set = false;
+
+ clk_unprepare(mdss_ahb_clk);
+}
+
+static int hdmi_pll_lock_status(void)
+{
+ u32 status;
+ int pll_locked = 0;
+ int rc;
+
+ rc = mdss_ahb_clk_enable(1);
+ if (rc) {
+ pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
+ __func__, rc);
+ return 0;
+ }
+ /* poll for PLL ready status */
+ if (readl_poll_timeout_noirq((hdmi_phy_base + HDMI_PHY_STATUS),
+ status, ((status & BIT(0)) == 1),
+ PLL_POLL_MAX_READS, PLL_POLL_TIMEOUT_US)) {
+ pr_debug("%s: HDMI PLL status=%x failed to Lock\n",
+ __func__, status);
+ pll_locked = 0;
+ } else {
+ pll_locked = 1;
+ }
+ mdss_ahb_clk_enable(0);
+
+ return pll_locked;
+}
+
+static enum handoff hdmi_vco_handoff(struct clk *c)
+{
+ enum handoff ret = HANDOFF_DISABLED_CLK;
+
+ if (hdmi_pll_lock_status()) {
+ c->rate = hdmi_vco_get_rate(c);
+ ret = HANDOFF_ENABLED_CLK;
+ }
+
+ pr_debug("%s: done, ret=%d\n", __func__, ret);
+ return ret;
+}
+
+static struct clk_ops hdmi_vco_clk_ops = {
+ .enable = hdmi_vco_enable,
+ .set_rate = hdmi_vco_set_rate,
+ .get_rate = hdmi_vco_get_rate,
+ .round_rate = hdmi_vco_round_rate,
+ .prepare = hdmi_vco_prepare,
+ .unprepare = hdmi_vco_unprepare,
+ .disable = hdmi_vco_disable,
+ .handoff = hdmi_vco_handoff,
+};
+
+static struct hdmi_pll_vco_clk hdmi_vco_clk = {
+ .min_rate = 600000000,
+ .max_rate = 1800000000,
+ .c = {
+ .dbg_name = "hdmi_vco_clk",
+ .ops = &hdmi_vco_clk_ops,
+ CLK_INIT(hdmi_vco_clk.c),
+ },
+};
+
+struct div_clk hdmipll_div1_clk = {
+ .data = {
+ .div = 1,
+ .min_div = 1,
+ .max_div = 1,
+ },
+ .c = {
+ .parent = &hdmi_vco_clk.c,
+ .dbg_name = "hdmipll_div1_clk",
+ .ops = &clk_ops_div,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(hdmipll_div1_clk.c),
+ },
+};
+
+struct div_clk hdmipll_div2_clk = {
+ .data = {
+ .div = 2,
+ .min_div = 2,
+ .max_div = 2,
+ },
+ .c = {
+ .parent = &hdmi_vco_clk.c,
+ .dbg_name = "hdmipll_div2_clk",
+ .ops = &clk_ops_div,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(hdmipll_div2_clk.c),
+ },
+};
+
+struct div_clk hdmipll_div4_clk = {
+ .data = {
+ .div = 4,
+ .min_div = 4,
+ .max_div = 4,
+ },
+ .c = {
+ .parent = &hdmi_vco_clk.c,
+ .dbg_name = "hdmipll_div4_clk",
+ .ops = &clk_ops_div,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(hdmipll_div4_clk.c),
+ },
+};
+
+struct div_clk hdmipll_div6_clk = {
+ .data = {
+ .div = 6,
+ .min_div = 6,
+ .max_div = 6,
+ },
+ .c = {
+ .parent = &hdmi_vco_clk.c,
+ .dbg_name = "hdmipll_div6_clk",
+ .ops = &clk_ops_div,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(hdmipll_div6_clk.c),
+ },
+};
+
+static int hdmipll_set_mux_sel(struct mux_clk *clk, int mux_sel)
+{
+ int rc;
+
+ if (!mdss_gdsc_enabled()) {
+ pr_err("%s: mdss GDSC is not enabled\n", __func__);
+ return -EPERM;
+ }
+
+ rc = clk_enable(mdss_ahb_clk);
+ if (rc) {
+ pr_err("%s: Failed to enable mdss ahb clock\n", __func__);
+ return rc;
+ }
+
+ pr_debug("%s: mux_sel=%d\n", __func__, mux_sel);
+ DSS_REG_W(hdmi_phy_pll_base, HDMI_UNI_PLL_POSTDIV1_CFG, mux_sel);
+
+ clk_disable(mdss_ahb_clk);
+
+ return 0;
+}
+
+static int hdmipll_get_mux_sel(struct mux_clk *clk)
+{
+ int mux_sel = 0;
+
+ if (mdss_ahb_clk_enable(1)) {
+ pr_err("%s: Failed to enable mdss ahb clock\n", __func__);
+ return mux_sel;
+ }
+
+ mux_sel = DSS_REG_R(hdmi_phy_pll_base, HDMI_UNI_PLL_POSTDIV1_CFG);
+ mux_sel &= 0x03;
+ pr_debug("%s: mux_sel=%d\n", __func__, mux_sel);
+
+ mdss_ahb_clk_enable(0);
+
+ return mux_sel;
+}
+
+static struct clk_mux_ops hdmipll_mux_ops = {
+ .set_mux_sel = hdmipll_set_mux_sel,
+ .get_mux_sel = hdmipll_get_mux_sel,
+};
+
+static struct clk_ops hdmi_mux_ops;
+
+static int hdmi_mux_prepare(struct clk *c)
+{
+ int ret = 0;
+
+ if (c && c->ops && c->ops->set_rate)
+ ret = c->ops->set_rate(c, c->rate);
+
+ return ret;
+}
+
+static struct mux_clk hdmipll_mux_clk = {
+ MUX_SRC_LIST(
+ { &hdmipll_div1_clk.c, 0 },
+ { &hdmipll_div2_clk.c, 1 },
+ { &hdmipll_div4_clk.c, 2 },
+ { &hdmipll_div6_clk.c, 3 },
+ ),
+ .ops = &hdmipll_mux_ops,
+ .c = {
+ .parent = &hdmipll_div1_clk.c,
+ .dbg_name = "hdmipll_mux_clk",
+ .ops = &hdmi_mux_ops,
+ CLK_INIT(hdmipll_mux_clk.c),
+ },
+};
+
+struct div_clk hdmipll_clk_src = {
+ .data = {
+ .div = 5,
+ .min_div = 5,
+ .max_div = 5,
+ },
+ .c = {
+ .parent = &hdmipll_mux_clk.c,
+ .dbg_name = "hdmipll_clk_src",
+ .ops = &clk_ops_div,
+ CLK_INIT(hdmipll_clk_src.c),
+ },
+};
+
void __init mdss_clk_ctrl_pre_init(struct clk *ahb_clk)
{
BUG_ON(ahb_clk == NULL);
@@ -2170,4 +2627,7 @@
edp_pixel_clk_ops = clk_ops_slave_div;
edp_pixel_clk_ops.prepare = div_prepare;
+
+ hdmi_mux_ops = clk_ops_gen_mux;
+ hdmi_mux_ops.prepare = hdmi_mux_prepare;
}
diff --git a/arch/arm/mach-msm/clock-mdss-8974.h b/arch/arm/mach-msm/clock-mdss-8974.h
index da24b0d..f9286f1 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.h
+++ b/arch/arm/mach-msm/clock-mdss-8974.h
@@ -22,9 +22,15 @@
void mdss_clk_ctrl_pre_init(struct clk *ahb_clk);
void mdss_clk_ctrl_post_init(void);
-int hdmi_pll_enable(void);
-void hdmi_pll_disable(void);
-int hdmi_pll_set_rate(unsigned long rate);
+
+struct hdmi_pll_vco_clk {
+ unsigned long rate; /* current vco rate */
+ unsigned long min_rate; /* min vco rate */
+ unsigned long max_rate; /* max vco rate */
+ bool rate_set;
+
+ struct clk c;
+};
struct edp_pll_vco_clk {
unsigned long ref_clk_rate;
@@ -67,5 +73,6 @@
extern struct div_clk edp_mainlink_clk_src;
extern struct div_clk edp_pixel_clk_src;
+extern struct div_clk hdmipll_clk_src;
#endif
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index 1cf2e41..fa132fa 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -25,7 +25,6 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
-#include <linux/cpufreq.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/cpr-regulator.h>
@@ -33,6 +32,10 @@
/* Register Offsets for RB-CPR and Bit Definitions */
+/* RBCPR Version Register */
+#define REG_RBCPR_VERSION 0
+#define RBCPR_VER_2 0x02
+
/* RBCPR Gate Count and Target Registers */
#define REG_RBCPR_GCNT_TARGET(n) (0x60 + 4 * n)
@@ -131,14 +134,14 @@
#define BYTES_PER_FUSE_ROW 8
+#define FLAGS_IGNORE_1ST_IRQ_STATUS BIT(0)
#define FLAGS_SET_MIN_VOLTAGE BIT(1)
#define FLAGS_UPLIFT_QUOT_VOLT BIT(2)
-#define FLAGS_QUOT_ADJUST_WITH_FREQ BIT(3)
-struct cpufreq_mapping_info {
- int freq;
+struct quot_adjust_info {
+ int speed_bin;
+ int virtual_corner;
int quot_adjust;
- int corner;
};
enum voltage_change_dir {
@@ -160,7 +163,7 @@
/* Process voltage parameters */
u32 pvs_init_v[CPR_PVS_EFUSE_BINS_MAX];
- u32 pvs_corner_v[NUM_APC_PVS][CPR_CORNER_MAX];
+ u32 pvs_corner_v[NUM_APC_PVS][CPR_FUSE_CORNER_MAX];
/* Process voltage variables */
u32 pvs_bin;
u32 process;
@@ -178,9 +181,8 @@
u64 cpr_fuse_bits;
bool cpr_fuse_disable;
bool cpr_fuse_local;
- int cpr_fuse_target_quot[CPR_CORNER_MAX];
- int cpr_fuse_original_quot[CPR_CORNER_MAX];
- int cpr_fuse_ro_sel[CPR_CORNER_MAX];
+ int cpr_fuse_target_quot[CPR_FUSE_CORNER_MAX];
+ int cpr_fuse_ro_sel[CPR_FUSE_CORNER_MAX];
int gcnt;
unsigned int cpr_irq;
@@ -188,13 +190,13 @@
phys_addr_t rbcpr_clk_addr;
struct mutex cpr_mutex;
- int ceiling_volt[CPR_CORNER_MAX];
- int floor_volt[CPR_CORNER_MAX];
- int last_volt[CPR_CORNER_MAX];
+ int ceiling_volt[CPR_FUSE_CORNER_MAX];
+ int floor_volt[CPR_FUSE_CORNER_MAX];
+ int *last_volt;
int step_volt;
- int save_ctl[CPR_CORNER_MAX];
- int save_irq[CPR_CORNER_MAX];
+ int *save_ctl;
+ int *save_irq;
u32 save_regs[CPR_NUM_SAVE_REGS];
u32 save_reg_val[CPR_NUM_SAVE_REGS];
@@ -214,10 +216,9 @@
u32 vdd_apc_step_up_limit;
u32 vdd_apc_step_down_limit;
u32 flags;
- struct notifier_block freq_transition;
- unsigned int freq;
- struct cpufreq_mapping_info *cpufreq_mapping;
- u32 cpufreq_mapping_size;
+ int *corner_map;
+ u32 num_corners;
+ int *quot_adjust;
};
#define CPR_DEBUG_MASK_IRQ BIT(0)
@@ -280,28 +281,6 @@
return efuse_bits;
}
-static int cpr_get_freq_corner(struct cpr_regulator *cpr_vreg, int freq)
-{
- int i;
-
- for (i = 0; i < cpr_vreg->cpufreq_mapping_size; i++) {
- if (freq == cpr_vreg->cpufreq_mapping[i].freq)
- return cpr_vreg->cpufreq_mapping[i].corner;
- }
-
- return -EINVAL;
-}
-
-static int cpr_get_freq_quot_adjust(struct cpr_regulator *cpr_vreg, int freq)
-{
- int i;
-
- for (i = 0; i < cpr_vreg->cpufreq_mapping_size; i++) {
- if (freq == cpr_vreg->cpufreq_mapping[i].freq)
- return cpr_vreg->cpufreq_mapping[i].quot_adjust;
- }
- return 0;
-}
static bool cpr_is_allowed(struct cpr_regulator *cpr_vreg)
{
@@ -362,9 +341,11 @@
static void cpr_ctl_enable(struct cpr_regulator *cpr_vreg, int corner)
{
u32 val;
+ int fuse_corner = cpr_vreg->corner_map[corner];
if (cpr_is_allowed(cpr_vreg) &&
- (cpr_vreg->ceiling_volt[corner] > cpr_vreg->floor_volt[corner]))
+ (cpr_vreg->ceiling_volt[fuse_corner] >
+ cpr_vreg->floor_volt[fuse_corner]))
val = RBCPR_CTL_LOOP_EN;
else
val = 0;
@@ -376,13 +357,6 @@
cpr_ctl_modify(cpr_vreg, RBCPR_CTL_LOOP_EN, 0);
}
-static bool cpr_ctl_is_enabled(struct cpr_regulator *cpr_vreg)
-{
- u32 val;
- val = cpr_read(cpr_vreg, REG_RBCPR_CTL);
- return ((val & RBCPR_CTL_LOOP_EN) == RBCPR_CTL_LOOP_EN);
-}
-
static void cpr_regs_save(struct cpr_regulator *cpr_vreg)
{
int i, offset;
@@ -415,16 +389,12 @@
static void cpr_corner_restore(struct cpr_regulator *cpr_vreg, int corner)
{
u32 gcnt, ctl, irq, ro_sel;
- int adjust;
+ int fuse_corner = cpr_vreg->corner_map[corner];
- if (cpr_vreg->flags & FLAGS_QUOT_ADJUST_WITH_FREQ) {
- adjust = cpr_get_freq_quot_adjust(cpr_vreg, cpr_vreg->freq);
- cpr_vreg->cpr_fuse_target_quot[corner] =
- cpr_vreg->cpr_fuse_original_quot[corner] - adjust;
- }
+ ro_sel = cpr_vreg->cpr_fuse_ro_sel[fuse_corner];
+ gcnt = cpr_vreg->gcnt | (cpr_vreg->cpr_fuse_target_quot[fuse_corner] -
+ cpr_vreg->quot_adjust[corner]);
- ro_sel = cpr_vreg->cpr_fuse_ro_sel[corner];
- gcnt = cpr_vreg->gcnt | cpr_vreg->cpr_fuse_target_quot[corner];
cpr_write(cpr_vreg, REG_RBCPR_GCNT_TARGET(ro_sel), gcnt);
ctl = cpr_vreg->save_ctl[corner];
cpr_write(cpr_vreg, REG_RBCPR_CTL, ctl);
@@ -462,8 +432,9 @@
goto _exit;
}
- cpr_debug("%d -> %d [corner=%d]\n",
- old_cpr_enable, cpr_enable, the_cpr->corner);
+ cpr_debug("%d -> %d [corner=%d, fuse_corner=%d]\n",
+ old_cpr_enable, cpr_enable, the_cpr->corner,
+ the_cpr->corner_map[the_cpr->corner]);
if (the_cpr->cpr_fuse_disable) {
/* Already disabled */
@@ -509,17 +480,18 @@
static int cpr_mx_get(struct cpr_regulator *cpr_vreg, int corner, int apc_volt)
{
int vdd_mx;
+ int fuse_corner = cpr_vreg->corner_map[corner];
switch (cpr_vreg->vdd_mx_vmin_method) {
case VDD_MX_VMIN_APC:
vdd_mx = apc_volt;
break;
case VDD_MX_VMIN_APC_CORNER_CEILING:
- vdd_mx = cpr_vreg->ceiling_volt[corner];
+ vdd_mx = cpr_vreg->ceiling_volt[fuse_corner];
break;
case VDD_MX_VMIN_APC_SLOW_CORNER_CEILING:
vdd_mx = cpr_vreg->pvs_corner_v[APC_PVS_SLOW]
- [CPR_CORNER_TURBO];
+ [CPR_FUSE_CORNER_TURBO];
break;
case VDD_MX_VMIN_MX_VMAX:
vdd_mx = cpr_vreg->vdd_mx_vmax;
@@ -536,15 +508,19 @@
int vdd_mx_vmin)
{
int rc;
+ int fuse_corner = cpr_vreg->corner_map[corner];
rc = regulator_set_voltage(cpr_vreg->vdd_mx, vdd_mx_vmin,
cpr_vreg->vdd_mx_vmax);
- cpr_debug("[corner:%d] %d uV\n", corner, vdd_mx_vmin);
- if (!rc)
+ cpr_debug("[corner:%d, fuse_corner:%d] %d uV\n", corner,
+ fuse_corner, vdd_mx_vmin);
+
+ if (!rc) {
cpr_vreg->vdd_mx_vmin = vdd_mx_vmin;
- else
- pr_err("set: vdd_mx [%d] = %d uV: rc=%d\n",
- corner, vdd_mx_vmin, rc);
+ } else {
+ pr_err("set: vdd_mx [corner:%d, fuse_corner:%d] = %d uV failed: rc=%d\n",
+ corner, fuse_corner, vdd_mx_vmin, rc);
+ }
return rc;
}
@@ -582,9 +558,11 @@
enum voltage_change_dir dir)
{
u32 reg_val, error_steps, reg_mask;
- int last_volt, new_volt, corner;
+ int last_volt, new_volt, corner, fuse_corner;
+ u32 gcnt, quot;
corner = cpr_vreg->corner;
+ fuse_corner = cpr_vreg->corner_map[corner];
reg_val = cpr_read(cpr_vreg, REG_RBCPR_RESULT_0);
@@ -592,18 +570,27 @@
& RBCPR_RESULT0_ERROR_STEPS_MASK;
last_volt = cpr_vreg->last_volt[corner];
- cpr_debug_irq("last_volt[corner:%d] = %d uV\n", corner, last_volt);
+ cpr_debug_irq("last_volt[corner:%d, fuse_corner:%d] = %d uV\n", corner,
+ fuse_corner, last_volt);
+
+ gcnt = cpr_read(cpr_vreg, REG_RBCPR_GCNT_TARGET
+ (cpr_vreg->cpr_fuse_ro_sel[fuse_corner]));
+ quot = gcnt & ((1 << RBCPR_GCNT_TARGET_GCNT_SHIFT) - 1);
if (dir == UP) {
cpr_debug_irq("Up: cpr status = 0x%08x (error_steps=%d)\n",
reg_val, error_steps);
- if (last_volt >= cpr_vreg->ceiling_volt[corner]) {
- cpr_debug_irq("[corn:%d] @ ceiling: %d >= %d: NACK\n",
- corner, last_volt,
- cpr_vreg->ceiling_volt[corner]);
+ if (last_volt >= cpr_vreg->ceiling_volt[fuse_corner]) {
+ cpr_debug_irq(
+ "[corn:%d, fuse_corn:%d] @ ceiling: %d >= %d: NACK\n",
+ corner, fuse_corner, last_volt,
+ cpr_vreg->ceiling_volt[fuse_corner]);
cpr_irq_clr_nack(cpr_vreg);
+ cpr_debug_irq("gcnt = 0x%08x (quot = %d)\n", gcnt,
+ quot);
+
/* Maximize the UP threshold */
reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK <<
RBCPR_CTL_UP_THRESHOLD_SHIFT;
@@ -621,11 +608,12 @@
/* Calculate new voltage */
new_volt = last_volt + (error_steps * cpr_vreg->step_volt);
- if (new_volt > cpr_vreg->ceiling_volt[corner]) {
+ if (new_volt > cpr_vreg->ceiling_volt[fuse_corner]) {
cpr_debug_irq("new_volt(%d) >= ceiling(%d): Clamp\n",
new_volt,
- cpr_vreg->ceiling_volt[corner]);
- new_volt = cpr_vreg->ceiling_volt[corner];
+ cpr_vreg->ceiling_volt[fuse_corner]);
+
+ new_volt = cpr_vreg->ceiling_volt[fuse_corner];
}
if (cpr_scale_voltage(cpr_vreg, corner, new_volt, dir)) {
@@ -650,22 +638,26 @@
/* Ack */
cpr_irq_clr_ack(cpr_vreg);
- cpr_debug_irq("UP: -> new_volt[corner:%d] = %d uV\n",
- corner, new_volt);
+ cpr_debug_irq(
+ "UP: -> new_volt[corner:%d, fuse_corner:%d] = %d uV\n",
+ corner, fuse_corner, new_volt);
} else if (dir == DOWN) {
cpr_debug_irq("Down: cpr status = 0x%08x (error_steps=%d)\n",
reg_val, error_steps);
- if (last_volt <= cpr_vreg->floor_volt[corner]) {
- cpr_debug_irq("[corn:%d] @ floor: %d <= %d: NACK\n",
- corner, last_volt,
- cpr_vreg->floor_volt[corner]);
+ if (last_volt <= cpr_vreg->floor_volt[fuse_corner]) {
+ cpr_debug_irq(
+ "[corn:%d, fuse_corner:%d] @ floor: %d <= %d: NACK\n",
+ corner, fuse_corner, last_volt,
+ cpr_vreg->floor_volt[fuse_corner]);
cpr_irq_clr_nack(cpr_vreg);
/* Maximize the DOWN threshold */
reg_mask = RBCPR_CTL_DN_THRESHOLD_MASK <<
RBCPR_CTL_DN_THRESHOLD_SHIFT;
reg_val = reg_mask;
+ cpr_debug_irq("gcnt = 0x%08x (quot = %d)\n", gcnt,
+ quot);
/* Enable auto nack down */
reg_mask |= RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
@@ -688,11 +680,11 @@
/* Calculte new voltage */
new_volt = last_volt - (error_steps * cpr_vreg->step_volt);
- if (new_volt < cpr_vreg->floor_volt[corner]) {
+ if (new_volt < cpr_vreg->floor_volt[fuse_corner]) {
cpr_debug_irq("new_volt(%d) < floor(%d): Clamp\n",
new_volt,
- cpr_vreg->floor_volt[corner]);
- new_volt = cpr_vreg->floor_volt[corner];
+ cpr_vreg->floor_volt[fuse_corner]);
+ new_volt = cpr_vreg->floor_volt[fuse_corner];
}
if (cpr_scale_voltage(cpr_vreg, corner, new_volt, dir)) {
@@ -711,8 +703,9 @@
/* Ack */
cpr_irq_clr_ack(cpr_vreg);
- cpr_debug_irq("DOWN: -> new_volt[corner:%d] = %d uV\n",
- corner, new_volt);
+ cpr_debug_irq(
+ "DOWN: -> new_volt[corner:%d, fuse_corner:%d] = %d uV\n",
+ corner, fuse_corner, new_volt);
}
}
@@ -724,6 +717,9 @@
mutex_lock(&cpr_vreg->cpr_mutex);
reg_val = cpr_read(cpr_vreg, REG_RBIF_IRQ_STATUS);
+ if (cpr_vreg->flags & FLAGS_IGNORE_1ST_IRQ_STATUS)
+ reg_val = cpr_read(cpr_vreg, REG_RBIF_IRQ_STATUS);
+
cpr_debug_irq("IRQ_STATUS = 0x%02X\n", reg_val);
if (!cpr_is_allowed(cpr_vreg)) {
@@ -831,6 +827,7 @@
int rc;
int new_volt;
enum voltage_change_dir change_dir = NO_CHANGE;
+ int fuse_corner = cpr_vreg->corner_map[corner];
mutex_lock(&cpr_vreg->cpr_mutex);
@@ -838,10 +835,12 @@
cpr_ctl_disable(cpr_vreg);
new_volt = cpr_vreg->last_volt[corner];
} else {
- new_volt = cpr_vreg->pvs_corner_v[cpr_vreg->process][corner];
+ new_volt = cpr_vreg->pvs_corner_v
+ [cpr_vreg->process][fuse_corner];
}
- cpr_debug("[corner:%d] = %d uV\n", corner, new_volt);
+ cpr_debug("[corner:%d, fuse_corner:%d] = %d uV\n", corner, fuse_corner,
+ new_volt);
if (corner > cpr_vreg->corner)
change_dir = UP;
@@ -934,11 +933,13 @@
#define cpr_regulator_resume NULL
#endif
-static int __devinit cpr_config(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_config(struct cpr_regulator *cpr_vreg,
+ struct device *dev)
{
int i;
u32 val, gcnt, reg;
void __iomem *rbcpr_clk;
+ int size;
/* Use 19.2 MHz clock for CPR. */
rbcpr_clk = ioremap(cpr_vreg->rbcpr_clk_addr, 4);
@@ -1009,17 +1010,26 @@
cpr_vreg->save_regs[5] = REG_RBIF_IRQ_EN(cpr_vreg->irq_line);
cpr_vreg->save_regs[6] = REG_RBCPR_CTL;
cpr_vreg->save_regs[7] = REG_RBCPR_GCNT_TARGET
- (cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_SVS]);
+ (cpr_vreg->cpr_fuse_ro_sel[CPR_FUSE_CORNER_SVS]);
cpr_vreg->save_regs[8] = REG_RBCPR_GCNT_TARGET
- (cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_NORMAL]);
+ (cpr_vreg->cpr_fuse_ro_sel[CPR_FUSE_CORNER_NORMAL]);
cpr_vreg->save_regs[9] = REG_RBCPR_GCNT_TARGET
- (cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_TURBO]);
+ (cpr_vreg->cpr_fuse_ro_sel[CPR_FUSE_CORNER_TURBO]);
cpr_irq_set(cpr_vreg, CPR_INT_DEFAULT);
- cpr_corner_save(cpr_vreg, CPR_CORNER_SVS);
- cpr_corner_save(cpr_vreg, CPR_CORNER_NORMAL);
- cpr_corner_save(cpr_vreg, CPR_CORNER_TURBO);
+ val = cpr_read(cpr_vreg, REG_RBCPR_VERSION);
+ if (val <= RBCPR_VER_2)
+ cpr_vreg->flags |= FLAGS_IGNORE_1ST_IRQ_STATUS;
+
+ size = cpr_vreg->num_corners + 1;
+ cpr_vreg->save_ctl = devm_kzalloc(dev, sizeof(int) * size, GFP_KERNEL);
+ cpr_vreg->save_irq = devm_kzalloc(dev, sizeof(int) * size, GFP_KERNEL);
+ if (!cpr_vreg->save_ctl || !cpr_vreg->save_irq)
+ return -ENOMEM;
+
+ for (i = 1; i < size; i++)
+ cpr_corner_save(cpr_vreg, i);
return 0;
}
@@ -1135,16 +1145,18 @@
init_v = cpr_vreg->pvs_init_v[cpr_vreg->pvs_bin];
for (process = NUM_APC_PVS - 1; process > APC_PVS_NO; process--) {
- if (init_v <= cpr_vreg->pvs_corner_v[process][CPR_CORNER_TURBO])
+ if (init_v <= cpr_vreg->pvs_corner_v
+ [process][CPR_FUSE_CORNER_TURBO])
break;
}
if (process == APC_PVS_NO) {
process = APC_PVS_SLOW;
- cpr_vreg->pvs_corner_v[process][CPR_CORNER_TURBO] = init_v;
+ cpr_vreg->pvs_corner_v[process][CPR_FUSE_CORNER_TURBO] = init_v;
cpr_vreg->ceiling_max = init_v;
} else if (process == APC_PVS_FAST &&
- init_v < cpr_vreg->pvs_corner_v[APC_PVS_FAST][CPR_CORNER_SVS]) {
+ init_v < cpr_vreg->pvs_corner_v
+ [APC_PVS_FAST][CPR_FUSE_CORNER_SVS]) {
process = APC_PVS_SLOW;
}
@@ -1152,7 +1164,7 @@
pvs_fuse[0], efuse_bits, pvs_fuse[2],
cpr_vreg->pvs_bin, process);
pr_info("pvs initial turbo voltage_= from %u to %u\n",
- init_v, cpr_vreg->pvs_corner_v[process][CPR_CORNER_TURBO]);
+ init_v, cpr_vreg->pvs_corner_v[process][CPR_FUSE_CORNER_TURBO]);
cpr_vreg->process = process;
@@ -1245,22 +1257,68 @@
pr_err("cpr-uplift-quotient is missing: %d", rc);
return rc;
}
- for (i = CPR_CORNER_SVS; i < CPR_CORNER_MAX; i++)
+ for (i = CPR_FUSE_CORNER_SVS; i < CPR_FUSE_CORNER_MAX; i++)
cpr_vreg->cpr_fuse_target_quot[i] += delta_quot[i-1];
return rc;
}
-static int cpr_get_of_cprfreq_mappings(struct cpr_regulator *cpr_vreg,
+static int cpr_get_of_corner_mappings(struct cpr_regulator *cpr_vreg,
struct device *dev)
{
int rc = 0;
- int i, j, size, stripe_size, length;
+ int i, size, stripe_size;
struct property *prop;
u32 *tmp;
+ bool corners_mapped;
+
+ prop = of_find_property(dev->of_node, "qti,cpr-corner-map", NULL);
+
+ if (prop) {
+ size = prop->length / sizeof(u32);
+ corners_mapped = true;
+ } else {
+ size = CPR_FUSE_CORNER_MAX - 1;
+ corners_mapped = false;
+ }
+
+ cpr_vreg->corner_map = devm_kzalloc(dev, sizeof(int) * (size + 1),
+ GFP_KERNEL);
+ if (!cpr_vreg->corner_map) {
+ pr_err("Can't allocate cpr_vreg->corner_map memory\n");
+ return -ENOMEM;
+ }
+ cpr_vreg->num_corners = size;
+
+ if (!corners_mapped) {
+ for (i = CPR_FUSE_CORNER_SVS; i < CPR_FUSE_CORNER_MAX; i++)
+ cpr_vreg->corner_map[i] = i;
+ } else {
+ rc = of_property_read_u32_array(dev->of_node,
+ "qti,cpr-corner-map", &cpr_vreg->corner_map[1], size);
+
+ if (rc) {
+ pr_err("qti,cpr-corner-map missing, rc = %d", rc);
+ return rc;
+ }
+ }
+
+ cpr_vreg->quot_adjust = devm_kzalloc(dev,
+ sizeof(int) * (cpr_vreg->num_corners + 1),
+ GFP_KERNEL);
+ if (!cpr_vreg->quot_adjust) {
+ pr_err("Can't allocate cpr_vreg->quot_adjust memory\n");
+ return -ENOMEM;
+ }
prop = of_find_property(dev->of_node, "qti,cpr-quot-adjust-table",
NULL);
+
if (prop) {
+ if (!corners_mapped) {
+ pr_err("qti,cpr-corner-map missing\n");
+ return -EINVAL;
+ }
+
size = prop->length / sizeof(u32);
tmp = kzalloc(sizeof(u32) * size, GFP_KERNEL);
if (!tmp)
@@ -1275,51 +1333,33 @@
return rc;
}
- length = 0;
- stripe_size = 1 + sizeof(struct cpufreq_mapping_info) /
- sizeof(int);
- for (i = 0; i < size; i += stripe_size) {
- if (tmp[i] == cpr_vreg->speed_bin)
- length++;
- }
- if (i != size) {
- pr_err("qti,cpr-quot-adjust-table data is not correct\n");
+ stripe_size = sizeof(struct quot_adjust_info) / sizeof(int);
+
+ if ((size % stripe_size) != 0) {
+ pr_err("qti,cpr-quot-adjust-table data is not correct");
kfree(tmp);
return -EINVAL;
}
- cpr_vreg->cpufreq_mapping_size = length;
- if (length) {
- cpr_vreg->cpufreq_mapping = devm_kzalloc(dev,
- sizeof(struct cpufreq_mapping_info) * length,
- GFP_KERNEL);
-
- if (!cpr_vreg->cpufreq_mapping) {
- kfree(tmp);
- return -ENOMEM;
- }
-
- cpr_vreg->flags |= FLAGS_QUOT_ADJUST_WITH_FREQ;
-
- for (i = 0, j = 0; i < size; i += stripe_size) {
- if (tmp[i] == cpr_vreg->speed_bin) {
- cpr_vreg->cpufreq_mapping[j].freq =
- tmp[i+1];
- cpr_vreg->cpufreq_mapping[j].quot_adjust
- = tmp[i+2];
- cpr_vreg->cpufreq_mapping[j].corner =
- tmp[i+3];
- ++j;
+ for (i = 0; i < size; i += stripe_size) {
+ if (tmp[i] == cpr_vreg->speed_bin) {
+ if (tmp[i + 1] >= 1 &&
+ tmp[i + 1] <=
+ cpr_vreg->num_corners) {
+ cpr_vreg->quot_adjust[tmp[i + 1]] =
+ tmp[i + 2];
+ } else {
+ pr_err("qti,cpr-quot-adjust-table data is not correct");
+ kfree(tmp);
+ return -EINVAL;
}
-
}
-
}
kfree(tmp);
}
- return rc;
+ return 0;
}
static int __devinit cpr_init_cpr_efuse(struct platform_device *pdev,
@@ -1332,8 +1372,8 @@
char *targ_quot_str, *ro_sel_str;
u32 cpr_fuse_row[2];
u32 bp_cpr_disable, bp_scheme;
- int bp_target_quot[CPR_CORNER_MAX];
- int bp_ro_sel[CPR_CORNER_MAX];
+ int bp_target_quot[CPR_FUSE_CORNER_MAX];
+ int bp_ro_sel[CPR_FUSE_CORNER_MAX];
u32 ro_sel, val;
u64 fuse_bits, fuse_bits_2;
@@ -1364,8 +1404,8 @@
rc = of_property_read_u32_array(of_node,
targ_quot_str,
- &bp_target_quot[CPR_CORNER_SVS],
- CPR_CORNER_MAX - CPR_CORNER_SVS);
+ &bp_target_quot[CPR_FUSE_CORNER_SVS],
+ CPR_FUSE_CORNER_MAX - CPR_FUSE_CORNER_SVS);
if (rc < 0) {
pr_err("missing %s: rc=%d\n", targ_quot_str, rc);
return rc;
@@ -1373,8 +1413,8 @@
rc = of_property_read_u32_array(of_node,
ro_sel_str,
- &bp_ro_sel[CPR_CORNER_SVS],
- CPR_CORNER_MAX - CPR_CORNER_SVS);
+ &bp_ro_sel[CPR_FUSE_CORNER_SVS],
+ CPR_FUSE_CORNER_MAX - CPR_FUSE_CORNER_SVS);
if (rc < 0) {
pr_err("missing %s: rc=%d\n", ro_sel_str, rc);
return rc;
@@ -1432,7 +1472,7 @@
pr_info("disable = %d, local = %d\n",
cpr_vreg->cpr_fuse_disable, cpr_vreg->cpr_fuse_local);
- for (i = CPR_CORNER_SVS; i < CPR_CORNER_MAX; i++) {
+ for (i = CPR_FUSE_CORNER_SVS; i < CPR_FUSE_CORNER_MAX; i++) {
ro_sel = (fuse_bits >> bp_ro_sel[i])
& CPR_FUSE_RO_SEL_BITS_MASK;
val = (fuse_bits >> bp_target_quot[i])
@@ -1445,18 +1485,13 @@
if (cpr_vreg->flags & FLAGS_UPLIFT_QUOT_VOLT) {
cpr_voltage_uplift_wa_inc_quot(cpr_vreg, of_node);
- for (i = CPR_CORNER_SVS; i < CPR_CORNER_MAX; i++) {
+ for (i = CPR_FUSE_CORNER_SVS; i < CPR_FUSE_CORNER_MAX; i++) {
pr_info("Corner[%d]: uplifted target quot = %d\n",
i, cpr_vreg->cpr_fuse_target_quot[i]);
}
}
- for (i = CPR_CORNER_SVS; i < CPR_CORNER_MAX; i++) {
- cpr_vreg->cpr_fuse_original_quot[i] =
- cpr_vreg->cpr_fuse_target_quot[i];
- }
-
- rc = cpr_get_of_cprfreq_mappings(cpr_vreg, &pdev->dev);
+ rc = cpr_get_of_corner_mappings(cpr_vreg, &pdev->dev);
if (rc)
return rc;
@@ -1469,10 +1504,12 @@
int *quot = cpr_vreg->cpr_fuse_target_quot;
bool valid_fuse = true;
- if ((quot[CPR_CORNER_TURBO] > quot[CPR_CORNER_NORMAL]) &&
- (quot[CPR_CORNER_NORMAL] > quot[CPR_CORNER_SVS])) {
- if ((quot[CPR_CORNER_TURBO] -
- quot[CPR_CORNER_NORMAL])
+ if ((quot[CPR_FUSE_CORNER_TURBO] >
+ quot[CPR_FUSE_CORNER_NORMAL]) &&
+ (quot[CPR_FUSE_CORNER_NORMAL] >
+ quot[CPR_FUSE_CORNER_SVS])) {
+ if ((quot[CPR_FUSE_CORNER_TURBO] -
+ quot[CPR_FUSE_CORNER_NORMAL])
<= CPR_FUSE_MIN_QUOT_DIFF)
valid_fuse = false;
} else {
@@ -1488,18 +1525,27 @@
return 0;
}
-static int __devinit cpr_init_cpr_voltages(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_init_cpr_voltages(struct cpr_regulator *cpr_vreg,
+ struct device *dev)
{
int i;
+ int size = cpr_vreg->num_corners + 1;
+
+ cpr_vreg->last_volt = devm_kzalloc(dev, sizeof(int) * size, GFP_KERNEL);
+ if (!cpr_vreg->last_volt)
+ return -EINVAL;
/* Construct CPR voltage limits */
- for (i = CPR_CORNER_SVS; i < CPR_CORNER_MAX; i++) {
+ for (i = CPR_FUSE_CORNER_SVS; i < CPR_FUSE_CORNER_MAX; i++) {
cpr_vreg->floor_volt[i] =
cpr_vreg->pvs_corner_v[APC_PVS_FAST][i];
cpr_vreg->ceiling_volt[i] =
cpr_vreg->pvs_corner_v[APC_PVS_SLOW][i];
- cpr_vreg->last_volt[i] =
- cpr_vreg->pvs_corner_v[cpr_vreg->process][i];
+ }
+
+ for (i = 1; i < size; i++) {
+ cpr_vreg->last_volt[i] = cpr_vreg->pvs_corner_v
+ [cpr_vreg->process][cpr_vreg->corner_map[i]];
}
return 0;
@@ -1599,7 +1645,9 @@
resource_size(res));
/* Init all voltage set points of APC regulator for CPR */
- cpr_init_cpr_voltages(cpr_vreg);
+ rc = cpr_init_cpr_voltages(cpr_vreg, &pdev->dev);
+ if (rc)
+ return rc;
/* Init CPR configuration parameters */
rc = cpr_init_cpr_parameters(pdev, cpr_vreg);
@@ -1614,7 +1662,7 @@
}
/* Configure CPR HW but keep it disabled */
- rc = cpr_config(cpr_vreg);
+ rc = cpr_config(cpr_vreg, &pdev->dev);
if (rc)
return rc;
@@ -1739,8 +1787,8 @@
rc = of_property_read_u32_array(of_node,
"qti,pvs-corner-ceiling-slow",
- &cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_CORNER_SVS],
- CPR_CORNER_MAX - CPR_CORNER_SVS);
+ &cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_FUSE_CORNER_SVS],
+ CPR_FUSE_CORNER_MAX - CPR_FUSE_CORNER_SVS);
if (rc < 0) {
pr_err("pvs-corner-ceiling-slow missing: rc=%d\n", rc);
return rc;
@@ -1748,8 +1796,8 @@
rc = of_property_read_u32_array(of_node,
"qti,pvs-corner-ceiling-nom",
- &cpr_vreg->pvs_corner_v[APC_PVS_NOM][CPR_CORNER_SVS],
- CPR_CORNER_MAX - CPR_CORNER_SVS);
+ &cpr_vreg->pvs_corner_v[APC_PVS_NOM][CPR_FUSE_CORNER_SVS],
+ CPR_FUSE_CORNER_MAX - CPR_FUSE_CORNER_SVS);
if (rc < 0) {
pr_err("pvs-corner-ceiling-norm missing: rc=%d\n", rc);
return rc;
@@ -1757,8 +1805,8 @@
rc = of_property_read_u32_array(of_node,
"qti,pvs-corner-ceiling-fast",
- &cpr_vreg->pvs_corner_v[APC_PVS_FAST][CPR_CORNER_SVS],
- CPR_CORNER_MAX - CPR_CORNER_SVS);
+ &cpr_vreg->pvs_corner_v[APC_PVS_FAST][CPR_FUSE_CORNER_SVS],
+ CPR_FUSE_CORNER_MAX - CPR_FUSE_CORNER_SVS);
if (rc < 0) {
pr_err("pvs-corner-ceiling-fast missing: rc=%d\n", rc);
return rc;
@@ -1775,70 +1823,26 @@
of_property_read_u32(of_node, "qti,cpr-cond-min-voltage",
&min_uv);
for (i = APC_PVS_SLOW; i < NUM_APC_PVS; i++)
- for (j = CPR_CORNER_SVS; j < CPR_CORNER_MAX; j++)
+ for (j = CPR_FUSE_CORNER_SVS; j < CPR_FUSE_CORNER_MAX;
+ j++)
if (cpr_vreg->pvs_corner_v[i][j] < min_uv)
cpr_vreg->pvs_corner_v[i][j] = min_uv;
}
/* Set ceiling max and use it for APC_PVS_NO */
cpr_vreg->ceiling_max =
- cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_CORNER_TURBO];
+ cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_FUSE_CORNER_TURBO];
for (i = APC_PVS_SLOW; i < NUM_APC_PVS; i++) {
pr_info("[%d] [%d %d %d] uV\n", i,
- cpr_vreg->pvs_corner_v[i][CPR_CORNER_SVS],
- cpr_vreg->pvs_corner_v[i][CPR_CORNER_NORMAL],
- cpr_vreg->pvs_corner_v[i][CPR_CORNER_TURBO]);
+ cpr_vreg->pvs_corner_v[i][CPR_FUSE_CORNER_SVS],
+ cpr_vreg->pvs_corner_v[i][CPR_FUSE_CORNER_NORMAL],
+ cpr_vreg->pvs_corner_v[i][CPR_FUSE_CORNER_TURBO]);
}
return 0;
}
-static int cpr_freq_transition(struct notifier_block *nb, unsigned long val,
- void *data)
-{
- int old_corner, new_corner;
- struct cpr_regulator *cpr_vreg = container_of(nb, struct cpr_regulator,
- freq_transition);
- struct cpufreq_freqs *freqs = data;
-
- mutex_lock(&cpr_vreg->cpr_mutex);
- switch (val) {
- case CPUFREQ_PRECHANGE:
- cpr_vreg->freq = freqs->new;
- if (freqs->new > freqs->old) {
- old_corner = cpr_get_freq_corner(cpr_vreg, freqs->old);
- new_corner = cpr_get_freq_corner(cpr_vreg, freqs->new);
- if (new_corner > 0 && old_corner == new_corner &&
- cpr_ctl_is_enabled(cpr_vreg)) {
- cpr_ctl_disable(cpr_vreg);
- cpr_irq_clr(cpr_vreg);
- cpr_corner_restore(cpr_vreg, new_corner);
- cpr_ctl_enable(cpr_vreg, new_corner);
- }
- }
- break;
- case CPUFREQ_POSTCHANGE:
- if (freqs->new < freqs->old) {
- old_corner = cpr_get_freq_corner(cpr_vreg, freqs->old);
- new_corner = cpr_get_freq_corner(cpr_vreg, freqs->new);
- if (new_corner > 0 && old_corner == new_corner &&
- cpr_ctl_is_enabled(cpr_vreg)) {
- cpr_ctl_disable(cpr_vreg);
- cpr_irq_clr(cpr_vreg);
- cpr_corner_restore(cpr_vreg, new_corner);
- cpr_ctl_enable(cpr_vreg, new_corner);
- }
- }
- break;
- default:
- break;
- }
- mutex_unlock(&cpr_vreg->cpr_mutex);
-
- return NOTIFY_OK;
-}
-
static int __devinit cpr_regulator_probe(struct platform_device *pdev)
{
struct cpr_regulator *cpr_vreg;
@@ -1922,10 +1926,6 @@
platform_set_drvdata(pdev, cpr_vreg);
the_cpr = cpr_vreg;
- cpr_vreg->freq_transition.notifier_call = cpr_freq_transition;
- if (cpr_vreg->flags & FLAGS_QUOT_ADJUST_WITH_FREQ)
- cpufreq_register_notifier(&cpr_vreg->freq_transition,
- CPUFREQ_TRANSITION_NOTIFIER);
return 0;
@@ -1946,9 +1946,6 @@
cpr_irq_set(cpr_vreg, 0);
}
- if (cpr_vreg->flags & FLAGS_QUOT_ADJUST_WITH_FREQ)
- cpufreq_unregister_notifier(&cpr_vreg->freq_transition,
- CPUFREQ_TRANSITION_NOTIFIER);
cpr_apc_exit(cpr_vreg);
regulator_unregister(cpr_vreg->rdev);
}
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h b/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
index 0a1cdd4..42cf6f9 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
@@ -45,7 +45,7 @@
};
void rtac_add_adm_device(u32 port_id, u32 copp_id, u32 path_id, u32 popp_id);
-void rtac_remove_adm_device(u32 port_id);
+void rtac_remove_adm_device(u32 port_id, u32 copp_id);
void rtac_remove_popp_from_adm_devices(u32 popp_id);
void rtac_add_voice(u32 cvs_handle, u32 cvp_handle, u32 rx_afe_port,
u32 tx_afe_port, u32 session_id);
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index ce66531..6bb4011 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -434,7 +434,7 @@
unsigned int len)
{
struct sk_buff *temp;
- int offset = 0, buf_len = 0, copy_len;
+ unsigned int offset = 0, buf_len = 0, copy_len;
void *buf;
if (!skb_head) {
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index b9dcf88..06160f7 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -212,7 +212,6 @@
switch (sleep_mode) {
case MSM_SPM_L2_MODE_POWER_COLLAPSE:
- pr_info("Configuring for L2 power collapse\n");
msm_pm_set_l2_flush_flag(MSM_SCM_L2_OFF);
break;
case MSM_SPM_L2_MODE_GDHS:
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
index e6b1324..a18d0f3 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
@@ -51,6 +51,11 @@
#define Y_IND 1
#define Z_IND 2
+/* Shared memory limits */
+/* max_buf_size = (port_size(65535*2) * port_num(8) * group_size(3) */
+#define USF_MAX_BUF_SIZE 3145680
+#define USF_MAX_BUF_NUM 32
+
/* Place for opreation result, received from QDSP6 */
#define APR_RESULT_IND 1
@@ -482,6 +487,15 @@
(config == NULL))
return -EINVAL;
+ if ((config->buf_size == 0) ||
+ (config->buf_size > USF_MAX_BUF_SIZE) ||
+ (config->buf_num == 0) ||
+ (config->buf_num > USF_MAX_BUF_NUM)) {
+ pr_err("%s: wrong params: buf_size=%d; buf_num=%d\n",
+ __func__, config->buf_size, config->buf_num);
+ return -EINVAL;
+ }
+
data_map_size = sizeof(usf_xx->encdec_cfg.cfg_common.data_map);
min_map_size = min(data_map_size, config->port_cnt);
@@ -794,6 +808,7 @@
{
uint32_t timeout = 0;
struct us_detect_info_type detect_info;
+ struct usm_session_cmd_detect_info *p_allocated_memory = NULL;
struct usm_session_cmd_detect_info usm_detect_info;
struct usm_session_cmd_detect_info *p_usm_detect_info =
&usm_detect_info;
@@ -820,12 +835,13 @@
uint8_t *p_data = NULL;
detect_info_size += detect_info.params_data_size;
- p_usm_detect_info = kzalloc(detect_info_size, GFP_KERNEL);
- if (p_usm_detect_info == NULL) {
+ p_allocated_memory = kzalloc(detect_info_size, GFP_KERNEL);
+ if (p_allocated_memory == NULL) {
pr_err("%s: detect_info[%d] allocation failed\n",
__func__, detect_info_size);
return -ENOMEM;
}
+ p_usm_detect_info = p_allocated_memory;
p_data = (uint8_t *)p_usm_detect_info +
sizeof(struct usm_session_cmd_detect_info);
@@ -835,7 +851,7 @@
if (rc) {
pr_err("%s: copy params from user; rc=%d\n",
__func__, rc);
- kfree(p_usm_detect_info);
+ kfree(p_allocated_memory);
return -EFAULT;
}
p_usm_detect_info->algorithm_cfg_size =
@@ -852,9 +868,7 @@
p_usm_detect_info,
detect_info_size);
if (rc || (detect_info.detect_timeout == USF_NO_WAIT_TIMEOUT)) {
- if (detect_info_size >
- sizeof(struct usm_session_cmd_detect_info))
- kfree(p_usm_detect_info);
+ kfree(p_allocated_memory);
return rc;
}
@@ -874,25 +888,24 @@
USF_US_DETECT_UNDEF),
timeout);
/* In the case of timeout, "no US" is assumed */
- if (rc < 0) {
+ if (rc < 0)
pr_err("%s: Getting US detection failed rc[%d]\n",
__func__, rc);
- return rc;
+ else {
+ usf->usf_rx.us_detect_type = usf->usf_tx.us_detect_type;
+ detect_info.is_us =
+ (usf_xx->us_detect_type == USF_US_DETECT_YES);
+ rc = copy_to_user((void __user *)arg,
+ &detect_info,
+ sizeof(detect_info));
+ if (rc) {
+ pr_err("%s: copy detect_info to user; rc=%d\n",
+ __func__, rc);
+ rc = -EFAULT;
+ }
}
- usf->usf_rx.us_detect_type = usf->usf_tx.us_detect_type;
- detect_info.is_us = (usf_xx->us_detect_type == USF_US_DETECT_YES);
- rc = copy_to_user((void __user *)arg,
- &detect_info,
- sizeof(detect_info));
- if (rc) {
- pr_err("%s: copy detect_info to user; rc=%d\n",
- __func__, rc);
- rc = -EFAULT;
- }
-
- if (detect_info_size > sizeof(struct usm_session_cmd_detect_info))
- kfree(p_usm_detect_info);
+ kfree(p_allocated_memory);
return rc;
} /* usf_set_us_detection */
@@ -993,16 +1006,14 @@
if (rc)
return rc;
- if (usf_xx->buffer_size && usf_xx->buffer_count) {
- rc = q6usm_us_client_buf_alloc(
- IN,
- usf_xx->usc,
- usf_xx->buffer_size,
- usf_xx->buffer_count);
- if (rc) {
- (void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
- return rc;
- }
+ rc = q6usm_us_client_buf_alloc(
+ IN,
+ usf_xx->usc,
+ usf_xx->buffer_size,
+ usf_xx->buffer_count);
+ if (rc) {
+ (void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+ return rc;
}
rc = q6usm_dec_cfg_blk(usf_xx->usc,
@@ -1221,10 +1232,15 @@
return -EFAULT;
}
- /* version_info.buf is pointer to place for the version string */
+ if (version_info.buf_size < sizeof(DRV_VERSION)) {
+ pr_err("%s: buf_size (%d) < version string size (%d)\n",
+ __func__, version_info.buf_size, sizeof(DRV_VERSION));
+ return -EINVAL;
+ }
+
rc = copy_to_user(version_info.pbuf,
DRV_VERSION,
- version_info.buf_size);
+ sizeof(DRV_VERSION));
if (rc) {
pr_err("%s: copy to version_info.pbuf; rc=%d\n",
__func__, rc);
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 22448a1..45a41eb 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -124,11 +124,14 @@
static bool io_is_busy;
/*
- * If the max load among the other CPUs is higher than sync_freq_load_threshold
- * then do not let the frequency to drop below sync_freq
+ * If the max load among other CPUs is higher than up_threshold_any_cpu_load
+ * and if the highest frequency among the other CPUs is higher than
+ * up_threshold_any_cpu_freq then do not let the frequency to drop below
+ * sync_freq
*/
-static unsigned int sync_freq_load_threshold;
+static unsigned int up_threshold_any_cpu_load;
static unsigned int sync_freq;
+static unsigned int up_threshold_any_cpu_freq;
static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
unsigned int event);
@@ -393,8 +396,9 @@
unsigned long flags;
bool boosted;
unsigned long mod_min_sample_time;
- int i, max_load_other_cpu;
- unsigned int max_freq_other_cpu;
+ int i, max_load;
+ unsigned int max_freq;
+ struct cpufreq_interactive_cpuinfo *picpu;
if (!down_read_trylock(&pcpu->enable_sem))
return;
@@ -416,20 +420,6 @@
pcpu->prev_load = cpu_load;
boosted = boost_val || now < boostpulse_endtime;
- max_load_other_cpu = 0;
- max_freq_other_cpu = 0;
- for_each_online_cpu(i) {
- struct cpufreq_interactive_cpuinfo *picpu =
- &per_cpu(cpuinfo, i);
- if (i == data)
- continue;
- if (max_load_other_cpu < picpu->prev_load)
- max_load_other_cpu = picpu->prev_load;
-
- if (picpu->policy->cur > max_freq_other_cpu)
- max_freq_other_cpu = picpu->policy->cur;
- }
-
if (cpu_load >= go_hispeed_load || boosted) {
if (pcpu->target_freq < hispeed_freq) {
new_freq = hispeed_freq;
@@ -441,10 +431,27 @@
}
} else {
new_freq = choose_freq(pcpu, loadadjfreq);
- if (sync_freq && (max_freq_other_cpu > sync_freq) &&
- (max_load_other_cpu > sync_freq_load_threshold) &&
- (new_freq < sync_freq))
- new_freq = sync_freq;
+
+ if (sync_freq && new_freq < sync_freq) {
+
+ max_load = 0;
+ max_freq = 0;
+
+ for_each_online_cpu(i) {
+ picpu = &per_cpu(cpuinfo, i);
+
+ if (i == data || picpu->prev_load <
+ up_threshold_any_cpu_load)
+ continue;
+
+ max_load = max(max_load, picpu->prev_load);
+ max_freq = max(max_freq, picpu->policy->cur);
+ }
+
+ if (max_freq > up_threshold_any_cpu_freq &&
+ max_load >= up_threshold_any_cpu_load)
+ new_freq = sync_freq;
+ }
}
if (pcpu->target_freq >= hispeed_freq &&
@@ -470,11 +477,10 @@
* Do not scale below floor_freq unless we have been at or above the
* floor frequency for the minimum sample time since last validated.
*/
- if (pcpu->policy->cur == pcpu->policy->max) {
+ if (sampling_down_factor && pcpu->policy->cur == pcpu->policy->max)
mod_min_sample_time = sampling_down_factor;
- } else {
+ else
mod_min_sample_time = min_sample_time;
- }
if (new_freq < pcpu->floor_freq) {
if (now - pcpu->floor_validate_time < mod_min_sample_time) {
@@ -1121,13 +1127,13 @@
static struct global_attr sync_freq_attr = __ATTR(sync_freq, 0644,
show_sync_freq, store_sync_freq);
-static ssize_t show_sync_freq_load_threshold(struct kobject *kobj,
+static ssize_t show_up_threshold_any_cpu_load(struct kobject *kobj,
struct attribute *attr, char *buf)
{
- return sprintf(buf, "%u\n", sync_freq_load_threshold);
+ return snprintf(buf, PAGE_SIZE, "%u\n", up_threshold_any_cpu_load);
}
-static ssize_t store_sync_freq_load_threshold(struct kobject *kobj,
+static ssize_t store_up_threshold_any_cpu_load(struct kobject *kobj,
struct attribute *attr, const char *buf, size_t count)
{
int ret;
@@ -1136,14 +1142,38 @@
ret = kstrtoul(buf, 0, &val);
if (ret < 0)
return ret;
- sync_freq_load_threshold = val;
+ up_threshold_any_cpu_load = val;
return count;
}
-static struct global_attr sync_freq_load_threshold_attr =
- __ATTR(sync_freq_load_threshold, 0644,
- show_sync_freq_load_threshold, store_sync_freq_load_threshold);
+static struct global_attr up_threshold_any_cpu_load_attr =
+ __ATTR(up_threshold_any_cpu_load, 0644,
+ show_up_threshold_any_cpu_load,
+ store_up_threshold_any_cpu_load);
+static ssize_t show_up_threshold_any_cpu_freq(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", up_threshold_any_cpu_freq);
+}
+
+static ssize_t store_up_threshold_any_cpu_freq(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+ unsigned long val;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+ up_threshold_any_cpu_freq = val;
+ return count;
+}
+
+static struct global_attr up_threshold_any_cpu_freq_attr =
+ __ATTR(up_threshold_any_cpu_freq, 0644,
+ show_up_threshold_any_cpu_freq,
+ store_up_threshold_any_cpu_freq);
static struct attribute *interactive_attributes[] = {
&target_loads_attr.attr,
@@ -1159,7 +1189,8 @@
&io_is_busy_attr.attr,
&sampling_down_factor_attr.attr,
&sync_freq_attr.attr,
- &sync_freq_load_threshold_attr.attr,
+ &up_threshold_any_cpu_load_attr.attr,
+ &up_threshold_any_cpu_freq_attr.attr,
NULL,
};
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index cdd31e1..a6fc3d5 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -973,7 +973,7 @@
sizeof(struct ion_flush_data)))
return -EFAULT;
- if (data.handle >= 0) {
+ if (data.handle > 0) {
handle = ion_handle_get_by_id(client, (int)data.handle);
if (IS_ERR(handle)) {
pr_info("%s: Could not find handle: %d\n",
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 070b5ac..eba60ea 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2051,6 +2051,8 @@
device->reset_counter++;
+ set_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv);
+
return 0;
error_rb_stop:
@@ -2088,7 +2090,25 @@
set_user_nice(current, _wake_nice);
mutex_lock(&device->mutex);
- _status = _adreno_start(adreno_dev);
+ /*
+ * If adreno start is already called, no need to call it again
+ * it can lead to unpredictable behavior if we try to start
+ * the device that is already started.
+ * Below is the sequence of events that can go bad without the check
+ * 1) thread 1 calls adreno_start to be scheduled on high priority wq
+ * 2) thread 2 calls adreno_start with normal priority
+ * 3) thread 1 after checking the device to be in slumber state gives
+ * up mutex to be scheduled on high priority wq
+ * 4) thread 2 after checking the device to be in slumber state gets
+ * the mutex and finishes adreno_start before thread 1 is scheduled
+ * on high priority wq.
+ * 5) thread 1 gets scheduled on high priority wq and executes
+ * adreno_start again. This leads to unpredictable behavior.
+ */
+ if (!test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv))
+ _status = _adreno_start(adreno_dev);
+ else
+ _status = 0;
mutex_unlock(&device->mutex);
}
@@ -2149,6 +2169,8 @@
kgsl_cffdump_close(device);
+ clear_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv);
+
return 0;
}
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 1b538a7..800caf1 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -216,6 +216,7 @@
ADRENO_DEVICE_PWRON = 0,
ADRENO_DEVICE_PWRON_FIXUP = 1,
ADRENO_DEVICE_INITIALIZED = 2,
+ ADRENO_DEVICE_STARTED = 3,
};
#define PERFCOUNTER_FLAG_NONE 0x0
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 505be69..f0114ad 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -141,7 +141,7 @@
static inline void *kgsl_sg_alloc(unsigned int sglen)
{
- if (sglen >= ULONG_MAX / sizeof(struct scatterlist))
+ if ((sglen == 0) || (sglen >= ULONG_MAX / sizeof(struct scatterlist)))
return NULL;
if ((sglen * sizeof(struct scatterlist)) < PAGE_SIZE)
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 755084c..7152ec8 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -2424,6 +2424,8 @@
}
}
+ INIT_LIST_HEAD(&rmi->support_fn_list);
+
retval = synaptics_rmi4_query_device(rmi4_data);
if (retval < 0) {
dev_err(&rmi4_data->i2c_client->dev,
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 6ea4ea6..32623f4 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -832,13 +832,12 @@
int rc = 0;
u8 usb_reg = 0, temp = 8;
- if (mA < QPNP_CHG_I_MAX_MIN_100
- || mA > QPNP_CHG_I_MAX_MAX_MA) {
+ if (mA < 0 || mA > QPNP_CHG_I_MAX_MAX_MA) {
pr_err("bad mA=%d asked to set\n", mA);
return -EINVAL;
}
- if (mA == QPNP_CHG_I_MAX_MIN_100) {
+ if (mA <= QPNP_CHG_I_MAX_MIN_100) {
usb_reg = 0x00;
pr_debug("current=%d setting %02x\n", mA, usb_reg);
return qpnp_chg_write(chip, &usb_reg,
@@ -1476,6 +1475,7 @@
chip->chg_done = false;
}
qpnp_chg_usb_suspend_enable(chip, 0);
+ qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
chip->prev_usb_max_ma = -EINVAL;
chip->aicl_settled = false;
} else {
@@ -3641,7 +3641,8 @@
qpnp_batt_system_temp_level_set(chip, val->intval);
break;
case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
- qpnp_chg_iusbmax_set(chip, val->intval / 1000);
+ if (qpnp_chg_is_usb_chg_plugged_in(chip))
+ qpnp_chg_iusbmax_set(chip, val->intval / 1000);
break;
case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
qpnp_chg_iusb_trim_set(chip, val->intval);
diff --git a/drivers/sensors/sensors_class.c b/drivers/sensors/sensors_class.c
index 74e0d8d..bbf168c 100644
--- a/drivers/sensors/sensors_class.c
+++ b/drivers/sensors/sensors_class.c
@@ -105,6 +105,78 @@
sensors_cdev->fifo_max_event_count);
}
+static ssize_t sensors_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
+ ssize_t ret = -EINVAL;
+ unsigned long data = 0;
+
+ ret = kstrtoul(buf, 10, &data);
+ if (ret)
+ return ret;
+ if (data > 1) {
+ dev_err(dev, "Invalid value of input, input=%ld\n", data);
+ return -EINVAL;
+ }
+
+ if (sensors_cdev->sensors_enable == NULL) {
+ dev_err(dev, "Invalid sensor class enable handle\n");
+ return -EINVAL;
+ }
+ ret = sensors_cdev->sensors_enable(sensors_cdev, data);
+ if (ret)
+ return ret;
+
+ sensors_cdev->enabled = data;
+ return size;
+}
+
+
+static ssize_t sensors_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ sensors_cdev->enabled);
+}
+
+static ssize_t sensors_delay_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
+ ssize_t ret = -EINVAL;
+ unsigned long data = 0;
+
+ ret = kstrtoul(buf, 10, &data);
+ if (ret)
+ return ret;
+ /* The data unit is millisecond, the min_delay unit is microseconds. */
+ if ((data * 1000) < sensors_cdev->min_delay) {
+ dev_err(dev, "Invalid value of delay, delay=%ld\n", data);
+ return -EINVAL;
+ }
+ if (sensors_cdev->sensors_poll_delay == NULL) {
+ dev_err(dev, "Invalid sensor class delay handle\n");
+ return -EINVAL;
+ }
+ ret = sensors_cdev->sensors_poll_delay(sensors_cdev, data);
+ if (ret)
+ return ret;
+
+ sensors_cdev->delay_msec = data;
+ return size;
+}
+
+static ssize_t sensors_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct sensors_classdev *sensors_cdev = dev_get_drvdata(dev);
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ sensors_cdev->delay_msec);
+}
+
+
static struct device_attribute sensors_class_attrs[] = {
__ATTR(name, 0444, sensors_name_show, NULL),
__ATTR(vendor, 0444, sensors_vendor_show, NULL),
@@ -117,6 +189,8 @@
__ATTR(min_delay, 0444, sensors_min_delay_show, NULL),
__ATTR(fifo_reserved_event_count, 0444, sensors_fifo_event_show, NULL),
__ATTR(fifo_max_event_count, 0444, sensors_fifo_max_show, NULL),
+ __ATTR(enable, 0664, sensors_enable_show, sensors_enable_store),
+ __ATTR(poll_delay, 0664, sensors_delay_show, sensors_delay_store),
__ATTR_NULL,
};
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 7d8899e..efb87a9 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -1902,7 +1902,7 @@
pr_debug("thermal node%x\n", btm_channel_num);
chip->sensor[sen_idx].mode = THERMAL_DEVICE_DISABLED;
chip->sensor[sen_idx].thermal_node = true;
- snprintf(name, sizeof(name),
+ snprintf(name, sizeof(name), "%s",
chip->adc->adc_channels[sen_idx].name);
chip->sensor[sen_idx].meas_interval =
QPNP_ADC_TM_MEAS_INTERVAL;
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index 6d7dd3d..88ebd80 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -899,7 +899,10 @@
dev->rx_done || dev->state != STATE_BUSY);
if (dev->state == STATE_CANCELED
|| dev->state == STATE_OFFLINE) {
- r = -ECANCELED;
+ if (dev->state == STATE_OFFLINE)
+ r = -EIO;
+ else
+ r = -ECANCELED;
if (!dev->rx_done)
usb_ep_dequeue(dev->ep_out, read_req);
break;
diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c
index e8c9667..883c5fa 100644
--- a/drivers/usb/gadget/f_uac1.c
+++ b/drivers/usb/gadget/f_uac1.c
@@ -1,7 +1,7 @@
/*
* f_audio.c -- USB Audio class function driver
*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
* Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
* Copyright (C) 2008 Analog Devices, Inc
*
@@ -438,8 +438,8 @@
{
if (audio_buf) {
kfree(audio_buf->buf);
- kfree(audio_buf);
audio_buf->buf = NULL;
+ kfree(audio_buf);
audio_buf = NULL;
}
}
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 28997ec..f1f0455 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -26,6 +26,7 @@
#include "mdss_fb.h"
#define MDP_VSYNC_CLK_RATE 19200000
+#define KOFF_TIMEOUT msecs_to_jiffies(84)
enum {
MDP3_CLK_AHB,
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index a6fc20d..6fc6195 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -91,6 +91,36 @@
return bufq->count;
}
+void mdp3_ctrl_notifier_register(struct mdp3_session_data *ses,
+ struct notifier_block *notifier)
+{
+ blocking_notifier_chain_register(&ses->notifier_head, notifier);
+}
+
+void mdp3_ctrl_notifier_unregister(struct mdp3_session_data *ses,
+ struct notifier_block *notifier)
+{
+ blocking_notifier_chain_unregister(&ses->notifier_head, notifier);
+}
+
+int mdp3_ctrl_notify(struct mdp3_session_data *ses, int event)
+{
+ return blocking_notifier_call_chain(&ses->notifier_head, event, ses);
+}
+
+static void mdp3_dispatch_dma_done(struct work_struct *work)
+{
+ struct mdp3_session_data *session;
+
+ pr_debug("%s\n", __func__);
+ session = container_of(work, struct mdp3_session_data,
+ dma_done_work);
+ if (!session)
+ return;
+
+ mdp3_ctrl_notify(session, MDP_NOTIFY_FRAME_DONE);
+}
+
static void mdp3_dispatch_clk_off(struct work_struct *work)
{
struct mdp3_session_data *session;
@@ -121,6 +151,12 @@
sysfs_notify_dirent(session->vsync_event_sd);
}
+void dma_done_notify_handler(void *arg)
+{
+ struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
+ schedule_work(&session->dma_done_work);
+}
+
void vsync_count_down(void *arg)
{
struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
@@ -140,8 +176,8 @@
static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
{
struct mdp3_session_data *mdp3_session;
- struct mdp3_vsync_notification vsync_client;
- struct mdp3_vsync_notification *arg = NULL;
+ struct mdp3_notification vsync_client;
+ struct mdp3_notification *arg = NULL;
pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -464,6 +500,7 @@
int frame_rate = mfd->panel_info->mipi.frame_rate;
int vbp, vfp, vspw;
int vtotal, vporch;
+ struct mdp3_notification dma_done_callback;
vbp = panel_info->lcdc.v_back_porch;
vfp = panel_info->lcdc.v_front_porch;
@@ -499,6 +536,13 @@
rc = dma->dma_config(dma, &sourceConfig, &outputConfig);
else
rc = -EINVAL;
+
+ if (outputConfig.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ dma_done_callback.handler = dma_done_notify_handler;
+ dma_done_callback.arg = mfd->mdp.private1;
+ dma->dma_done_notifier(dma, &dma_done_callback);
+ }
+
return rc;
}
@@ -527,6 +571,8 @@
}
mdp3_batfet_ctrl(true);
+ mdp3_ctrl_notifier_register(mdp3_session,
+ &mdp3_session->mfd->mdp_sync_pt_data.notifier);
rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
if (rc) {
@@ -658,6 +704,8 @@
if (rc)
pr_err("fail to dettach MDP DMA SMMU\n");
+ mdp3_ctrl_notifier_unregister(mdp3_session,
+ &mdp3_session->mfd->mdp_sync_pt_data.notifier);
mdp3_batfet_ctrl(false);
mdp3_session->vsync_enabled = 0;
atomic_set(&mdp3_session->vsync_countdown, 0);
@@ -677,7 +725,7 @@
struct mdp3_session_data *mdp3_session;
struct mdp3_dma *mdp3_dma;
struct mdss_panel_data *panel;
- struct mdp3_vsync_notification vsync_client;
+ struct mdp3_notification vsync_client;
pr_debug("mdp3_ctrl_reset_cmd\n");
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -727,7 +775,7 @@
struct mdp3_session_data *mdp3_session;
struct mdp3_dma *mdp3_dma;
struct mdss_panel_data *panel;
- struct mdp3_vsync_notification vsync_client;
+ struct mdp3_notification vsync_client;
pr_debug("mdp3_ctrl_reset\n");
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -969,13 +1017,27 @@
return -EPERM;
}
+ mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_BEGIN);
data = mdp3_bufq_pop(&mdp3_session->bufq_in);
if (data) {
mdp3_ctrl_reset_countdown(mdp3_session, mfd);
mdp3_ctrl_clk_enable(mfd, 1);
- mdp3_session->dma->update(mdp3_session->dma,
+ rc = mdp3_session->dma->update(mdp3_session->dma,
(void *)data->addr,
mdp3_session->intf);
+ /* This is for the previous frame */
+ if (rc < 0) {
+ mdp3_ctrl_notify(mdp3_session,
+ MDP_NOTIFY_FRAME_TIMEOUT);
+ } else {
+ if (mdp3_ctrl_get_intf_type(mfd) ==
+ MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
+ mdp3_ctrl_notify(mdp3_session,
+ MDP_NOTIFY_FRAME_DONE);
+ }
+ }
+
+ mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_FLUSHED);
mdp3_bufq_push(&mdp3_session->bufq_out, data);
}
@@ -998,7 +1060,7 @@
mdss_fb_update_notify_update(mfd);
- return rc;
+ return 0;
}
static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
@@ -1008,6 +1070,7 @@
u32 offset;
int bpp;
struct mdss_panel_info *panel_info = mfd->panel_info;
+ int rc;
pr_debug("mdp3_ctrl_pan_display\n");
if (!mfd || !mfd->mdp.private1)
@@ -1044,10 +1107,23 @@
if (mfd->fbi->screen_base) {
mdp3_ctrl_reset_countdown(mdp3_session, mfd);
+ mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_BEGIN);
mdp3_ctrl_clk_enable(mfd, 1);
- mdp3_session->dma->update(mdp3_session->dma,
- (void *)mfd->iova + offset,
+ rc = mdp3_session->dma->update(mdp3_session->dma,
+ (void *)(mfd->iova + offset),
mdp3_session->intf);
+ /* This is for the previous frame */
+ if (rc < 0) {
+ mdp3_ctrl_notify(mdp3_session,
+ MDP_NOTIFY_FRAME_TIMEOUT);
+ } else {
+ if (mdp3_ctrl_get_intf_type(mfd) ==
+ MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
+ mdp3_ctrl_notify(mdp3_session,
+ MDP_NOTIFY_FRAME_DONE);
+ }
+ }
+ mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_FLUSHED);
} else {
pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
mdp3_clk_enable(1, 0);
@@ -1658,6 +1734,7 @@
memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
mutex_init(&mdp3_session->lock);
INIT_WORK(&mdp3_session->clk_off_work, mdp3_dispatch_clk_off);
+ INIT_WORK(&mdp3_session->dma_done_work, mdp3_dispatch_dma_done);
atomic_set(&mdp3_session->vsync_countdown, 0);
mutex_init(&mdp3_session->histo_lock);
mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
@@ -1693,6 +1770,7 @@
mdp3_bufq_init(&mdp3_session->bufq_out);
mdp3_session->histo_status = 0;
mdp3_session->lut_sel = 0;
+ BLOCKING_INIT_NOTIFIER_HEAD(&mdp3_session->notifier_head);
init_timer(&mdp3_session->vsync_timer);
mdp3_session->vsync_timer.function = mdp3_vsync_timer_func;
@@ -1721,8 +1799,11 @@
kobject_uevent(&dev->kobj, KOBJ_ADD);
pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
- if (mdp3_get_cont_spash_en())
+ if (mdp3_get_cont_spash_en()) {
mdp3_session->clk_on = 1;
+ mdp3_ctrl_notifier_register(mdp3_session,
+ &mdp3_session->mfd->mdp_sync_pt_data.notifier);
+ }
if (splash_mismatch) {
pr_err("splash memory mismatch, stop splash\n");
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index f2484ef..cfad1d3 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -49,6 +49,7 @@
struct mdp3_buffer_queue bufq_in;
struct mdp3_buffer_queue bufq_out;
struct work_struct clk_off_work;
+ struct work_struct dma_done_work;
int histo_status;
struct mutex histo_lock;
int lut_sel;
@@ -56,6 +57,7 @@
bool vsync_before_commit;
bool first_commit;
int clk_on;
+ struct blocking_notifier_head notifier_head;
int vsync_enabled;
atomic_t vsync_countdown; /* Used to count down */
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index ae7598f..5cae2de 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -27,7 +27,7 @@
static void mdp3_vsync_intr_handler(int type, void *arg)
{
struct mdp3_dma *dma = (struct mdp3_dma *)arg;
- struct mdp3_vsync_notification vsync_client;
+ struct mdp3_notification vsync_client;
unsigned int wait_for_next_vs;
pr_debug("mdp3_vsync_intr_handler\n");
@@ -49,10 +49,16 @@
static void mdp3_dma_done_intr_handler(int type, void *arg)
{
struct mdp3_dma *dma = (struct mdp3_dma *)arg;
+ struct mdp3_notification dma_client;
pr_debug("mdp3_dma_done_intr_handler\n");
+ spin_lock(&dma->dma_lock);
+ dma_client = dma->dma_notifier_client;
complete(&dma->dma_comp);
+ spin_unlock(&dma->dma_lock);
mdp3_irq_disable_nosync(type);
+ if (dma_client.handler)
+ dma_client.handler(dma_client.arg);
}
static void mdp3_hist_done_intr_handler(int type, void *arg)
@@ -195,7 +201,7 @@
}
static void mdp3_dma_vsync_enable(struct mdp3_dma *dma,
- struct mdp3_vsync_notification *vsync_client)
+ struct mdp3_notification *vsync_client)
{
unsigned long flag;
int updated = 0;
@@ -226,6 +232,21 @@
}
}
+static void mdp3_dma_done_notifier(struct mdp3_dma *dma,
+ struct mdp3_notification *dma_client)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&dma->dma_lock, flag);
+ if (dma_client) {
+ dma->dma_notifier_client = *dma_client;
+ } else {
+ dma->dma_notifier_client.handler = NULL;
+ dma->dma_notifier_client.arg = NULL;
+ }
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+}
+
static void mdp3_dma_clk_auto_gating(struct mdp3_dma *dma, int enable)
{
u32 cgc;
@@ -552,13 +573,20 @@
{
unsigned long flag;
int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
+ int rc = 0;
pr_debug("mdp3_dmap_update\n");
if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
- if (intf->active)
- wait_for_completion_killable(&dma->dma_comp);
+ if (intf->active) {
+ rc = wait_for_completion_timeout(&dma->dma_comp,
+ KOFF_TIMEOUT);
+ if (rc <= 0) {
+ WARN(1, "cmd kickoff timed out (%d)\n", rc);
+ rc = -1;
+ }
+ }
}
spin_lock_irqsave(&dma->dma_lock, flag);
MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
@@ -581,10 +609,14 @@
mdp3_dma_callback_enable(dma, cb_type);
pr_debug("mdp3_dmap_update wait for vsync_comp in\n");
- if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
- wait_for_completion_killable(&dma->vsync_comp);
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
+ rc = wait_for_completion_timeout(&dma->vsync_comp,
+ KOFF_TIMEOUT);
+ if (rc <= 0)
+ rc = -1;
+ }
pr_debug("mdp3_dmap_update wait for vsync_comp out\n");
- return 0;
+ return rc;
}
static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf,
@@ -878,6 +910,7 @@
dma->get_histo = mdp3_dmap_histo_get;
dma->histo_op = mdp3_dmap_histo_op;
dma->vsync_enable = mdp3_dma_vsync_enable;
+ dma->dma_done_notifier = mdp3_dma_done_notifier;
dma->start = mdp3_dma_start;
dma->stop = mdp3_dma_stop;
dma->config_stride = mdp3_dma_stride_config;
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 6ad4c79..04955d4 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -14,6 +14,7 @@
#ifndef MDP3_DMA_H
#define MDP3_DMA_H
+#include <linux/notifier.h>
#include <linux/sched.h>
#define MDP_HISTOGRAM_BL_SCALE_MAX 1024
@@ -227,7 +228,7 @@
u32 extra[2];
};
-struct mdp3_vsync_notification {
+struct mdp3_notification {
void (*handler)(void *arg);
void *arg;
};
@@ -245,7 +246,8 @@
struct completion vsync_comp;
struct completion dma_comp;
struct completion histo_comp;
- struct mdp3_vsync_notification vsync_client;
+ struct mdp3_notification vsync_client;
+ struct mdp3_notification dma_notifier_client;
struct mdp3_dma_output_config output_config;
struct mdp3_dma_source source_config;
@@ -291,7 +293,10 @@
void (*config_stride)(struct mdp3_dma *dma, int stride);
void (*vsync_enable)(struct mdp3_dma *dma,
- struct mdp3_vsync_notification *vsync_client);
+ struct mdp3_notification *vsync_client);
+
+ void (*dma_done_notifier)(struct mdp3_dma *dma,
+ struct mdp3_notification *dma_client);
};
struct mdp3_video_intf_cfg {
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 3c7d17c..8c3e470 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -767,6 +767,8 @@
ctrl_pdata->bklt_ctrl = BL_DCS_CMD;
}
}
+ rc = of_property_read_u32(np, "qcom,mdss-brightness-max-level", &tmp);
+ pinfo->brightness_max = (!rc ? tmp : MDSS_MAX_BL_BRIGHTNESS);
rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-min-level", &tmp);
pinfo->bl_min = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-max-level", &tmp);
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index 6dbca10..95c746e 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -697,10 +697,15 @@
static int mdss_edp_device_register(struct mdss_edp_drv_pdata *edp_drv)
{
int ret;
+ u32 tmp;
mdss_edp_edid2pinfo(edp_drv);
edp_drv->panel_data.panel_info.bl_min = 1;
edp_drv->panel_data.panel_info.bl_max = 255;
+ ret = of_property_read_u32(edp_drv->pdev->dev.of_node,
+ "qcom,mdss-brightness-max-level", &tmp);
+ edp_drv->panel_data.panel_info.brightness_max =
+ (!ret ? tmp : MDSS_MAX_BL_BRIGHTNESS);
edp_drv->panel_data.event_handler = mdss_edp_event_handler;
edp_drv->panel_data.set_backlight = mdss_edp_set_backlight;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 94b2cbd..c2db15c 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -154,13 +154,13 @@
struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
int bl_lvl;
- if (value > MDSS_MAX_BL_BRIGHTNESS)
- value = MDSS_MAX_BL_BRIGHTNESS;
+ if (value > mfd->panel_info->brightness_max)
+ value = mfd->panel_info->brightness_max;
/* This maps android backlight level 0 to 255 into
driver backlight level 0 to bl_max with rounding */
MDSS_BRIGHT_TO_BL(bl_lvl, value, mfd->panel_info->bl_max,
- MDSS_MAX_BL_BRIGHTNESS);
+ mfd->panel_info->brightness_max);
if (!bl_lvl && value)
bl_lvl = 1;
@@ -374,6 +374,9 @@
/* android supports only one lcd-backlight/lcd for now */
if (!lcd_backlight_registered) {
+
+ backlight_led.brightness = mfd->panel_info->brightness_max;
+ backlight_led.max_brightness = mfd->panel_info->brightness_max;
if (led_classdev_register(&pdev->dev, &backlight_led))
pr_err("led_classdev_register failed\n");
else
@@ -1836,11 +1839,11 @@
int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state)
{
- int ret = -EINVAL;
+ int ret = 0;
if (req_state == mfd->dcm_state) {
- pr_warn("Already in correct DCM state");
- ret = 0;
+ pr_warn("Already in correct DCM/DTM state");
+ return ret;
}
switch (req_state) {
@@ -1856,11 +1859,12 @@
break;
case DCM_ENTER:
if (mfd->dcm_state == DCM_UNBLANK) {
- /* Keep unblank path available for only
- DCM operation */
+ /*
+ * Keep unblank path available for only
+ * DCM operation
+ */
mfd->panel_power_on = false;
mfd->dcm_state = DCM_ENTER;
- ret = 0;
}
break;
case DCM_EXIT:
@@ -1868,7 +1872,6 @@
/* Release the unblank path for exit */
mfd->panel_power_on = true;
mfd->dcm_state = DCM_EXIT;
- ret = 0;
}
break;
case DCM_BLANK:
@@ -1882,7 +1885,16 @@
}
}
break;
+ case DTM_ENTER:
+ if (mfd->dcm_state == DCM_UNINIT)
+ mfd->dcm_state = DTM_ENTER;
+ break;
+ case DTM_EXIT:
+ if (mfd->dcm_state == DTM_ENTER)
+ mfd->dcm_state = DCM_UNINIT;
+ break;
}
+
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index f73b583..d57e4fb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1913,8 +1913,10 @@
if (ctl->wait_pingpong)
ctl->wait_pingpong(ctl, NULL);
- /* postprocessing setup, including dspp */
- mdss_mdp_pp_setup_locked(ctl);
+ if (ctl->mfd && ctl->mfd->dcm_state != DTM_ENTER)
+ /* postprocessing setup, including dspp */
+ mdss_mdp_pp_setup_locked(ctl);
+
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl->flush_bits);
if (sctl) {
mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH,
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index b6f94d0..bcd3cf4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -108,7 +108,9 @@
MDSS_MDP_MAX_CTL
};
-#define MDSS_MDP_REG_CTL_OFFSET(ctl) (0x00600 + ((ctl) * 0x100))
+#define MDSS_MDP_CTL_ADDRESS_OFFSET 0x100
+#define MDSS_MDP_REG_CTL_OFFSET(ctl) (0x00600 + ((ctl) * \
+ MDSS_MDP_CTL_ADDRESS_OFFSET))
#define MDSS_MDP_REG_CTL_LAYER(lm) ((lm) * 0x004)
#define MDSS_MDP_REG_CTL_TOP 0x014
@@ -159,7 +161,10 @@
MDSS_MDP_CHROMA_420
};
-#define MDSS_MDP_REG_SSPP_OFFSET(pipe) (0x01200 + ((pipe) * 0x400))
+
+#define MDSS_MDP_SSPP_ADDRESS_OFFSET 0x400
+#define MDSS_MDP_REG_SSPP_OFFSET(pipe) (0x01200 + ((pipe) * \
+ MDSS_MDP_SSPP_ADDRESS_OFFSET))
#define MDSS_MDP_REG_SSPP_SRC_SIZE 0x000
#define MDSS_MDP_REG_SSPP_SRC_IMG_SIZE 0x004
@@ -175,6 +180,7 @@
#define MDSS_MDP_REG_SSPP_STILE_FRAME_SIZE 0x02C
#define MDSS_MDP_REG_SSPP_SRC_FORMAT 0x030
#define MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN 0x034
+#define MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR 0x03C
#define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_0 0x050
#define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_1 0x054
#define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_2 0x058
@@ -280,8 +286,9 @@
MDSS_MDP_MAX_STAGE
};
-#define MDSS_MDP_REG_LM_OFFSET(lm) (0x03200 + ((lm) * 0x400))
-
+#define MDSS_MDP_LM_ADDRESS_OFFSET 0x400
+#define MDSS_MDP_REG_LM_OFFSET(lm) (0x03200 + ((lm) * \
+ MDSS_MDP_LM_ADDRESS_OFFSET))
#define MDSS_MDP_REG_LM_OP_MODE 0x000
#define MDSS_MDP_REG_LM_OUT_SIZE 0x004
#define MDSS_MDP_REG_LM_BORDER_COLOR_0 0x008
@@ -423,7 +430,9 @@
MDSS_MDP_MAX_DSPP
};
-#define MDSS_MDP_REG_DSPP_OFFSET(pipe) (0x4600 + ((pipe) * 0x400))
+#define MDSS_MDP_DSPP_ADDRESS_OFFSET 0x400
+#define MDSS_MDP_REG_DSPP_OFFSET(pipe) (0x4600 + ((pipe) * \
+ MDSS_MDP_DSPP_ADDRESS_OFFSET))
#define MDSS_MDP_REG_DSPP_OP_MODE 0x000
#define MDSS_MDP_REG_DSPP_PCC_BASE 0x030
#define MDSS_MDP_REG_DSPP_DITHER_DEPTH 0x150
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index d0d2157..311efb2 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -173,6 +173,13 @@
GAMUT_T2_SIZE + GAMUT_T3_SIZE + GAMUT_T4_SIZE + \
GAMUT_T5_SIZE + GAMUT_T6_SIZE + GAMUT_T7_SIZE)
+#define MDSS_MDP_PA_SIZE 0xC
+#define MDSS_MDP_GC_SIZE 0x28
+#define MDSS_MDP_PCC_SIZE 0xB8
+#define MDSS_MDP_GAMUT_SIZE 0x5C
+#define MDSS_MDP_IGC_DSPP_COLORS 0x3
+#define TOTAL_BLEND_STAGES 0x4
+
#define PP_FLAGS_DIRTY_PA 0x1
#define PP_FLAGS_DIRTY_PCC 0x2
#define PP_FLAGS_DIRTY_IGC 0x4
@@ -1082,7 +1089,7 @@
/*program pixel extn values for the SSPP*/
mdss_mdp_pipe_program_pixel_extn(pipe);
- } else {
+ } else if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG) {
writel_relaxed(phasex_step, pipe->base +
MDSS_MDP_REG_SCALE_PHASE_STEP_X);
writel_relaxed(phasey_step, pipe->base +
@@ -1091,6 +1098,11 @@
MDSS_MDP_REG_SCALE_INIT_PHASE_X);
writel_relaxed(init_phasey, pipe->base +
MDSS_MDP_REG_SCALE_INIT_PHASE_Y);
+ } 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(scale_config, pipe->base +
@@ -1505,6 +1517,9 @@
pp_sts_set_split_bits(&pp_sts->pgc_sts, pgc_config->flags);
}
+ pp_dspp_opmode_config(ctl, dspp_num, pp_sts, mdata->mdp_rev, &opmode);
+
+flush_exit:
if (ad_hw) {
mutex_lock(&ad->lock);
ad_flags = ad->reg_sts;
@@ -1519,8 +1534,6 @@
mutex_unlock(&ad->lock);
}
- pp_dspp_opmode_config(ctl, dspp_num, pp_sts, mdata->mdp_rev, &opmode);
-flush_exit:
writel_relaxed(opmode, base + MDSS_MDP_REG_DSPP_OP_MODE);
ctl->flush_bits |= BIT(13 + dspp_num);
wmb();
@@ -1727,11 +1740,13 @@
if (mdss_pp_res == NULL) {
pr_err("%s mdss_pp_res allocation failed!", __func__);
ret = -ENOMEM;
- }
-
- for (i = 0; i < MDSS_MDP_MAX_DSPP; i++) {
- mutex_init(&mdss_pp_res->dspp_hist[i].hist_mutex);
- spin_lock_init(&mdss_pp_res->dspp_hist[i].hist_lock);
+ } else {
+ for (i = 0; i < MDSS_MDP_MAX_DSPP; i++) {
+ mutex_init(
+ &mdss_pp_res->dspp_hist[i].hist_mutex);
+ spin_lock_init(
+ &mdss_pp_res->dspp_hist[i].hist_lock);
+ }
}
}
if (mdata) {
@@ -3860,7 +3875,7 @@
mutex_unlock(&ad->lock);
mutex_lock(&mfd->bl_lock);
MDSS_BRIGHT_TO_BL(bl, bl, mfd->panel_info->bl_max,
- MDSS_MAX_BL_BRIGHTNESS);
+ mfd->panel_info->brightness_max);
mdss_fb_set_backlight(mfd, bl);
mutex_unlock(&mfd->bl_lock);
mutex_lock(&ad->lock);
@@ -4434,71 +4449,271 @@
return rc;
}
-static int is_valid_calib_addr(void *addr)
+static int is_valid_calib_ctrl_addr(char __iomem *ptr)
+{
+ char __iomem *base;
+ int ret = 0, counter = 0;
+ int stage = 0;
+ struct mdss_mdp_ctl *ctl;
+
+ /* Controller */
+ for (counter = 0; counter < mdss_res->nctl; counter++) {
+ ctl = mdss_res->ctl_off + counter;
+ base = ctl->base;
+
+ if (ptr == base + MDSS_MDP_REG_CTL_TOP) {
+ ret = MDP_PP_OPS_READ;
+ break;
+ } else if (ptr == base + MDSS_MDP_REG_CTL_FLUSH) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ }
+
+ for (stage = 0; stage < mdss_res->nmixers_intf; stage++)
+ if (ptr == base + MDSS_MDP_REG_CTL_LAYER(stage)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ goto End;
+ }
+ }
+
+End:
+ return ret;
+}
+
+static int is_valid_calib_dspp_addr(char __iomem *ptr)
+{
+ char __iomem *base;
+ int ret = 0, counter = 0;
+ struct mdss_mdp_mixer *mixer;
+
+ for (counter = 0; counter < mdss_res->nmixers_intf; counter++) {
+ mixer = mdss_res->mixer_intf + counter;
+ base = mixer->dspp_base;
+
+ if (ptr == base) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ /* PA range */
+ } else if ((ptr >= base + MDSS_MDP_REG_DSPP_PA_BASE) &&
+ (ptr <= base + MDSS_MDP_REG_DSPP_PA_BASE +
+ MDSS_MDP_PA_SIZE)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ /* PCC range */
+ } else if ((ptr >= base + MDSS_MDP_REG_DSPP_PCC_BASE) &&
+ (ptr <= base + MDSS_MDP_REG_DSPP_PCC_BASE +
+ MDSS_MDP_PCC_SIZE)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ /* Gamut range */
+ } else if ((ptr >= base + MDSS_MDP_REG_DSPP_GAMUT_BASE) &&
+ (ptr <= base + MDSS_MDP_REG_DSPP_GAMUT_BASE +
+ MDSS_MDP_GAMUT_SIZE)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ /* GC range */
+ } else if ((ptr >= base + MDSS_MDP_REG_DSPP_GC_BASE) &&
+ (ptr <= base + MDSS_MDP_REG_DSPP_GC_BASE +
+ MDSS_MDP_GC_SIZE)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ /* Dither enable/disable */
+ } else if ((ptr == base + MDSS_MDP_REG_DSPP_DITHER_DEPTH)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int is_valid_calib_vig_addr(char __iomem *ptr)
+{
+ char __iomem *base;
+ int ret = 0, counter = 0;
+ struct mdss_mdp_pipe *pipe;
+
+ for (counter = 0; counter < mdss_res->nvig_pipes; counter++) {
+ pipe = mdss_res->vig_pipes + counter;
+ base = pipe->base;
+
+ if (ptr == base + MDSS_MDP_REG_SSPP_SRC_FORMAT) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ } else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ } else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ } else if ((ptr == base + MDSS_MDP_REG_VIG_QSEED2_SHARP)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ /* PA range */
+ } else if ((ptr >= base + MDSS_MDP_REG_VIG_PA_BASE) &&
+ (ptr <= base + MDSS_MDP_REG_VIG_PA_BASE +
+ MDSS_MDP_PA_SIZE)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ /* IGC range */
+ } else if ((ptr >= base + MDSS_MDP_REG_IGC_VIG_BASE) &&
+ (ptr <= base + MDSS_MDP_REG_IGC_VIG_BASE +
+ MDSS_MDP_GC_SIZE)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int is_valid_calib_rgb_addr(char __iomem *ptr)
+{
+ char __iomem *base;
+ int ret = 0, counter = 0;
+ struct mdss_mdp_pipe *pipe;
+
+ for (counter = 0; counter < mdss_res->nrgb_pipes; counter++) {
+ pipe = mdss_res->rgb_pipes + counter;
+ base = pipe->base;
+
+ if (ptr == base + MDSS_MDP_REG_SSPP_SRC_FORMAT) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ } else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ } else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ /* IGC range */
+ } else if ((ptr >= base + MDSS_MDP_REG_IGC_RGB_BASE) &&
+ (ptr <= base + MDSS_MDP_REG_IGC_RGB_BASE +
+ MDSS_MDP_GC_SIZE)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int is_valid_calib_dma_addr(char __iomem *ptr)
+{
+ char __iomem *base;
+ int ret = 0, counter = 0;
+ struct mdss_mdp_pipe *pipe;
+
+ for (counter = 0; counter < mdss_res->ndma_pipes; counter++) {
+ pipe = mdss_res->dma_pipes + counter;
+ base = pipe->base;
+
+ if (ptr == base + MDSS_MDP_REG_SSPP_SRC_FORMAT) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ } else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ } else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ /* IGC range */
+ } else if ((ptr >= base + MDSS_MDP_REG_IGC_DMA_BASE) &&
+ (ptr <= base + MDSS_MDP_REG_IGC_DMA_BASE +
+ MDSS_MDP_GC_SIZE)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int is_valid_calib_mixer_addr(char __iomem *ptr)
+{
+ char __iomem *base;
+ int ret = 0, counter = 0;
+ int stage = 0;
+ struct mdss_mdp_mixer *mixer;
+
+ for (counter = 0; counter < mdss_res->nmixers_intf; counter++) {
+ mixer = mdss_res->mixer_intf + counter;
+ base = mixer->base;
+
+ if (ptr == base + MDSS_MDP_REG_LM_OP_MODE) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ /* GC range */
+ } else if ((ptr >= base + MDSS_MDP_REG_LM_GC_LUT_BASE) &&
+ (ptr <= base + MDSS_MDP_REG_LM_GC_LUT_BASE +
+ MDSS_MDP_GC_SIZE)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ break;
+ }
+
+ for (stage = 0; stage < TOTAL_BLEND_STAGES; stage++)
+ if (ptr == base + MDSS_MDP_REG_LM_BLEND_OFFSET(stage) +
+ MDSS_MDP_REG_LM_BLEND_OP) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ goto End;
+ } else if (ptr == base +
+ MDSS_MDP_REG_LM_BLEND_OFFSET(stage) +
+ MDSS_MDP_REG_LM_BLEND_FG_ALPHA) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ goto End;
+ } else if (ptr == base +
+ MDSS_MDP_REG_LM_BLEND_OFFSET(stage) +
+ MDSS_MDP_REG_LM_BLEND_BG_ALPHA) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ goto End;
+ }
+ }
+
+End:
+ return ret;
+}
+
+static int is_valid_calib_addr(void *addr, u32 operation)
{
int ret = 0;
- unsigned int ptr;
- ptr = (unsigned int) addr;
- /* if request is outside the MDP reg-map or is not aligned 4 */
- if (ptr > 0x5138 || ptr % 0x4)
- goto end;
- if (ptr >= 0x100 && ptr <= 0x5138) {
- /* if ptr is in dspp range */
- if (ptr >= 0x4600 && ptr <= 0x5138) {
- /* if ptr is in dspp0 range*/
- if (ptr >= 0x4600 && ptr <= 0x4938)
- ptr -= 0x4600;
- /* if ptr is in dspp1 range */
- else if (ptr >= 0x4a00 && ptr <= 0x4d38)
- ptr -= 0x4a00;
- /* if ptr is in dspp2 range */
- else if (ptr >= 0x4e00 && ptr <= 0x5138)
- ptr -= 0x4e00;
- /* if ptr is in pcc plane rgb coeff.range */
- if (ptr >= 0x30 && ptr <= 0xe8)
- ret = 1;
- /* if ptr is in ARLUT red range */
- else if (ptr >= 0x2b0 && ptr <= 0x2b8)
- ret = 1;
- /* if ptr is in PA range */
- else if (ptr >= 0x238 && ptr <= 0x244)
- ret = 1;
- /* if ptr is in ARLUT green range */
- else if (ptr >= 0x2c0 && ptr <= 0x2c8)
- ret = 1;
- /* if ptr is in ARLUT blue range or
- gamut map table range */
- else if (ptr >= 0x2d0 && ptr <= 0x338)
- ret = 1;
- /* if ptr is dspp0,dspp1,dspp2 op mode
- register */
- else if (ptr == 0)
- ret = 1;
- } else if (ptr >= 0x600 && ptr <= 0x608)
- ret = 1;
- else if (ptr >= 0x400 && ptr <= 0x408)
- ret = 1;
- else if ((ptr == 0x1830) || (ptr == 0x1c30) ||
- (ptr == 0x1430) || (ptr == 0x1e38))
- ret = 1;
- else if ((ptr == 0x1e3c) || (ptr == 0x1e30))
- ret = 1;
- else if (ptr >= 0x3220 && ptr <= 0x3228)
- ret = 1;
- else if (ptr == 0x3200 || ptr == 0x100)
- ret = 1;
- else if (ptr == 0x104 || ptr == 0x614 || ptr == 0x714 ||
- ptr == 0x814 || ptr == 0x914 || ptr == 0xa14)
- ret = 1;
- else if (ptr == 0x618 || ptr == 0x718 || ptr == 0x818 ||
- ptr == 0x918 || ptr == 0xa18)
- ret = 1;
- else if (ptr == 0x2234 || ptr == 0x1e34 || ptr == 0x2634)
- ret = 1;
- } else if (ptr == 0x0)
- ret = 1;
-end:
- return ret;
+ char __iomem *ptr = addr;
+ char __iomem *mixer_base = mdss_res->mixer_intf->base;
+ char __iomem *rgb_base = mdss_res->rgb_pipes->base;
+ char __iomem *dma_base = mdss_res->dma_pipes->base;
+ char __iomem *vig_base = mdss_res->vig_pipes->base;
+ char __iomem *ctl_base = mdss_res->ctl_off->base;
+ char __iomem *dspp_base = mdss_res->mixer_intf->dspp_base;
+
+ if ((unsigned int)addr % 4) {
+ ret = 0;
+ } else if (ptr == (mdss_res->mdp_base + MDSS_MDP_REG_HW_VERSION) ||
+ ptr == (mdss_res->mdp_base + MDSS_MDP_REG_DISP_INTF_SEL)) {
+ ret = MDP_PP_OPS_READ;
+ } else if (ptr >= (mdss_res->mdp_base + MDSS_MDP_REG_IGC_DSPP_BASE) &&
+ ptr < (mdss_res->mdp_base + MDSS_MDP_REG_IGC_DSPP_BASE +
+ MDSS_MDP_IGC_DSPP_COLORS)) {
+ ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+ } else if (ptr >= dspp_base && ptr < (dspp_base +
+ (mdss_res->nmixers_intf * MDSS_MDP_DSPP_ADDRESS_OFFSET))) {
+ ret = is_valid_calib_dspp_addr(ptr);
+ } else if (ptr >= ctl_base && ptr < (ctl_base + (mdss_res->nctl
+ * MDSS_MDP_CTL_ADDRESS_OFFSET))) {
+ ret = is_valid_calib_ctrl_addr(ptr);
+ } else if (ptr >= vig_base && ptr < (vig_base + (mdss_res->nvig_pipes
+ * MDSS_MDP_SSPP_ADDRESS_OFFSET))) {
+ ret = is_valid_calib_vig_addr(ptr);
+ } else if (ptr >= rgb_base && ptr < (rgb_base + (mdss_res->nrgb_pipes
+ * MDSS_MDP_SSPP_ADDRESS_OFFSET))) {
+ ret = is_valid_calib_rgb_addr(ptr);
+ } else if (ptr >= dma_base && ptr < (dma_base + (mdss_res->ndma_pipes
+ * MDSS_MDP_SSPP_ADDRESS_OFFSET))) {
+ ret = is_valid_calib_dma_addr(ptr);
+ } else if (ptr >= mixer_base && ptr < (mixer_base +
+ (mdss_res->nmixers_intf * MDSS_MDP_LM_ADDRESS_OFFSET))) {
+ ret = is_valid_calib_mixer_addr(ptr);
+ }
+
+ return ret & operation;
}
int mdss_mdp_calib_config(struct mdp_calib_config_data *cfg, u32 *copyback)
@@ -4506,11 +4721,12 @@
int ret = -1;
void *ptr = (void *) cfg->addr;
- if (is_valid_calib_addr(ptr))
+ ptr = (void *)(((unsigned int) ptr) + (mdss_res->mdp_base));
+ if (is_valid_calib_addr(ptr, cfg->ops))
ret = 0;
else
return ret;
- ptr = (void *)(((unsigned int) ptr) + (mdss_res->mdp_base));
+
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
if (cfg->ops & MDP_PP_OPS_READ) {
@@ -4545,65 +4761,50 @@
int i = 0;
if (!cfg) {
- pr_err("Invalid buffer pointer");
+ pr_err("Invalid buffer pointer\n");
return ret;
}
- if (cfg->size == 0 || cfg->size > PAGE_SIZE) {
- pr_err("Invalid buffer size %d", cfg->size);
+ if (cfg->size == 0) {
+ pr_err("Invalid buffer size\n");
return ret;
}
counter = cfg->size / (sizeof(uint32_t) * 2);
buff_org = buff = kzalloc(cfg->size, GFP_KERNEL);
if (buff == NULL) {
- pr_err("Allocation failed");
+ pr_err("Config buffer allocation failed\n");
return ret;
}
if (copy_from_user(buff, cfg->buffer, cfg->size)) {
kfree(buff);
- pr_err("Copy failed");
+ pr_err("config buffer copy failed\n");
return ret;
}
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- if (cfg->ops & MDP_PP_OPS_READ) {
- for (i = 0 ; i < counter ; i++) {
- if (is_valid_calib_addr((void *) *buff)) {
- ret = 0;
- } else {
- ret = -1;
- pr_err("Address validation failed");
- break;
- }
+ for (i = 0; i < counter; i++) {
+ ptr = (void *) (((unsigned int) *buff) + mdss_res->mdp_base);
- ptr = (void *)(((unsigned int) *buff) +
- (mdss_res->mdp_base));
- buff++;
+ if (!is_valid_calib_addr(ptr, cfg->ops)) {
+ ret = -1;
+ pr_err("Address validation failed or access not permitted\n");
+ break;
+ }
+
+ buff++;
+ if (cfg->ops & MDP_PP_OPS_READ)
*buff = readl_relaxed(ptr);
- buff++;
- }
- if (!ret)
- ret = copy_to_user(cfg->buffer, buff_org, cfg->size);
- *copyback = 1;
- } else if (cfg->ops & MDP_PP_OPS_WRITE) {
- for (i = 0 ; i < counter ; i++) {
- if (is_valid_calib_addr((void *) *buff)) {
- ret = 0;
- } else {
- ret = -1;
- pr_err("Address validation failed");
- break;
- }
-
- ptr = (void *)(((unsigned int) *buff) +
- (mdss_res->mdp_base));
- buff++;
+ else if (cfg->ops & MDP_PP_OPS_WRITE)
writel_relaxed(*buff, ptr);
- buff++;
- }
+ buff++;
+ }
+
+ if (ret & MDP_PP_OPS_READ) {
+ ret = copy_to_user(cfg->buffer, buff_org, cfg->size);
+ *copyback = 1;
}
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 65275db..a42ff1e 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -272,6 +272,7 @@
u32 type;
u32 wait_cycle;
u32 pdest;
+ u32 brightness_max;
u32 bl_max;
u32 bl_min;
u32 fb_num;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 4903939..0791545 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -800,6 +800,8 @@
DCM_ENTER,
DCM_EXIT,
DCM_BLANK,
+ DTM_ENTER,
+ DTM_EXIT,
};
#define MDSS_PP_SPLIT_LEFT_ONLY 0x10000000
diff --git a/include/linux/regulator/cpr-regulator.h b/include/linux/regulator/cpr-regulator.h
index 624860e..2e2d931 100644
--- a/include/linux/regulator/cpr-regulator.h
+++ b/include/linux/regulator/cpr-regulator.h
@@ -22,20 +22,51 @@
#define CPR_PVS_EFUSE_BINS_MAX (1 << CPR_PVS_EFUSE_BITS_MAX)
/**
+ * enum cpr_fuse_corner_enum - CPR fuse corner enum values
+ * %CPR_FUSE_CORNER_SVS: Lowest voltage for APC
+ * %CPR_FUSE_CORNER_NORMAL: Normal mode voltage
+ * %CPR_FUSE_CORNER_TURBO: Turbo mode voltage
+ * %CPR_FUSE_CORNER_SUPER_TURBO: Super Turbo mode voltage
+ *
+ */
+enum cpr_fuse_corner_enum {
+ CPR_FUSE_CORNER_SVS = 1,
+ CPR_FUSE_CORNER_NORMAL,
+ CPR_FUSE_CORNER_TURBO,
+ CPR_FUSE_CORNER_MAX,
+};
+
+/**
* enum cpr_corner_enum - CPR corner enum values
- * %CPR_CORNER_SVS: Lowest voltage for APC
- * %CPR_CORNER_NORMAL: Normal mode voltage
- * %CPR_CORNER_TURBO: Turbo mode voltage
- * %CPR_CORNER_SUPER_TURBO: Super Turbo mode voltage
+ * %CPR_CORNER_1: Lowest voltage for APC
+ * %CPR_CORNER_2: Second lowest voltage for APC
+ * %CPR_CORNER_3: Third lowest voltage for APC
+ * %CPR_CORNER_4: Forth lowest voltage for APC
+ * %CPR_CORNER_5: Fifth lowest voltage for APC
+ * %CPR_CORNER_6: Sixth lowest voltage for APC
+ * %CPR_CORNER_7: Seventh lowest voltage for APC
+ * %CPR_CORNER_8: Eighth lowest voltage for APC
+ * %CPR_CORNER_9: Ninth lowest voltage for APC
+ * %CPR_CORNER_10: Tenth lowest voltage for APC
+ * %CPR_CORNER_11: Eleventh lowest voltage for APC
+ * %CPR_CORNER_12: Twelfth lowest voltage for APC
*
* These should be used in regulator_set_voltage() for CPR
* regulator as if they had units of uV.
*/
enum cpr_corner_enum {
- CPR_CORNER_SVS = 1,
- CPR_CORNER_NORMAL,
- CPR_CORNER_TURBO,
- CPR_CORNER_MAX,
+ CPR_CORNER_1 = 1,
+ CPR_CORNER_2,
+ CPR_CORNER_3,
+ CPR_CORNER_4,
+ CPR_CORNER_5,
+ CPR_CORNER_6,
+ CPR_CORNER_7,
+ CPR_CORNER_8,
+ CPR_CORNER_9,
+ CPR_CORNER_10,
+ CPR_CORNER_11,
+ CPR_CORNER_12,
};
/**
diff --git a/include/linux/sensors.h b/include/linux/sensors.h
index 3520034..96d2aa6 100644
--- a/include/linux/sensors.h
+++ b/include/linux/sensors.h
@@ -47,9 +47,37 @@
#define SENSOR_TYPE_STEP_COUNTER 19
#define SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR 20
+/**
+ * struct sensors_classdev - hold the sensor general parameters and APIs
+ * @dev: The device to register.
+ * @node: The list for the all the sensor drivers.
+ * @name: Name of this sensor.
+ * @vendor: The vendor of the hardware part.
+ * @handle: The handle that identifies this sensors.
+ * @type: The sensor type.
+ * @max_range: The maximum range of this sensor's value in SI units.
+ * @resolution: The smallest difference between two values reported by
+ * this sensor.
+ * @sensor_power: The rough estimate of this sensor's power consumption
+ * in mA.
+ * @min_delay: This value depends on the trigger mode:
+ * continuous: minimum period allowed in microseconds
+ * on-change : 0
+ * one-shot :-1
+ * special : 0, unless otherwise noted
+ * @fifo_reserved_event_count: The number of events reserved for this sensor
+ * in the batch mode FIFO.
+ * @fifo_max_event_count: The maximum number of events of this sensor
+ * that could be batched.
+ * @enabled: Store the sensor driver enable status.
+ * @delay_msec: Store the sensor driver delay value. The data unit is
+ * millisecond.
+ * @sensors_enable: The handle for enable and disable sensor.
+ * @sensors_poll_delay: The handle for set the sensor polling delay time.
+ */
struct sensors_classdev {
struct device *dev;
- struct list_head node;
+ struct list_head node;
const char *name;
const char *vendor;
int version;
@@ -61,6 +89,13 @@
int min_delay;
int fifo_reserved_event_count;
int fifo_max_event_count;
+ unsigned int enabled;
+ unsigned int delay_msec;
+ /* enable and disable the sensor handle*/
+ int (*sensors_enable)(struct sensors_classdev *sensors_cdev,
+ unsigned int enabled);
+ int (*sensors_poll_delay)(struct sensors_classdev *sensors_cdev,
+ unsigned int delay_msec);
};
extern int sensors_classdev_register(struct device *parent,
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index 6f121b3..5941f71 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -31,7 +31,7 @@
int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params);
int adm_open(int port, int path, int rate, int mode, int topology,
- bool perf_mode, uint16_t bits_per_sample);
+ int perf_mode, uint16_t bits_per_sample);
int adm_get_params(int port_id, uint32_t module_id, uint32_t param_id,
uint32_t params_length, char *params);
@@ -40,7 +40,7 @@
uint32_t params_length);
int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
- int topology, bool perf_mode, uint16_t bits_per_sample);
+ int topology, int perf_mode, uint16_t bits_per_sample);
int adm_unmap_cal_blocks(void);
@@ -53,10 +53,10 @@
int adm_memory_unmap_regions(int port_id);
-int adm_close(int port, bool perf_mode);
+int adm_close(int port, int perf_mode);
int adm_matrix_map(int session_id, int path, int num_copps,
- unsigned int *port_id, int copp_id, bool perf_mode);
+ unsigned int *port_id, int copp_id, int perf_mode);
int adm_connect_afe_port(int mode, int session_id, int port_id);
@@ -64,6 +64,8 @@
int adm_get_copp_id(int port_id);
+int adm_get_lowlatency_copp_id(int port_id);
+
void adm_set_multi_ch_map(char *channel_map);
void adm_get_multi_ch_map(char *channel_map);
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index b00cfc9..a78c333 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -175,7 +175,7 @@
struct audio_port_data port[2];
wait_queue_head_t cmd_wait;
wait_queue_head_t time_wait;
- bool perf_mode;
+ int perf_mode;
int stream_id;
/* audio cache operations fptr*/
int (*fptr_cache_ops)(struct audio_buffer *abuff, int cache_op);
diff --git a/include/sound/q6audio-v2.h b/include/sound/q6audio-v2.h
index fd6a490..8ac835c 100644
--- a/include/sound/q6audio-v2.h
+++ b/include/sound/q6audio-v2.h
@@ -15,6 +15,13 @@
#include <mach/qdsp6v2/apr.h>
+enum {
+ LEGACY_PCM_MODE = 0,
+ LOW_LATENCY_PCM_MODE,
+ ULTRA_LOW_LATENCY_PCM_MODE,
+};
+
+
int q6audio_get_port_index(u16 port_id);
int q6audio_convert_virtual_to_portid(u16 port_id);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index fa8a793..e174693 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -184,6 +184,36 @@
return ret;
}
+#ifdef ENABLE_VMALLOC_SAVING
+int is_vmalloc_addr(const void *x)
+{
+ struct rb_node *n;
+ struct vmap_area *va;
+ int ret = 0;
+
+ spin_lock(&vmap_area_lock);
+
+ for (n = rb_first(vmap_area_root); n; rb_next(n)) {
+ va = rb_entry(n, struct vmap_area, rb_node);
+ if (x >= va->va_start && x < va->va_end) {
+ ret = 1;
+ break;
+ }
+ }
+
+ spin_unlock(&vmap_area_lock);
+ return ret;
+}
+#else
+int is_vmalloc_addr(const void *x)
+{
+ unsigned long addr = (unsigned long)x;
+
+ return addr >= VMALLOC_START && addr < VMALLOC_END;
+}
+#endif
+EXPORT_SYMBOL(is_vmalloc_addr);
+
int is_vmalloc_or_module_addr(const void *x)
{
/*
@@ -272,47 +302,6 @@
static unsigned long vmap_area_pcpu_hole;
-#ifdef CONFIG_ENABLE_VMALLOC_SAVING
-int is_vmalloc_addr(const void *x)
-{
- struct vmap_area *va;
- int ret = 0;
-
- spin_lock(&vmap_area_lock);
- list_for_each_entry(va, &vmap_area_list, list) {
- if (va->flags & (VM_LAZY_FREE | VM_LAZY_FREEING))
- continue;
-
- if (!(va->flags & VM_VM_AREA))
- continue;
-
- if (va->vm == NULL)
- continue;
-
- if (va->vm->flags & VM_LOWMEM)
- continue;
-
- if ((unsigned long)x >= va->va_start &&
- (unsigned long)x < va->va_end) {
- ret = 1;
- break;
- }
- }
- spin_unlock(&vmap_area_lock);
- return ret;
-}
-#else
-int is_vmalloc_addr(const void *x)
-{
- unsigned long addr = (unsigned long)x;
-
- return addr >= VMALLOC_START && addr < VMALLOC_END;
-}
-#endif
-EXPORT_SYMBOL(is_vmalloc_addr);
-
-
-
static struct vmap_area *__find_vmap_area(unsigned long addr)
{
struct rb_node *n = vmap_area_root.rb_node;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index bddb720..b094741 100755
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1510,8 +1510,8 @@
if (wiphy_idx_valid(reg_request->wiphy_idx))
wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
- if (reg_initiator == NL80211_REGDOM_SET_BY_DRIVER &&
- !wiphy) {
+ if ((reg_initiator == NL80211_REGDOM_SET_BY_DRIVER ||
+ reg_initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) && !wiphy) {
kfree(reg_request);
return;
}
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index c62f875..f874c43 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -3404,6 +3404,7 @@
TAIKO_A_TX_7_MBHC_EN, 0x80, 00);
ret |= taiko_codec_enable_anc(w, kcontrol, event);
}
+ break;
case SND_SOC_DAPM_POST_PMD:
ret = taiko_hph_pa_event(w, kcontrol, event);
break;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 69a6671..4c3a72e 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -2203,6 +2203,22 @@
.codec_name = "snd-soc-dummy",
},
{
+ .name = "Voice2",
+ .stream_name = "Voice2",
+ .cpu_dai_name = "Voice2",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_VOICE2,
+ },
+ {
.name = "INT_HFP_BT Hostless",
.stream_name = "INT_HFP_BT Hostless",
.cpu_dai_name = "INT_HFP_BT_HOSTLESS",
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index f25f746..3ddc3e0 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -25,6 +25,7 @@
#include <sound/pcm.h>
#include <sound/initval.h>
#include <sound/control.h>
+#include <sound/q6audio-v2.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/msm_audio_ion.h>
@@ -916,11 +917,12 @@
int rc;
int id;
struct msm_plat_data *pdata;
+ const char *latency_level;
rc = of_property_read_u32(pdev->dev.of_node,
- "qcom,msm-pcm-dsp-id", &id);
+ "qti,msm-pcm-dsp-id", &id);
if (rc) {
- dev_err(&pdev->dev, "%s: qcom,msm-pcm-dsp-id missing in DT node\n",
+ dev_err(&pdev->dev, "%s: qti,msm-pcm-dsp-id missing in DT node\n",
__func__);
return rc;
}
@@ -932,10 +934,17 @@
}
if (of_property_read_bool(pdev->dev.of_node,
- "qcom,msm-pcm-low-latency"))
- pdata->perf_mode = 1;
- else
- pdata->perf_mode = 0;
+ "qti,msm-pcm-low-latency")) {
+
+ pdata->perf_mode = LOW_LATENCY_PCM_MODE;
+ rc = of_property_read_string(pdev->dev.of_node,
+ "qti,latency-level", &latency_level);
+ if (!rc) {
+ if (!strcmp(latency_level, "ultra"))
+ pdata->perf_mode = ULTRA_LOW_LATENCY_PCM_MODE;
+ }
+ } else
+ pdata->perf_mode = LEGACY_PCM_MODE;
dev_set_drvdata(&pdev->dev, pdata);
@@ -957,7 +966,7 @@
return 0;
}
static const struct of_device_id msm_pcm_dt_match[] = {
- {.compatible = "qcom,msm-pcm-dsp"},
+ {.compatible = "qti,msm-pcm-dsp"},
{}
};
MODULE_DEVICE_TABLE(of, msm_pcm_dt_match);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 711291da..91c0744 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -290,7 +290,7 @@
/* Track performance mode of all front-end multimedia sessions.
* Performance mode is only valid when session is valid.
*/
-static bool fe_dai_perf_mode[MSM_FRONTEND_DAI_MM_SIZE][2];
+static int fe_dai_perf_mode[MSM_FRONTEND_DAI_MM_SIZE][2];
static uint8_t is_be_dai_extproc(int be_dai)
{
@@ -303,7 +303,7 @@
}
static void msm_pcm_routing_build_matrix(int fedai_id, int dspst_id,
- int path_type, bool perf_mode)
+ int path_type, int perf_mode)
{
int i, port_type;
struct route_payload payload;
@@ -365,7 +365,7 @@
mutex_unlock(&routing_lock);
}
-void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode,
+void msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
int dspst_id, int stream_type)
{
int i, session_type, path_type, port_type, port_id, topology;
@@ -437,7 +437,7 @@
port_id = srs_port_id = msm_bedais[i].port_id;
srs_send_params(srs_port_id, 1, 0);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (!perf_mode))
+ (perf_mode == LEGACY_PCM_MODE))
if (dolby_dap_init(port_id,
msm_bedais[i].channel) < 0)
pr_err("%s: Err init dolby dap\n",
@@ -494,7 +494,8 @@
adm_close(msm_bedais[i].port_id,
fe_dai_perf_mode[fedai_id][session_type]);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (fe_dai_perf_mode[fedai_id][session_type] == false))
+ (fe_dai_perf_mode[fedai_id][session_type] ==
+ LEGACY_PCM_MODE))
dolby_dap_deinit(msm_bedais[i].port_id);
}
}
@@ -604,7 +605,8 @@
port_id = srs_port_id = msm_bedais[reg].port_id;
srs_send_params(srs_port_id, 1, 0);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (fe_dai_perf_mode[val][session_type] == false))
+ (fe_dai_perf_mode[val][session_type] ==
+ LEGACY_PCM_MODE))
if (dolby_dap_init(port_id, channels) < 0)
pr_err("%s: Err init dolby dap\n",
__func__);
@@ -621,7 +623,8 @@
adm_close(msm_bedais[reg].port_id,
fe_dai_perf_mode[val][session_type]);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (fe_dai_perf_mode[val][session_type] == false))
+ (fe_dai_perf_mode[val][session_type] ==
+ LEGACY_PCM_MODE))
dolby_dap_deinit(msm_bedais[reg].port_id);
msm_pcm_routing_build_matrix(val,
fdai->strm_id, path_type,
@@ -3960,7 +3963,8 @@
fe_dai_perf_mode[i][session_type]);
srs_port_id = -1;
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (fe_dai_perf_mode[i][session_type] == false))
+ (fe_dai_perf_mode[i][session_type] ==
+ LEGACY_PCM_MODE))
dolby_dap_deinit(bedai->port_id);
}
}
@@ -4060,7 +4064,8 @@
port_id = srs_port_id = bedai->port_id;
srs_send_params(srs_port_id, 1, 0);
if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
- (fe_dai_perf_mode[i][session_type] == false))
+ (fe_dai_perf_mode[i][session_type] ==
+ LEGACY_PCM_MODE))
if (dolby_dap_init(port_id, channels) < 0)
pr_err("%s: Err init dolby dap\n",
__func__);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 4f7c4e3..54f5e4a 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -143,7 +143,7 @@
* dspst_id: DSP audio stream ID
* stream_type: playback or capture
*/
-void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode, int dspst_id,
+void msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, int dspst_id,
int stream_type);
void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
int stream_type);
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 6cb7ce1..54b1263 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -702,7 +702,8 @@
return;
}
-static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
+static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal,
+ int perf_mode)
{
s32 result = 0;
struct adm_cmd_set_pp_params_v5 adm_params;
@@ -731,7 +732,14 @@
adm_params.hdr.src_port = port_id;
adm_params.hdr.dest_svc = APR_SVC_ADM;
adm_params.hdr.dest_domain = APR_DOMAIN_ADSP;
- adm_params.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+
+ if (perf_mode == LEGACY_PCM_MODE)
+ adm_params.hdr.dest_port =
+ atomic_read(&this_adm.copp_id[index]);
+ else
+ adm_params.hdr.dest_port =
+ atomic_read(&this_adm.copp_low_latency_id[index]);
+
adm_params.hdr.token = port_id;
adm_params.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
adm_params.payload_addr_lsw = aud_cal->cal_paddr;
@@ -767,7 +775,7 @@
return result;
}
-static void send_adm_cal(int port_id, int path)
+static void send_adm_cal(int port_id, int path, int perf_mode)
{
int result = 0;
s32 acdb_path;
@@ -808,7 +816,7 @@
}
}
- if (!send_adm_cal_block(port_id, &aud_cal))
+ if (!send_adm_cal_block(port_id, &aud_cal, perf_mode))
pr_debug("%s: Audproc cal sent for port id: %#x, path %d\n",
__func__, port_id, acdb_path);
else
@@ -842,7 +850,7 @@
}
}
- if (!send_adm_cal_block(port_id, &aud_cal))
+ if (!send_adm_cal_block(port_id, &aud_cal, perf_mode))
pr_debug("%s: Audvol cal sent for port id: %#x, path %d\n",
__func__, port_id, acdb_path);
else
@@ -1048,7 +1056,7 @@
}
int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
- bool perf_mode, uint16_t bits_per_sample)
+ int perf_mode, uint16_t bits_per_sample)
{
struct adm_cmd_device_open_v5 open;
int ret = 0;
@@ -1079,7 +1087,7 @@
rtac_set_adm_handle(this_adm.apr);
}
- if (!perf_mode) {
+ if (perf_mode == LEGACY_PCM_MODE) {
atomic_set(&this_adm.copp_perf_mode[index], 0);
send_adm_custom_topology(port_id);
} else {
@@ -1087,8 +1095,9 @@
}
/* Create a COPP if port id are not enabled */
- if ((!perf_mode && (atomic_read(&this_adm.copp_cnt[index]) == 0)) ||
- (perf_mode &&
+ if ((perf_mode == LEGACY_PCM_MODE &&
+ (atomic_read(&this_adm.copp_cnt[index]) == 0)) ||
+ (perf_mode != LEGACY_PCM_MODE &&
(atomic_read(&this_adm.copp_low_latency_cnt[index]) == 0))) {
pr_debug("%s:opening ADM: perf_mode: %d\n", __func__,
perf_mode);
@@ -1103,12 +1112,12 @@
open.hdr.dest_port = tmp_port;
open.hdr.token = port_id;
open.hdr.opcode = ADM_CMD_DEVICE_OPEN_V5;
- open.flags = 0x00;
- if (perf_mode) {
- open.flags |= ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
- } else {
- open.flags |= ADM_LEGACY_DEVICE_SESSION;
- }
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE)
+ open.flags = ADM_ULTRA_LOW_LATENCY_DEVICE_SESSION;
+ else if (perf_mode == LOW_LATENCY_PCM_MODE)
+ open.flags = ADM_LOW_LATENCY_DEVICE_SESSION;
+ else
+ open.flags = ADM_LEGACY_DEVICE_SESSION;
open.mode_of_operation = path;
open.endpoint_id_1 = tmp_port;
@@ -1125,7 +1134,7 @@
(open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
rate = 16000;
- if (perf_mode) {
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) {
open.topology_id = NULL_COPP_TOPOLOGY;
rate = ULL_SUPPORTED_SAMPLE_RATE;
if(channel_mode > ULL_MAX_SUPPORTED_CHANNEL)
@@ -1133,7 +1142,8 @@
}
open.dev_num_channel = channel_mode & 0x00FF;
open.bit_width = bits_per_sample;
- WARN_ON(perf_mode && (rate != 48000));
+ WARN_ON(perf_mode == ULTRA_LOW_LATENCY_PCM_MODE &&
+ (rate != 48000));
open.sample_rate = rate;
memset(open.dev_channel_mapping, 0, 8);
@@ -1208,7 +1218,8 @@
goto fail_cmd;
}
}
- if (perf_mode) {
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE) {
atomic_inc(&this_adm.copp_low_latency_cnt[index]);
pr_debug("%s: index: %d coppid: %d", __func__, index,
atomic_read(&this_adm.copp_low_latency_id[index]));
@@ -1225,7 +1236,7 @@
}
int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
- int topology, bool perf_mode, uint16_t bits_per_sample)
+ int topology, int perf_mode, uint16_t bits_per_sample)
{
int ret = 0;
@@ -1236,7 +1247,7 @@
}
int adm_matrix_map(int session_id, int path, int num_copps,
- unsigned int *port_id, int copp_id, bool perf_mode)
+ unsigned int *port_id, int copp_id, int perf_mode)
{
struct adm_cmd_matrix_map_routings_v5 *route;
struct adm_session_map_node_v5 *node;
@@ -1275,7 +1286,8 @@
route->hdr.src_port = copp_id;
route->hdr.dest_svc = APR_SVC_ADM;
route->hdr.dest_domain = APR_DOMAIN_ADSP;
- if (perf_mode) {
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE) {
route->hdr.dest_port =
atomic_read(&this_adm.copp_low_latency_id[index]);
} else {
@@ -1313,7 +1325,8 @@
if (tmp >= 0 && tmp < AFE_MAX_PORTS) {
- if (perf_mode)
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE)
copps_list[i] =
atomic_read(&this_adm.copp_low_latency_id[tmp]);
else
@@ -1323,8 +1336,7 @@
else
continue;
pr_debug("%s: port_id[%#x]: %d, index: %d act coppid[0x%x]\n",
- __func__, i, port_id[i], tmp,
- atomic_read(&this_adm.copp_id[tmp]));
+ __func__, i, port_id[i], tmp, copps_list[i]);
}
atomic_set(&this_adm.copp_stat[index], 0);
@@ -1344,25 +1356,31 @@
ret = -EINVAL;
goto fail_cmd;
}
- if (!perf_mode) {
+
+ if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
for (i = 0; i < num_copps; i++)
- send_adm_cal(port_id[i], path);
+ send_adm_cal(port_id[i], path, perf_mode);
for (i = 0; i < num_copps; i++) {
- int tmp;
+ int tmp, copp_id;
tmp = afe_get_port_index(port_id[i]);
if (tmp >= 0 && tmp < AFE_MAX_PORTS) {
+ if (perf_mode == LEGACY_PCM_MODE)
+ copp_id = atomic_read(
+ &this_adm.copp_id[tmp]);
+ else
+ copp_id = atomic_read(
+ &this_adm.copp_low_latency_id[tmp]);
rtac_add_adm_device(port_id[i],
- atomic_read(&this_adm.copp_id[tmp]),
- path, session_id);
- pr_debug("%s, copp_id: %d\n", __func__,
- atomic_read(&this_adm.copp_id[tmp]));
- } else {
+ copp_id, path, session_id);
+ pr_debug("%s, copp_id: %d\n",
+ __func__, copp_id);
+ } else
pr_debug("%s: Invalid port index %d",
- __func__, tmp);
- }
+ __func__, tmp);
}
}
+
fail_cmd:
kfree(matrix_map);
return ret;
@@ -1514,8 +1532,26 @@
return ret;
}
+#ifdef CONFIG_RTAC
int adm_get_copp_id(int port_index)
{
+ int copp_id;
+ pr_debug("%s\n", __func__);
+
+ if (port_index < 0) {
+ pr_err("%s: invalid port_id = %d\n", __func__, port_index);
+ return -EINVAL;
+ }
+
+ copp_id = atomic_read(&this_adm.copp_id[port_index]);
+ if (copp_id == RESET_COPP_ID)
+ copp_id = atomic_read(
+ &this_adm.copp_low_latency_id[port_index]);
+ return copp_id;
+}
+
+int adm_get_lowlatency_copp_id(int port_index)
+{
pr_debug("%s\n", __func__);
if (port_index < 0) {
@@ -1523,8 +1559,19 @@
return -EINVAL;
}
- return atomic_read(&this_adm.copp_id[port_index]);
+ return atomic_read(&this_adm.copp_low_latency_id[port_index]);
}
+#else
+int adm_get_copp_id(int port_index)
+{
+ return -EINVAL;
+}
+
+int adm_get_lowlatency_copp_id(int port_index)
+{
+ return -EINVAL;
+}
+#endif /* #ifdef CONFIG_RTAC */
void adm_ec_ref_rx_id(int port_id)
{
@@ -1532,12 +1579,13 @@
pr_debug("%s ec_ref_rx:%d", __func__, this_adm.ec_ref_rx);
}
-int adm_close(int port_id, bool perf_mode)
+int adm_close(int port_id, int perf_mode)
{
struct apr_hdr close;
int ret = 0;
int index = 0;
+ int copp_id = RESET_COPP_ID;
port_id = q6audio_convert_virtual_to_portid(port_id);
@@ -1548,7 +1596,8 @@
pr_debug("%s port_id=%#x index %d perf_mode: %d\n", __func__, port_id,
index, perf_mode);
- if (perf_mode) {
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE) {
if (!(atomic_read(&this_adm.copp_low_latency_cnt[index]))) {
pr_err("%s: copp count for port[%#x]is 0\n", __func__,
port_id);
@@ -1563,8 +1612,9 @@
}
atomic_dec(&this_adm.copp_cnt[index]);
}
- if ((!perf_mode && !(atomic_read(&this_adm.copp_cnt[index]))) ||
- (perf_mode &&
+ if ((perf_mode == LEGACY_PCM_MODE &&
+ !(atomic_read(&this_adm.copp_cnt[index]))) ||
+ ((perf_mode != LEGACY_PCM_MODE) &&
!(atomic_read(&this_adm.copp_low_latency_cnt[index])))) {
pr_debug("%s:Closing ADM: perf_mode: %d\n", __func__,
@@ -1577,7 +1627,8 @@
close.src_port = port_id;
close.dest_svc = APR_SVC_ADM;
close.dest_domain = APR_DOMAIN_ADSP;
- if (perf_mode)
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE)
close.dest_port =
atomic_read(&this_adm.copp_low_latency_id[index]);
else
@@ -1587,18 +1638,23 @@
atomic_set(&this_adm.copp_stat[index], 0);
- if (perf_mode) {
+ if (perf_mode == ULTRA_LOW_LATENCY_PCM_MODE ||
+ perf_mode == LOW_LATENCY_PCM_MODE) {
+ copp_id = atomic_read(
+ &this_adm.copp_low_latency_id[index]);
pr_debug("%s:coppid %d portid=%#x index=%d coppcnt=%d\n",
- __func__,
- atomic_read(&this_adm.copp_low_latency_id[index]),
- port_id, index,
- atomic_read(&this_adm.copp_low_latency_cnt[index]));
+ __func__,
+ copp_id,
+ port_id, index,
+ atomic_read(
+ &this_adm.copp_low_latency_cnt[index]));
atomic_set(&this_adm.copp_low_latency_id[index],
RESET_COPP_ID);
} else {
+ copp_id = atomic_read(&this_adm.copp_id[index]);
pr_debug("%s:coppid %d portid=%#x index=%d coppcnt=%d\n",
__func__,
- atomic_read(&this_adm.copp_id[index]),
+ copp_id,
port_id, index,
atomic_read(&this_adm.copp_cnt[index]));
atomic_set(&this_adm.copp_id[index],
@@ -1623,9 +1679,9 @@
}
}
- if (!perf_mode) {
+ if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
pr_debug("%s: remove adm device from rtac\n", __func__);
- rtac_remove_adm_device(port_id);
+ rtac_remove_adm_device(port_id, copp_id);
}
fail_cmd:
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 631e9bd..24f5f3b 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -39,6 +39,7 @@
#include <sound/apr_audio-v2.h>
#include <sound/q6asm-v2.h>
+#include <sound/q6audio-v2.h>
#include "audio_acdb.h"
@@ -354,7 +355,7 @@
session[ac->session] = 0;
mutex_unlock(&session_lock);
ac->session = 0;
- ac->perf_mode = 0;
+ ac->perf_mode = LEGACY_PCM_MODE;
ac->fptr_cache_ops = NULL;
return;
}
@@ -810,7 +811,7 @@
ac->cb = cb;
ac->priv = priv;
ac->io_mode = SYNC_IO_MODE;
- ac->perf_mode = false;
+ ac->perf_mode = LEGACY_PCM_MODE;
ac->fptr_cache_ops = NULL;
ac->apr = apr_register("ADSP", "ASM", \
(apr_fn)q6asm_callback,\
@@ -1695,7 +1696,7 @@
open.bits_per_sample = bits_per_sample;
open.mode_flags = 0x0;
- if (ac->perf_mode) {
+ if (ac->perf_mode == LOW_LATENCY_PCM_MODE) {
open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION <<
ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ;
} else {
@@ -1781,8 +1782,10 @@
open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3;
open.mode_flags = 0x00;
- if (ac->perf_mode)
+ if (ac->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE)
open.mode_flags |= ASM_ULTRA_LOW_LATENCY_STREAM_SESSION;
+ else if (ac->perf_mode == LOW_LATENCY_PCM_MODE)
+ open.mode_flags |= ASM_LOW_LATENCY_STREAM_SESSION;
else {
open.mode_flags |= ASM_LEGACY_STREAM_SESSION;
if (is_gapless_mode)
diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c
index f74dbe2..701dfef 100644
--- a/sound/soc/msm/qdsp6v2/rtac.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -556,7 +556,8 @@
/* Check if device already added */
if (rtac_adm_data.num_of_dev != 0) {
for (; i < rtac_adm_data.num_of_dev; i++) {
- if (rtac_adm_data.device[i].afe_port == port_id) {
+ if (rtac_adm_data.device[i].afe_port == port_id &&
+ rtac_adm_data.device[i].copp == copp_id) {
add_popp(i, port_id, popp_id);
goto done;
}
@@ -609,7 +610,7 @@
}
}
-void rtac_remove_adm_device(u32 port_id)
+void rtac_remove_adm_device(u32 port_id, u32 copp_id)
{
s32 i;
pr_debug("%s: port_id = %d\n", __func__, port_id);
@@ -619,7 +620,8 @@
/* look for device */
for (i = 0; i < rtac_adm_data.num_of_dev; i++) {
- if (rtac_adm_data.device[i].afe_port == port_id) {
+ if (rtac_adm_data.device[i].afe_port == port_id &&
+ rtac_adm_data.device[i].copp == copp_id) {
memset(&rtac_adm_data.device[i], 0,
sizeof(rtac_adm_data.device[i]));
rtac_adm_data.num_of_dev--;
@@ -870,6 +872,8 @@
for (port_index = 0; port_index < AFE_MAX_PORTS; port_index++) {
if (adm_get_copp_id(port_index) == copp_id)
break;
+ if (adm_get_lowlatency_copp_id(port_index) == copp_id)
+ break;
}
if (port_index >= AFE_MAX_PORTS) {
pr_err("%s: Could not find port index for copp = %d\n",
diff --git a/sound/usb/card.c b/sound/usb/card.c
index f453dbd..d419e2f 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -205,11 +205,24 @@
struct usb_device *dev = chip->dev;
struct usb_host_interface *host_iface;
struct usb_interface_descriptor *altsd;
+ struct usb_interface *usb_iface;
void *control_header;
int i, protocol;
+ usb_iface = usb_ifnum_to_if(dev, ctrlif);
+ if (!usb_iface) {
+ snd_printk(KERN_ERR "%d:%u : does not exist\n",
+ dev->devnum, ctrlif);
+ return -EINVAL;
+ }
+
/* find audiocontrol interface */
- host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
+ host_iface = &usb_iface->altsetting[0];
+ if (!host_iface) {
+ snd_printk(KERN_ERR "Audio Control interface is not available.");
+ return -EINVAL;
+ }
+
control_header = snd_usb_find_csint_desc(host_iface->extra,
host_iface->extralen,
NULL, UAC_HEADER);
@@ -248,8 +261,7 @@
case UAC_VERSION_2: {
struct usb_interface_assoc_descriptor *assoc =
- usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
-
+ usb_iface->intf_assoc;
if (!assoc) {
snd_printk(KERN_ERR "Audio class v2 interfaces need an interface association\n");
return -EINVAL;
@@ -723,6 +735,11 @@
}
usbaudiosdev = kzalloc(sizeof(*usbaudiosdev), GFP_KERNEL);
+ if (!usbaudiosdev) {
+ pr_err("Usb audio device memory allocation failed.\n");
+ return -ENOMEM;
+ }
+
usbaudiosdev->name = "usb_audio";
err = switch_dev_register(usbaudiosdev);