Merge "msm: board-qrd7627a: Regulator configuration for 8625Q device"
diff --git a/Documentation/ABI/testing/sysfs-kernel-iommu_groups b/Documentation/ABI/testing/sysfs-kernel-iommu_groups
new file mode 100644
index 0000000..9b31556
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-kernel-iommu_groups
@@ -0,0 +1,14 @@
+What: /sys/kernel/iommu_groups/
+Date: May 2012
+KernelVersion: v3.5
+Contact: Alex Williamson <alex.williamson@redhat.com>
+Description: /sys/kernel/iommu_groups/ contains a number of sub-
+ directories, each representing an IOMMU group. The
+ name of the sub-directory matches the iommu_group_id()
+ for the group, which is an integer value. Within each
+ subdirectory is another directory named "devices" with
+ links to the sysfs devices contained in this group.
+ The group directory also optionally contains a "name"
+ file if the IOMMU driver has chosen to register a more
+ common name for the group.
+Users:
diff --git a/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt b/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt
index b7dd427..f8152cfb 100644
--- a/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt
+++ b/Documentation/devicetree/bindings/arm/msm/dcvs-core-info.txt
@@ -37,9 +37,9 @@
- qcom,algo-ss-win-size-max-us: sets maximum steady state window size.
- qcom,algo-ss-util-pct: sets target CPU utilization during
steady-state.
-- qcom,algo-ss-iobusy-conv: specifies how wait time (i/o busy time)
- is incorporated into the steady-state
- algorithm.
+- qcom,algo-ss-no-corr-below-freq: specifies frequency below which DCVS
+ will not attempt to correlate busy or
+ idle information from different CPUs
- qcom,energy-active-coeff-a: sets active power equation coefficient a.
- qcom,energy-active-coeff-b: sets active power equation coefficient b.
@@ -89,7 +89,7 @@
qcom,algo-ss-win-size-min-us = <1000000>;
qcom,algo-ss-win-size-max-us = <1000000>;
qcom,algo-ss-util-pct = <95>;
- qcom,algo-ss-iobusy-conv = <100>;
+ qcom,algo-ss-no-corr-below-freq = <0>;
qcom,energy-active-coeff-a = <2492>;
qcom,energy-active-coeff-b = <0>;
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index 9164647..2ea9ba9 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -132,7 +132,7 @@
qcom,algo-ss-window-size = <1000000>;
qcom,algo-ss-util-pct = <95>;
qcom,algo-em-max-util-pct = <97>;
- qcom,algo-ss-iobusy-conv = <100>;
+ qcom,algo-ss-no-corr-below-freq = <0>;
qcom,dcvs-freq@0 {
reg = <0>;
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 4d571eb..af8d45c 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -4,24 +4,17 @@
to the battery. It's main function is to calculate the State of Charge (SOC),
a 0-100 percentage representing the amount of charge left in the battery.
-BMS node
+There are two required peripherals in the BMS driver, both implemented as
+subnodes in the example. These peripherals must not be disabled if the BMS
+device is to enabled:
+- qcom,bms-bms : The main BMS device. Supports battery monitoring controls and
+ sensors.
+- qcom,bms-iadc : The BMS IADC peripheral in the IADC device. This is required
+ to determine whether the BMS is using an internal or external
+ rsense to accumulate the Coulomb Counter and read current.
-Required properties:
+Parent node required properties:
- compatible : should be "qcom,qpnp-bms" for the BM driver.
-- reg : offset and length of the PMIC BMS register map.
-- interrupts : the interrupt mappings for bms.
- The format should be
- <slave-id peripheral-id interrupt-number>.
-- interrupt-names : names for the mapped bms interrupt
- The following interrupts are required:
- 0 : vsense_for_r
- 1 : vsense_avg
- 2 : sw_cc_thr
- 3 : ocv_thr
- 4 : charge_begin
- 5 : good_ocv
- 6 : ocv_for_r
- 7 : cc_thr
- qcom,bms-r-sense-mohm : sensor resistance in in milli-ohms.
- qcom,bms-v-cutoff-uv : cutoff voltage where the battery is considered dead in
micro-volts.
@@ -56,7 +49,7 @@
to the enum defined in
include/linux/mfd/pm8xxx/batterydata-lib.h
-Optional properties:
+Parent node optional properties:
- qcom,bms-ignore-shutdown-soc: A boolean that controls whether BMS will
try to force the startup SoC to be the same as the
shutdown SoC. Defining it will make BMS ignore the
@@ -65,14 +58,51 @@
voltage-based SoC instead of a coulomb counter based
one. Voltage-based SoC will not guarantee linearity.
+All sub node required properties:
+- reg : offset and length of the PMIC peripheral register map.
+
+qcom,bms-bms node required properties:
+- interrupts : the interrupt mappings.
+ The format should be
+ <slave-id peripheral-id interrupt-number>.
+- interrupt-names : names for the mapped bms interrupt
+ The following interrupts are required:
+ 0 : vsense_for_r
+ 1 : vsense_avg
+ 2 : sw_cc_thr
+ 3 : ocv_thr
+ 4 : charge_begin
+ 5 : good_ocv
+ 6 : ocv_for_r
+ 7 : cc_thr
+
Example:
- bms@4000 {
- #address-cells = <1>;
- #size-cells = <1>;
+pm8941_bms: qcom,bms {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-bms";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
- compatible = "qcom,qpnp-bms";
+ qcom,bms-r-sense-mohm = <2>;
+ qcom,bms-v-cutoff-uv = <3400000>;
+ qcom,bms-max-voltage-uv = <4200000>;
+ qcom,bms-r-conn-mohm = <18>;
+ qcom,bms-shutdown-soc-valid-limit = <20>;
+ qcom,bms-adjust-soc-low-threshold = <25>;
+ qcom,bms-adjust-soc-high-threshold = <45>;
+ qcom,bms-low-soc-calculate-soc-threshold = <15>;
+ qcom,bms-low-soc-calculate-soc-ms = <5000>;
+ qcom,bms-calculate-soc-ms = <20000>;
+ qcom,bms-chg-term-ua = <100000>;
+ qcom,bms-batt-type = <0>;
+
+ qcom,bms-iadc@3800 {
+ reg = <0x3800 0x100>;
+ };
+
+ qcom,bms-bms@4000 {
reg = <0x4000 0x100>;
-
interrupts = <0x0 0x40 0x0>,
<0x0 0x40 0x1>,
<0x0 0x40 0x2>,
@@ -90,18 +120,5 @@
"good_ocv",
"ocv_for_r",
"cc_thr";
-
- qcom,bms-r-sense-mohm = <10>;
- qcom,bms-v-cutoff-uv = <3400000>;
- qcom,bms-max-voltage-uv = <4200000>;
- qcom,bms-r-conn-mohm = <18>;
- qcom,bms-shutdown-soc-valid-limit = <20>;
- qcom,bms-adjust-soc-low-threshold = <25>;
- qcom,bms-adjust-soc-high-threshold = <45>;
- qcom,bms-low-soc-calculate-soc-threshold = <15>;
- qcom,bms-low-soc-calculate-soc-ms = <5000>;
- qcom,bms-calculate-soc-ms = <20000>;
- qcom,bms-chg-term-ua = <100000>;
- qcom,bms-batt-type = <0>;
- qcom,bms-ignore-shutdown-soc;
};
+};
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index c47d442..8cc509a 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -87,6 +87,7 @@
BT SCO port ID value from 12288 to 12289
RT Proxy port ID values from 224 to 225 and 240 to 241
FM Rx and TX port ID values from 12292 to 12293
+ incall record Rx and TX port ID values from 32771 to 32772
* msm-auxpcm
@@ -286,6 +287,16 @@
compatible = "qcom,msm-dai-q6-dev";
qcom,msm-dai-q6-dev-id = <240>;
};
+
+ qcom,msm-dai-q6-incall-record-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32771>;
+ };
+
+ qcom,msm-dai-q6-incall-record-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32772>;
+ };
};
qcom,msm-auxpcm {
diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
index 090d8db..74c25a0 100644
--- a/Documentation/devicetree/bindings/sound/taiko_codec.txt
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -34,7 +34,7 @@
- qcom,cdc-micbias2-ext-cap: Boolean. Enable micbias 2 external capacitor mode.
- qcom,cdc-micbias3-ext-cap: Boolean. Enable micbias 3 external capacitor mode.
- qcom,cdc-micbias4-ext-cap: Boolean. Enable micbias 4 external capacitor mode.
-
+ - qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for codec.
- qcom,cdc-slim-ifd-dev - namme of the codec slim interface device.
- qcom,cdc-slim-ifd-elemental-addr - codec slimbus slave interface device
enumeration address.
@@ -86,7 +86,7 @@
qcom,cdc-micbias2-ext-cap;
qcom,cdc-micbias3-ext-cap;
qcom,cdc-micbias4-ext-cap;
-
+ qcom,cdc-mclk-clk-rate = <9600000>;
qcom,cdc-slim-ifd = "taiko-slim-ifd";
qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
};
@@ -123,6 +123,7 @@
- qcom,cdc-micbias2-ext-cap: Boolean. Enable micbias 2 external capacitor mode.
- qcom,cdc-micbias3-ext-cap: Boolean. Enable micbias 3 external capacitor mode.
- qcom,cdc-micbias4-ext-cap: Boolean. Enable micbias 4 external capacitor mode.
+ - qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for codec.
Example:
i2c@f9925000 {
@@ -180,6 +181,7 @@
qcom,cdc-micbias2-cfilt-sel = <0x1>;
qcom,cdc-micbias3-cfilt-sel = <0x2>;
qcom,cdc-micbias4-cfilt-sel = <0x2>;
+ qcom,cdc-mclk-clk-rate = <12288000>;
};
wcd9xxx_codec@77{
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 7a9a80d..fe7b3e9 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -58,30 +58,12 @@
};
};
- pm8941_bms: bms@4000 {
+ pm8941_bms: qcom,bms {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-bms";
#address-cells = <1>;
#size-cells = <1>;
status = "disabled";
- compatible = "qcom,qpnp-bms";
- reg = <0x4000 0x100>;
-
- interrupts = <0x0 0x40 0x0>,
- <0x0 0x40 0x1>,
- <0x0 0x40 0x2>,
- <0x0 0x40 0x3>,
- <0x0 0x40 0x4>,
- <0x0 0x40 0x5>,
- <0x0 0x40 0x6>,
- <0x0 0x40 0x7>;
-
- interrupt-names = "vsense_for_r",
- "vsense_avg",
- "sw_cc_thr",
- "ocv_thr",
- "charge_begin",
- "good_ocv",
- "ocv_for_r",
- "cc_thr";
qcom,bms-r-sense-mohm = <2>;
qcom,bms-v-cutoff-uv = <3400000>;
@@ -95,6 +77,31 @@
qcom,bms-calculate-soc-ms = <20000>;
qcom,bms-chg-term-ua = <100000>;
qcom,bms-batt-type = <0>;
+
+ qcom,bms-iadc@3800 {
+ reg = <0x3800 0x100>;
+ };
+
+ qcom,bms-bms@4000 {
+ reg = <0x4000 0x100>;
+ interrupts = <0x0 0x40 0x0>,
+ <0x0 0x40 0x1>,
+ <0x0 0x40 0x2>,
+ <0x0 0x40 0x3>,
+ <0x0 0x40 0x4>,
+ <0x0 0x40 0x5>,
+ <0x0 0x40 0x6>,
+ <0x0 0x40 0x7>;
+
+ interrupt-names = "vsense_for_r",
+ "vsense_avg",
+ "sw_cc_thr",
+ "ocv_thr",
+ "charge_begin",
+ "good_ocv",
+ "ocv_for_r",
+ "cc_thr";
+ };
};
clkdiv@5b00 {
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index 41ac69d..9a0ec17 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -23,3 +23,54 @@
status = "ok";
};
};
+
+&sdcc1 {
+ qcom,vdd-always-on;
+ qcom,vdd-lpm-sup;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <800 500000>;
+
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <250 154000>;
+
+ qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+ qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+ vdd-supply = <&pm8026_l17>;
+ vdd-io-supply = <&pm8026_l6>;
+ qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+ qcom,sup-voltages = <2950 2950>;
+
+ qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+ qcom,nonremovable;
+ status = "ok";
+};
+
+&sdcc2 {
+ vdd-supply = <&pm8026_l18>;
+ vdd-io-supply = <&pm8026_l21>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <9000 800000>;
+
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <6 22000>;
+
+ qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+ qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+ qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+ qcom,sup-voltages = <2950 2950>;
+
+ qcom,xpc;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+ qcom,current-limit = <800>;
+
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index a69e1b7..000737f 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -159,6 +159,31 @@
};
};
+ sdcc1: qcom,sdcc@f9824000 {
+ cell-index = <1>; /* SDC1 eMMC slot */
+ compatible = "qcom,msm-sdcc";
+
+ reg = <0xf9824000 0x800>;
+ reg-names = "core_mem";
+ interrupts = <0 123 0>;
+ interrupt-names ="core_irq";
+
+ qcom,bus-width = <8>;
+ status = "disabled";
+ };
+
+ sdcc2: qcom,sdcc@f98a4000 {
+ cell-index = <2>; /* SDC2 SD card slot */
+ compatible = "qcom,msm-sdcc";
+
+ reg = <0xf98a4000 0x800>;
+ reg-names = "core_mem";
+ interrupts = <0 125 0>;
+ interrupt-names = "core_irq";
+
+ qcom,bus-width = <4>;
+ status = "disabled";
+ };
};
&gdsc_venus {
diff --git a/arch/arm/boot/dts/msm8910.dtsi b/arch/arm/boot/dts/msm8910.dtsi
index 06f8dc7..e1e608b 100644
--- a/arch/arm/boot/dts/msm8910.dtsi
+++ b/arch/arm/boot/dts/msm8910.dtsi
@@ -139,9 +139,9 @@
qcom,device-type = <3>;
};
- qcom,smem@fa00000 {
+ qcom,smem@d600000 {
compatible = "qcom,smem";
- reg = <0xfa00000 0x200000>,
+ reg = <0xd600000 0x200000>,
<0xfa006000 0x1000>,
<0xfc428000 0x4000>;
reg-names = "smem", "irq-reg-base", "aux-mem1";
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 570eb0f..979876d 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -233,6 +233,10 @@
wp-gpios = <&pm8941_gpios 29 0x1>;
};
+&usb3 {
+ qcom,otg-capability;
+};
+
&pm8941_chg {
status = "ok";
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 8479dfa..6a35f2f 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -252,6 +252,44 @@
cd-gpios = <&msmgpio 62 0x1>;
};
+&usb3 {
+ qcom,otg-capability;
+};
+
+&pm8941_chg {
+ status = "ok";
+
+ qcom,chg-charging-disabled;
+
+ qcom,chg-chgr@1000 {
+ status = "ok";
+ };
+
+ qcom,chg-buck@1100 {
+ status = "ok";
+ };
+
+ qcom,chg-bat-if@1200 {
+ status = "ok";
+ };
+
+ qcom,chg-usb-chgpth@1300 {
+ status = "ok";
+ };
+
+ qcom,chg-dc-chgpth@1400 {
+ status = "ok";
+ };
+
+ qcom,chg-boost@1500 {
+ status = "ok";
+ };
+
+ qcom,chg-misc@1600 {
+ status = "ok";
+ };
+};
+
&pm8941_gpios {
gpio@c000 { /* GPIO 1 */
};
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index 6623568..480a034 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -36,8 +36,8 @@
qcom,msm-bus,num-paths = <2>;
qcom,msm-bus,vectors-KBps =
<26 512 0 0>, <89 604 0 0>,
- <26 512 0 2000000>, <89 604 0 3000000>,
- <26 512 0 4000000>, <89 604 0 5000000>,
+ <26 512 0 1600000>, <89 604 0 3000000>,
+ <26 512 0 4000000>, <89 604 0 4500000>,
<26 512 0 6400000>, <89 604 0 7600000>;
/* GDSC oxili regulators */
@@ -108,7 +108,7 @@
qcom,algo-ss-win-size-min-us = <1000000>;
qcom,algo-ss-win-size-max-us = <1000000>;
qcom,algo-ss-util-pct = <95>;
- qcom,algo-ss-iobusy-conv = <100>;
+ qcom,algo-ss-no-corr-below-freq = <0>;
qcom,energy-active-coeff-a = <2492>;
qcom,energy-active-coeff-b = <0>;
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 2cef567..a7a7c88 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -108,9 +108,9 @@
rpm-regulator-smpb4 {
status = "okay";
pm8841_s4: regulator-s4 {
- regulator-min-microvolt = <900000>;
+ regulator-min-microvolt = <815000>;
regulator-max-microvolt = <900000>;
- qcom,init-voltage = <900000>;
+ qcom,init-voltage = <815000>;
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index e995a56..1faa5f4 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -406,7 +406,7 @@
qcom,cdc-micbias2-cfilt-sel = <0x1>;
qcom,cdc-micbias3-cfilt-sel = <0x2>;
qcom,cdc-micbias4-cfilt-sel = <0x2>;
-
+ qcom,cdc-mclk-clk-rate = <9600000>;
qcom,cdc-slim-ifd = "taiko-slim-ifd";
qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
};
@@ -819,6 +819,16 @@
compatible = "qcom,msm-dai-q6-dev";
qcom,msm-dai-q6-dev-id = <240>;
};
+
+ qcom,msm-dai-q6-incall-record-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32771>;
+ };
+
+ qcom,msm-dai-q6-incall-record-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32772>;
+ };
};
qcom,msm-auxpcm {
@@ -868,6 +878,14 @@
<11 604 32506 32506>;
};
+ qcom,msm-adsp-sensors {
+ compatible = "qcom,msm-adsp-sensors";
+ qcom,msm-adsp-sensors-src-id = <11>;
+ qcom,msm-adsp-sensors-dst-id = <604>;
+ qcom,msm-adsp-sensors-ab = <32505856>;
+ qcom,msm-adsp-sensors-ib = <32505856>;
+ };
+
qcom,mss@fc880000 {
compatible = "qcom,pil-q6v5-mss";
reg = <0xfc880000 0x100>,
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index dfa5223..324d358 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -417,6 +417,7 @@
qcom,cdc-micbias2-cfilt-sel = <0x1>;
qcom,cdc-micbias3-cfilt-sel = <0x2>;
qcom,cdc-micbias4-cfilt-sel = <0x2>;
+ qcom,cdc-mclk-clk-rate = <12288000>;
};
wcd9xxx_codec@77{
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index e6255f2..ccd23e8 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -184,6 +184,7 @@
select USE_USER_ACCESSIBLE_TIMERS
select ARM_USE_USER_ACCESSIBLE_TIMERS
select MSM_USE_USER_ACCESSIBLE_TIMERS
+ select MSM_CPU_PWRCTL
config ARCH_MSM8930
bool "MSM8930"
@@ -221,6 +222,7 @@
select USE_USER_ACCESSIBLE_TIMERS
select ARM_USE_USER_ACCESSIBLE_TIMERS
select MSM_USE_USER_ACCESSIBLE_TIMERS
+ select MSM_CPU_PWRCTL
config ARCH_APQ8064
bool "APQ8064"
@@ -254,6 +256,7 @@
select USE_USER_ACCESSIBLE_TIMERS
select ARM_USE_USER_ACCESSIBLE_TIMERS
select MSM_USE_USER_ACCESSIBLE_TIMERS
+ select MSM_CPU_PWRCTL
config ARCH_MSM8974
bool "MSM8974"
@@ -2715,4 +2718,11 @@
help
Use Device Control Volume as opposed to ALSA volume control.
+config MSM_CPU_PWRCTL
+ bool "Ensures that krait droop detectors are always off"
+ help
+ Droop detector mechanism can adversely affect krait plls during
+ stand alone power collapse operation. Selecting this option
+ ensures that they are always off.
+
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 64fa9e2..78fe55f 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -305,6 +305,7 @@
obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
obj-$(CONFIG_ARCH_MSM8910) += board-8910.o board-8910-gpiomux.o
+obj-$(CONFIG_ARCH_MSM8910) += clock-local2.o clock-pll.o clock-8910.o clock-rpm.o clock-voter.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
@@ -418,3 +419,4 @@
obj-$(CONFIG_MEMORY_HOLE_CARVEOUT) += msm_mem_hole.o
obj-$(CONFIG_MSM_SMCMOD) += smcmod.o
+obj-$(CONFIG_MSM_CPU_PWRCTL) += msm_cpu_pwrctl.o
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index cd3e636..9e34f47 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -1647,7 +1647,8 @@
msm_gpiomux_install(mpq8064_mi2s_configs,
ARRAY_SIZE(mpq8064_mi2s_configs));
- msm_gpiomux_install(apq8064_ext_regulator_configs,
+ if (!machine_is_mpq8064_hrd())
+ msm_gpiomux_install(apq8064_ext_regulator_configs,
ARRAY_SIZE(apq8064_ext_regulator_configs));
if (machine_is_apq8064_mtp()) {
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 38ac83e..6b15883 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -51,7 +51,7 @@
.ss_win_size_min_us = 1000000,
.ss_win_size_max_us = 1000000,
.ss_util_pct = 95,
- .ss_iobusy_conv = 100,
+ .ss_no_corr_below_freq = 0,
},
.energy_coeffs = {
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index ed03e46..07e2623 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1635,10 +1635,10 @@
static struct cyttsp_platform_data cyttsp_pdata = {
.panel_maxx = 634,
.panel_maxy = 1166,
- .disp_maxx = 599,
- .disp_maxy = 1023,
- .disp_minx = 0,
- .disp_miny = 0,
+ .disp_minx = 18,
+ .disp_maxx = 617,
+ .disp_miny = 18,
+ .disp_maxy = 1041,
.flags = 0x01,
.gen = CY_GEN3,
.use_st = CY_USE_ST,
@@ -2527,6 +2527,13 @@
&apq8064_device_ssbi_pmic2,
};
+static struct platform_device *pm8921_mpq_hrd_common_devices[] __initdata = {
+ &apq8064_device_ext_5v_vreg,
+ &apq8064_device_ext_mpp8_vreg,
+ &apq8064_device_ssbi_pmic1,
+ &apq8064_device_ssbi_pmic2,
+};
+
static struct platform_device *pm8917_common_devices[] __initdata = {
&apq8064_device_ext_mpp8_vreg,
&apq8064_device_ext_3p3v_vreg,
@@ -3556,9 +3563,14 @@
platform_add_devices(early_common_devices,
ARRAY_SIZE(early_common_devices));
- if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
- platform_add_devices(pm8921_common_devices,
- ARRAY_SIZE(pm8921_common_devices));
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917) {
+ if (!machine_is_mpq8064_hrd())
+ platform_add_devices(pm8921_common_devices,
+ ARRAY_SIZE(pm8921_common_devices));
+ else
+ platform_add_devices(pm8921_mpq_hrd_common_devices,
+ ARRAY_SIZE(pm8921_mpq_hrd_common_devices));
+ }
else
platform_add_devices(pm8917_common_devices,
ARRAY_SIZE(pm8917_common_devices));
diff --git a/arch/arm/mach-msm/board-8910.c b/arch/arm/mach-msm/board-8910.c
index f9c5367..a4bafa5 100644
--- a/arch/arm/mach-msm/board-8910.c
+++ b/arch/arm/mach-msm/board-8910.c
@@ -58,37 +58,6 @@
return MEMTYPE_EBI1;
}
-static struct clk_lookup msm_clocks_dummy[] = {
- CLK_DUMMY("core_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
- CLK_DUMMY("iface_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
- CLK_DUMMY("iface_clk", HSUSB_IFACE_CLK, "f9a55000.usb", OFF),
- CLK_DUMMY("core_clk", HSUSB_CORE_CLK, "f9a55000.usb", OFF),
- CLK_DUMMY("iface_clk", NULL, "msm_sdcc.1", OFF),
- CLK_DUMMY("core_clk", NULL, "msm_sdcc.1", OFF),
- CLK_DUMMY("bus_clk", NULL, "msm_sdcc.1", OFF),
- CLK_DUMMY("iface_clk", NULL, "msm_sdcc.2", OFF),
- CLK_DUMMY("core_clk", NULL, "msm_sdcc.2", OFF),
- CLK_DUMMY("bus_clk", NULL, "msm_sdcc.2", OFF),
- CLK_DUMMY("dfab_clk", DFAB_CLK, "msm_sps", OFF),
- CLK_DUMMY("iface_clk", NULL, "fd890000.qcom,iommu", OFF),
- CLK_DUMMY("core_clk", NULL, "fd890000.qcom,iommu", OFF),
- CLK_DUMMY("iface_clk", NULL, "fd860000.qcom,iommu", OFF),
- CLK_DUMMY("core_clk", NULL, "fd860000.qcom,iommu", OFF),
- CLK_DUMMY("iface_clk", NULL, "fd870000.qcom,iommu", OFF),
- CLK_DUMMY("core_clk", NULL, "fd870000.qcom,iommu", OFF),
- CLK_DUMMY("iface_clk", NULL, "fd880000.qcom,iommu", OFF),
- CLK_DUMMY("core_clk", NULL, "fd880000.qcom,iommu", OFF),
- CLK_DUMMY("iface_clk", NULL, "fd000000.qcom,iommu", OFF),
- CLK_DUMMY("core_clk", NULL, "fd000000.qcom,iommu", OFF),
- CLK_DUMMY("iface_clk", NULL, "fd010000.qcom,iommu", OFF),
- CLK_DUMMY("core_clk", NULL, "fd010000.qcom,iommu", OFF),
-};
-
-static struct clock_init_data msm_dummy_clock_init_data __initdata = {
- .table = msm_clocks_dummy,
- .size = ARRAY_SIZE(msm_clocks_dummy),
-};
-
static struct of_dev_auxdata msm8910_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF9824000, \
"msm_sdcc.1", NULL),
@@ -118,7 +87,11 @@
struct of_dev_auxdata *adata = msm8910_auxdata_lookup;
msm8910_init_gpiomux();
- msm_clock_init(&msm_dummy_clock_init_data);
+
+ if (machine_is_msm8910_rumi())
+ msm_clock_init(&msm8910_rumi_clock_init_data);
+ else
+ msm_clock_init(&msm8910_clock_init_data);
if (socinfo_init() < 0)
pr_err("%s: socinfo_init() failed\n", __func__);
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 1dcd54f..2392f57 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -882,7 +882,9 @@
&msm_device_hsic_host,
&msm_device_usb_bam,
&msm_android_usb_device,
+#ifdef CONFIG_USB_CI13XXX_MSM_HSIC
&msm_android_usb_hsic_device,
+#endif
&msm9615_device_uart_gsbi4,
&msm9615_device_ext_2p95v_vreg,
&msm9615_device_ssbi_pmic1,
diff --git a/arch/arm/mach-msm/board-msm7627a-io.c b/arch/arm/mach-msm/board-msm7627a-io.c
index 8c52456..4ec1d33 100644
--- a/arch/arm/mach-msm/board-msm7627a-io.c
+++ b/arch/arm/mach-msm/board-msm7627a-io.c
@@ -887,7 +887,9 @@
ft5x06_touchpad_setup();
}
- /* headset */
+ /* headset and power key*/
+ /* ignore end key as this target doesn't need it */
+ hs_platform_data.ignore_end_key = true;
platform_device_register(&hs_pdev);
/* vibrator */
diff --git a/arch/arm/mach-msm/clock-8910.c b/arch/arm/mach-msm/clock-8910.c
new file mode 100644
index 0000000..c5541b4
--- /dev/null
+++ b/arch/arm/mach-msm/clock-8910.c
@@ -0,0 +1,3443 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+
+#include <mach/rpm-regulator-smd.h>
+#include <mach/socinfo.h>
+#include <mach/rpm-smd.h>
+
+#include "clock-local2.h"
+#include "clock-pll.h"
+#include "clock-rpm.h"
+#include "clock-voter.h"
+#include "clock.h"
+
+enum {
+ GCC_BASE,
+ MMSS_BASE,
+ LPASS_BASE,
+ APCS_BASE,
+ N_BASES,
+};
+
+static void __iomem *virt_bases[N_BASES];
+
+#define GCC_REG_BASE(x) (void __iomem *)(virt_bases[GCC_BASE] + (x))
+#define MMSS_REG_BASE(x) (void __iomem *)(virt_bases[MMSS_BASE] + (x))
+#define LPASS_REG_BASE(x) (void __iomem *)(virt_bases[LPASS_BASE] + (x))
+#define APCS_REG_BASE(x) (void __iomem *)(virt_bases[APCS_BASE] + (x))
+
+#define GPLL0_MODE 0x0000
+#define GPLL0_L_VAL 0x0004
+#define GPLL0_M_VAL 0x0008
+#define GPLL0_N_VAL 0x000C
+#define GPLL0_USER_CTL 0x0010
+#define GPLL0_STATUS 0x001C
+#define GPLL2_MODE 0x0080
+#define GPLL2_L_VAL 0x0084
+#define GPLL2_M_VAL 0x0088
+#define GPLL2_N_VAL 0x008C
+#define GPLL2_USER_CTL 0x0090
+#define GPLL2_STATUS 0x009C
+#define CONFIG_NOC_BCR 0x0140
+#define MMSS_BCR 0x0240
+#define MMSS_NOC_CFG_AHB_CBCR 0x024C
+#define MSS_CFG_AHB_CBCR 0x0280
+#define MSS_Q6_BIMC_AXI_CBCR 0x0284
+#define USB_HS_BCR 0x0480
+#define USB_HS_SYSTEM_CBCR 0x0484
+#define USB_HS_AHB_CBCR 0x0488
+#define USB_HS_SYSTEM_CMD_RCGR 0x0490
+#define USB2A_PHY_BCR 0x04A8
+#define USB2A_PHY_SLEEP_CBCR 0x04AC
+#define SDCC1_BCR 0x04C0
+#define SDCC1_APPS_CMD_RCGR 0x04D0
+#define SDCC1_APPS_CBCR 0x04C4
+#define SDCC1_AHB_CBCR 0x04C8
+#define SDCC2_BCR 0x0500
+#define SDCC2_APPS_CMD_RCGR 0x0510
+#define SDCC2_APPS_CBCR 0x0504
+#define SDCC2_AHB_CBCR 0x0508
+#define BLSP1_BCR 0x05C0
+#define BLSP1_AHB_CBCR 0x05C4
+#define BLSP1_QUP1_BCR 0x0640
+#define BLSP1_QUP1_SPI_APPS_CBCR 0x0644
+#define BLSP1_QUP1_I2C_APPS_CBCR 0x0648
+#define BLSP1_QUP1_SPI_APPS_CMD_RCGR 0x064C
+#define BLSP1_UART1_BCR 0x0680
+#define BLSP1_UART1_APPS_CBCR 0x0684
+#define BLSP1_UART1_SIM_CBCR 0x0688
+#define BLSP1_UART1_APPS_CMD_RCGR 0x068C
+#define BLSP1_QUP2_BCR 0x06C0
+#define BLSP1_QUP2_SPI_APPS_CBCR 0x06C4
+#define BLSP1_QUP2_I2C_APPS_CBCR 0x06C8
+#define BLSP1_QUP2_SPI_APPS_CMD_RCGR 0x06CC
+#define BLSP1_UART2_BCR 0x0700
+#define BLSP1_UART2_APPS_CBCR 0x0704
+#define BLSP1_UART2_SIM_CBCR 0x0708
+#define BLSP1_UART2_APPS_CMD_RCGR 0x070C
+#define BLSP1_QUP3_BCR 0x0740
+#define BLSP1_QUP3_SPI_APPS_CBCR 0x0744
+#define BLSP1_QUP3_I2C_APPS_CBCR 0x0748
+#define BLSP1_QUP3_SPI_APPS_CMD_RCGR 0x074C
+#define BLSP1_UART3_BCR 0x0780
+#define BLSP1_UART3_APPS_CBCR 0x0784
+#define BLSP1_UART3_SIM_CBCR 0x0788
+#define BLSP1_UART3_APPS_CMD_RCGR 0x078C
+#define BLSP1_QUP4_BCR 0x07C0
+#define BLSP1_QUP4_SPI_APPS_CBCR 0x07C4
+#define BLSP1_QUP4_I2C_APPS_CBCR 0x07C8
+#define BLSP1_QUP4_SPI_APPS_CMD_RCGR 0x07CC
+#define BLSP1_UART4_BCR 0x0800
+#define BLSP1_UART4_APPS_CBCR 0x0804
+#define BLSP1_UART4_SIM_CBCR 0x0808
+#define BLSP1_UART4_APPS_CMD_RCGR 0x080C
+#define BLSP1_QUP5_BCR 0x0840
+#define BLSP1_QUP5_SPI_APPS_CBCR 0x0844
+#define BLSP1_QUP5_I2C_APPS_CBCR 0x0848
+#define BLSP1_QUP5_SPI_APPS_CMD_RCGR 0x084C
+#define BLSP1_UART5_BCR 0x0880
+#define BLSP1_UART5_APPS_CBCR 0x0884
+#define BLSP1_UART5_SIM_CBCR 0x0888
+#define BLSP1_UART5_APPS_CMD_RCGR 0x088C
+#define BLSP1_QUP6_BCR 0x08C0
+#define BLSP1_QUP6_SPI_APPS_CBCR 0x08C4
+#define BLSP1_QUP6_I2C_APPS_CBCR 0x08C8
+#define BLSP1_QUP6_SPI_APPS_CMD_RCGR 0x08CC
+#define BLSP1_UART6_BCR 0x0900
+#define BLSP1_UART6_APPS_CBCR 0x0904
+#define BLSP1_UART6_SIM_CBCR 0x0908
+#define BLSP1_UART6_APPS_CMD_RCGR 0x090C
+#define PDM_BCR 0x0CC0
+#define PDM_AHB_CBCR 0x0CC4
+#define PDM2_CBCR 0x0CCC
+#define PDM2_CMD_RCGR 0x0CD0
+#define PRNG_BCR 0x0D00
+#define PRNG_AHB_CBCR 0x0D04
+#define BOOT_ROM_BCR 0x0E00
+#define BOOT_ROM_AHB_CBCR 0x0E04
+#define CE1_BCR 0x1040
+#define CE1_CMD_RCGR 0x1050
+#define CE1_CBCR 0x1044
+#define CE1_AXI_CBCR 0x1048
+#define CE1_AHB_CBCR 0x104C
+#define COPSS_SMMU_AHB_CBCR 0x015C
+#define LPSS_SMMU_AHB_CBCR 0x0158
+#define LPASS_Q6_AXI_CBCR 0x11C0
+#define APCS_GPLL_ENA_VOTE 0x1480
+#define APCS_CLOCK_BRANCH_ENA_VOTE 0x1484
+#define APCS_CLOCK_SLEEP_ENA_VOTE 0x1488
+#define GP1_CBCR 0x1900
+#define GP1_CMD_RCGR 0x1904
+#define GP2_CBCR 0x1940
+#define GP2_CMD_RCGR 0x1944
+#define GP3_CBCR 0x1980
+#define GP3_CMD_RCGR 0x1984
+#define XO_CBCR 0x0034
+
+#define MMPLL0_PLL_MODE 0x0000
+#define MMPLL0_PLL_L_VAL 0x0004
+#define MMPLL0_PLL_M_VAL 0x0008
+#define MMPLL0_PLL_N_VAL 0x000C
+#define MMPLL0_PLL_USER_CTL 0x0010
+#define MMPLL0_PLL_STATUS 0x001C
+#define MMSS_PLL_VOTE_APCS_REG 0x0100
+#define MMPLL1_PLL_MODE 0x4100
+#define MMPLL1_PLL_L_VAL 0x4104
+#define MMPLL1_PLL_M_VAL 0x4108
+#define MMPLL1_PLL_N_VAL 0x410C
+#define MMPLL1_PLL_USER_CTL 0x4110
+#define MMPLL1_PLL_STATUS 0x411C
+#define DSI_PCLK_CMD_RCGR 0x2000
+#define DSI_CMD_RCGR 0x2020
+#define MDP_VSYNC_CMD_RCGR 0x2080
+#define DSI_BYTE_CMD_RCGR 0x2120
+#define DSI_ESC_CMD_RCGR 0x2160
+#define DSI_BCR 0x2200
+#define DSI_BYTE_BCR 0x2204
+#define DSI_ESC_BCR 0x2208
+#define DSI_AHB_BCR 0x220C
+#define DSI_PCLK_BCR 0x2214
+#define MDP_LCDC_BCR 0x2218
+#define MDP_DSI_BCR 0x221C
+#define MDP_VSYNC_BCR 0x2220
+#define MDP_AXI_BCR 0x2224
+#define MDP_AHB_BCR 0x2228
+#define MDP_AXI_CBCR 0x2314
+#define MDP_VSYNC_CBCR 0x231C
+#define MDP_AHB_CBCR 0x2318
+#define DSI_PCLK_CBCR 0x233C
+#define GMEM_GFX3D_CBCR 0x4038
+#define MDP_LCDC_CBCR 0x2340
+#define MDP_DSI_CBCR 0x2320
+#define DSI_CBCR 0x2324
+#define DSI_BYTE_CBCR 0x2328
+#define DSI_ESC_CBCR 0x232C
+#define DSI_AHB_CBCR 0x2330
+#define CSI0PHYTIMER_CMD_RCGR 0x3000
+#define CSI0PHYTIMER_BCR 0x3020
+#define CSI0PHYTIMER_CBCR 0x3024
+#define CSI1PHYTIMER_CMD_RCGR 0x3030
+#define CSI1PHYTIMER_BCR 0x3050
+#define CSI1PHYTIMER_CBCR 0x3054
+#define CSI0_CMD_RCGR 0x3090
+#define CSI0_BCR 0x30B0
+#define CSI0_CBCR 0x30B4
+#define CSI_AHB_BCR 0x30B8
+#define CSI_AHB_CBCR 0x30BC
+#define CSI0PHY_BCR 0x30C0
+#define CSI0PHY_CBCR 0x30C4
+#define CSI0RDI_BCR 0x30D0
+#define CSI0RDI_CBCR 0x30D4
+#define CSI0PIX_BCR 0x30E0
+#define CSI0PIX_CBCR 0x30E4
+#define CSI1_CMD_RCGR 0x3100
+#define CSI1_BCR 0x3120
+#define CSI1_CBCR 0x3124
+#define CSI1PHY_BCR 0x3130
+#define CSI1PHY_CBCR 0x3134
+#define CSI1RDI_BCR 0x3140
+#define CSI1RDI_CBCR 0x3144
+#define CSI1PIX_BCR 0x3150
+#define CSI1PIX_CBCR 0x3154
+#define MCLK0_CMD_RCGR 0x3360
+#define MCLK0_BCR 0x3380
+#define MCLK0_CBCR 0x3384
+#define MCLK1_CMD_RCGR 0x3390
+#define MCLK1_BCR 0x33B0
+#define MCLK1_CBCR 0x33B4
+#define VFE_CMD_RCGR 0x3600
+#define VFE_BCR 0x36A0
+#define VFE_AHB_BCR 0x36AC
+#define VFE_AXI_BCR 0x36B0
+#define VFE_CBCR 0x36A8
+#define VFE_AHB_CBCR 0x36B8
+#define VFE_AXI_CBCR 0x36BC
+#define CSI_VFE_BCR 0x3700
+#define CSI_VFE_CBCR 0x3704
+#define GFX3D_CMD_RCGR 0x4000
+#define OXILI_GFX3D_CBCR 0x4028
+#define OXILI_GFX3D_BCR 0x4030
+#define OXILI_AHB_BCR 0x4044
+#define OXILI_AHB_CBCR 0x403C
+#define AHB_CMD_RCGR 0x5000
+#define MMSSNOCAHB_BCR 0x5020
+#define MMSSNOCAHB_BTO_BCR 0x5030
+#define MMSS_MISC_AHB_BCR 0x5034
+#define MMSS_MMSSNOC_AHB_CBCR 0x5024
+#define MMSS_MMSSNOC_BTO_AHB_CBCR 0x5028
+#define MMSS_MISC_AHB_CBCR 0x502C
+#define AXI_CMD_RCGR 0x5040
+#define MMSSNOCAXI_BCR 0x5060
+#define MMSS_S0_AXI_BCR 0x5068
+#define MMSS_S0_AXI_CBCR 0x5064
+#define MMSS_MMSSNOC_AXI_CBCR 0x506C
+#define BIMC_GFX_BCR 0x5090
+#define BIMC_GFX_CBCR 0x5094
+
+#define AUDIO_CORE_GDSCR 0x7000
+#define SPDM_BCR 0x1000
+#define LPAAUDIO_PLL_MODE 0x0000
+#define LPAAUDIO_PLL_L_VAL 0x0004
+#define LPAAUDIO_PLL_M_VAL 0x0008
+#define LPAAUDIO_PLL_N_VAL 0x000C
+#define LPAAUDIO_PLL_USER_CTL 0x0010
+#define LPAAUDIO_PLL_STATUS 0x001C
+#define LPAQ6_PLL_MODE 0x1000
+#define LPAQ6_PLL_USER_CTL 0x1010
+#define LPAQ6_PLL_STATUS 0x101C
+#define LPA_PLL_VOTE_APPS 0x2000
+#define AUDIO_CORE_BCR_SLP_CBCR 0x4004
+#define Q6SS_BCR_SLP_CBCR 0x6004
+#define AUDIO_CORE_GDSC_XO_CBCR 0x7004
+#define AUDIO_CORE_LPAIF_DMA_CBCR 0x9000
+#define AUDIO_CORE_LPAIF_CSR_CBCR 0x9004
+#define LPAIF_SPKR_CMD_RCGR 0xA000
+#define AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR 0xA014
+#define AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR 0xA018
+#define AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR 0xA01C
+#define LPAIF_PRI_CMD_RCGR 0xB000
+#define AUDIO_CORE_LPAIF_PRI_OSR_CBCR 0xB014
+#define AUDIO_CORE_LPAIF_PRI_IBIT_CBCR 0xB018
+#define AUDIO_CORE_LPAIF_PRI_EBIT_CBCR 0xB01C
+#define LPAIF_SEC_CMD_RCGR 0xC000
+#define AUDIO_CORE_LPAIF_SEC_OSR_CBCR 0xC014
+#define AUDIO_CORE_LPAIF_SEC_IBIT_CBCR 0xC018
+#define AUDIO_CORE_LPAIF_SEC_EBIT_CBCR 0xC01C
+#define LPAIF_TER_CMD_RCGR 0xD000
+#define AUDIO_CORE_LPAIF_TER_OSR_CBCR 0xD014
+#define AUDIO_CORE_LPAIF_TER_IBIT_CBCR 0xD018
+#define AUDIO_CORE_LPAIF_TER_EBIT_CBCR 0xD01C
+#define LPAIF_QUAD_CMD_RCGR 0xE000
+#define AUDIO_CORE_LPAIF_QUAD_OSR_CBCR 0xE014
+#define AUDIO_CORE_LPAIF_QUAD_IBIT_CBCR 0xE018
+#define AUDIO_CORE_LPAIF_QUAD_EBIT_CBCR 0xE01C
+#define LPAIF_PCM0_CMD_RCGR 0xF000
+#define AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR 0xF014
+#define AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR 0xF018
+#define LPAIF_PCM1_CMD_RCGR 0x10000
+#define AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR 0x10014
+#define AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR 0x10018
+#define SLIMBUS_CMD_RCGR 0x12000
+#define AUDIO_CORE_SLIMBUS_CORE_CBCR 0x12014
+#define LPAIF_PCMOE_CMD_RCGR 0x13000
+#define AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR 0x13014
+#define Q6CORE_CMD_RCGR 0x14000
+#define SLEEP_CMD_RCGR 0x15000
+#define SPDM_CMD_RCGR 0x16000
+#define AUDIO_WRAPPER_SPDM_CBCR 0x16014
+#define XO_CMD_RCGR 0x17000
+#define AHBFABRIC_CMD_RCGR 0x18000
+#define AUDIO_CORE_LPM_CBCR 0x19000
+#define AUDIO_CORE_AVSYNC_CSR_CBCR 0x1A000
+#define AUDIO_CORE_AVSYNC_XO_CBCR 0x1A004
+#define AUDIO_CORE_AVSYNC_BT_XO_CBCR 0x1A008
+#define AUDIO_CORE_AVSYNC_FM_XO_CBCR 0x1A00C
+#define AUDIO_CORE_IXFABRIC_CBCR 0x1B000
+#define AUDIO_WRAPPER_EFABRIC_CBCR 0x1B004
+#define AUDIO_CORE_TCM_SLAVE_CBCR 0x1C000
+#define AUDIO_CORE_CSR_CBCR 0x1D000
+#define AUDIO_CORE_DML_CBCR 0x1E000
+#define AUDIO_CORE_SYSNOC_CBCR 0x1F000
+#define AUDIO_WRAPPER_SYSNOC_SWAY_CBCR 0x1F004
+#define AUDIO_CORE_TIMEOUT_CBCR 0x20000
+#define AUDIO_WRAPPER_TIMEOUT_CBCR 0x20004
+#define AUDIO_CORE_SECURITY_CBCR 0x21000
+#define AUDIO_WRAPPER_SECURITY_CBCR 0x21004
+#define Q6SS_AHB_LFABIF_CBCR 0x22000
+#define Q6SS_AHBM_CBCR 0x22004
+#define AUDIO_WRAPPER_LCC_CSR_CBCR 0x23000
+#define AUDIO_WRAPPER_BR_CBCR 0x24000
+#define AUDIO_WRAPPER_SMEM_CBCR 0x25000
+#define Q6SS_XO_CBCR 0x26000
+#define Q6SS_SLP_CBCR 0x26004
+#define LPASS_Q6SS_BCR 0x6000
+#define AUDIO_WRAPPER_STM_XO_CBCR 0x27000
+#define AUDIO_CORE_IXFABRIC_SPDMTM_CSR_CBCR 0x28000
+#define AUDIO_WRAPPER_EFABRIC_SPDMTM_CSR_CBCR 0x28004
+
+/* Mux source select values */
+#define gcc_xo_source_val 0
+#define gpll0_source_val 1
+#define gnd_source_val 5
+#define mmpll0_mm_source_val 1
+#define mmpll1_mm_source_val 2
+#define gpll0_mm_source_val 5
+#define gcc_xo_mm_source_val 0
+#define mm_gnd_source_val 6
+#define cxo_lpass_source_val 0
+#define lpapll0_lpass_source_val 1
+#define gpll0_lpass_source_val 5
+#define dsipll_mm_source_val 1
+
+#define F(f, s, div, m, n) \
+ { \
+ .freq_hz = (f), \
+ .src_clk = &s##_clk_src.c, \
+ .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##_source_val), \
+ }
+
+#define F_MM(f, s, div, m, n) \
+ { \
+ .freq_hz = (f), \
+ .src_clk = &s##_clk_src.c, \
+ .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_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_MDSS(f, s, div, m, n) \
+ { \
+ .freq_hz = (f), \
+ .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_LPASS(f, s, div, m, n) \
+ { \
+ .freq_hz = (f), \
+ .src_clk = &s##_clk_src.c, \
+ .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##_lpass_source_val), \
+ }
+
+#define VDD_DIG_FMAX_MAP1(l1, f1) \
+ .vdd_class = &vdd_dig, \
+ .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ [VDD_DIG_##l1] = (f1), \
+ }, \
+ .num_fmax = VDD_DIG_NUM
+#define VDD_DIG_FMAX_MAP2(l1, f1, l2, f2) \
+ .vdd_class = &vdd_dig, \
+ .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ [VDD_DIG_##l1] = (f1), \
+ [VDD_DIG_##l2] = (f2), \
+ }, \
+ .num_fmax = VDD_DIG_NUM
+#define VDD_DIG_FMAX_MAP3(l1, f1, l2, f2, l3, f3) \
+ .vdd_class = &vdd_dig, \
+ .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ [VDD_DIG_##l1] = (f1), \
+ [VDD_DIG_##l2] = (f2), \
+ [VDD_DIG_##l3] = (f3), \
+ }, \
+ .num_fmax = VDD_DIG_NUM
+
+enum vdd_dig_levels {
+ VDD_DIG_NONE,
+ VDD_DIG_LOW,
+ VDD_DIG_NOMINAL,
+ VDD_DIG_HIGH,
+ VDD_DIG_NUM
+};
+
+static const int vdd_corner[] = {
+ [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
+ [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
+ [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
+ [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+};
+
+static struct rpm_regulator *vdd_dig_reg;
+
+static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
+{
+ return rpm_regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
+ RPM_REGULATOR_CORNER_SUPER_TURBO);
+}
+
+static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+
+#define RPM_MISC_CLK_TYPE 0x306b6c63
+#define RPM_BUS_CLK_TYPE 0x316b6c63
+#define RPM_MEM_CLK_TYPE 0x326b6c63
+
+#define RPM_SMD_KEY_ENABLE 0x62616E45
+
+#define CXO_ID 0x0
+#define QDSS_ID 0x1
+#define RPM_SCALING_ENABLE_ID 0x2
+
+#define PNOC_ID 0x0
+#define SNOC_ID 0x1
+#define CNOC_ID 0x2
+#define MMSSNOC_AHB_ID 0x3
+
+#define BIMC_ID 0x0
+#define OXILI_ID 0x1
+#define OCMEM_ID 0x2
+
+#define D0_ID 1
+#define D1_ID 2
+#define A0_ID 3
+#define A1_ID 4
+#define A2_ID 5
+#define DIFF_CLK_ID 7
+#define DIV_CLK_ID 11
+
+DEFINE_CLK_RPM_SMD(pnoc_clk, pnoc_a_clk, RPM_BUS_CLK_TYPE, PNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(snoc_clk, snoc_a_clk, RPM_BUS_CLK_TYPE, SNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(cnoc_clk, cnoc_a_clk, RPM_BUS_CLK_TYPE, CNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, RPM_BUS_CLK_TYPE,
+ MMSSNOC_AHB_ID, NULL);
+
+DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE, BIMC_ID, NULL);
+
+DEFINE_CLK_RPM_SMD_BRANCH(gcc_xo_clk_src, gcc_xo_a_clk_src,
+ RPM_MISC_CLK_TYPE, CXO_ID, 19200000);
+DEFINE_CLK_RPM_SMD_QDSS(qdss_clk, qdss_a_clk, RPM_MISC_CLK_TYPE, QDSS_ID);
+
+DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_d0, cxo_d0_a, D0_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_d1, cxo_d1_a, D1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a0, cxo_a0_a, A0_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a1, cxo_a1_a, A1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a2, cxo_a2_a, A2_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(div_clk, div_a_clk, DIV_CLK_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(diff_clk, diff_a_clk, DIFF_CLK_ID);
+
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_d0_pin, cxo_d0_a_pin, D0_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_d1_pin, cxo_d1_a_pin, D1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a0_pin, cxo_a0_a_pin, A0_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a1_pin, cxo_a1_a_pin, A1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a2_pin, cxo_a2_a_pin, A2_ID);
+
+static DEFINE_CLK_VOTER(pnoc_msmbus_clk, &pnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_clk, &snoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_msmbus_clk, &cnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pnoc_msmbus_a_clk, &pnoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_a_clk, &snoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_msmbus_a_clk, &cnoc_a_clk.c, LONG_MAX);
+
+static DEFINE_CLK_VOTER(bimc_msmbus_clk, &bimc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_msmbus_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_acpu_a_clk, &bimc_a_clk.c, LONG_MAX);
+
+static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pnoc_iommu_clk, &pnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pnoc_qseecom_clk, &pnoc_clk.c, LONG_MAX);
+
+static struct pll_vote_clk gpll0_clk_src = {
+ .en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+ .en_mask = BIT(0),
+ .status_reg = (void __iomem *)GPLL0_STATUS,
+ .status_mask = BIT(17),
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .rate = 600000000,
+ .dbg_name = "gpll0_clk_src",
+ .ops = &clk_ops_pll_vote,
+ CLK_INIT(gpll0_clk_src.c),
+ },
+};
+
+static struct pll_vote_clk mmpll0_clk_src = {
+ .en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS_REG,
+ .en_mask = BIT(0),
+ .status_reg = (void __iomem *)MMPLL0_PLL_STATUS,
+ .status_mask = BIT(17),
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .dbg_name = "mmpll0_clk_src",
+ .rate = 800000000,
+ .ops = &clk_ops_pll_vote,
+ CLK_INIT(mmpll0_clk_src.c),
+ },
+};
+
+static struct pll_config_regs mmpll0_regs __initdata = {
+ .l_reg = (void __iomem *)MMPLL0_PLL_L_VAL,
+ .m_reg = (void __iomem *)MMPLL0_PLL_M_VAL,
+ .n_reg = (void __iomem *)MMPLL0_PLL_N_VAL,
+ .config_reg = (void __iomem *)MMPLL0_PLL_USER_CTL,
+ .mode_reg = (void __iomem *)MMPLL0_PLL_MODE,
+ .base = &virt_bases[MMSS_BASE],
+};
+
+static struct pll_clk mmpll1_clk_src = {
+ .mode_reg = (void __iomem *)MMPLL1_PLL_MODE,
+ .status_reg = (void __iomem *)MMPLL1_PLL_STATUS,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .dbg_name = "mmpll1_clk_src",
+ .rate = 1200000000,
+ .ops = &clk_ops_local_pll,
+ CLK_INIT(mmpll1_clk_src.c),
+ },
+};
+
+static struct pll_config_regs mmpll1_regs __initdata = {
+ .l_reg = (void __iomem *)MMPLL1_PLL_L_VAL,
+ .m_reg = (void __iomem *)MMPLL1_PLL_M_VAL,
+ .n_reg = (void __iomem *)MMPLL1_PLL_N_VAL,
+ .config_reg = (void __iomem *)MMPLL1_PLL_USER_CTL,
+ .mode_reg = (void __iomem *)MMPLL1_PLL_MODE,
+ .base = &virt_bases[MMSS_BASE],
+};
+
+static struct pll_vote_clk lpapll0_clk_src = {
+ .en_reg = (void __iomem *)LPA_PLL_VOTE_APPS,
+ .en_mask = BIT(0),
+ .status_reg = (void __iomem *)LPAAUDIO_PLL_STATUS,
+ .status_mask = BIT(17),
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .rate = 491520000,
+ .dbg_name = "lpapll0_clk_src",
+ .ops = &clk_ops_pll_vote,
+ CLK_INIT(lpapll0_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_gcc_blsp1_qup1_6_spi_apps_clk[] = {
+ F( 960000, gcc_xo, 10, 1, 2),
+ F( 4800000, gcc_xo, 4, 0, 0),
+ F( 9600000, gcc_xo, 2, 0, 0),
+ F(15000000, gpll0, 10, 1, 4),
+ F(19200000, gcc_xo, 1, 0, 0),
+ F(25000000, gpll0, 12, 1, 2),
+ F(50000000, gpll0, 12, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk blsp1_qup1_spi_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_QUP1_SPI_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_qup1_spi_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+ CLK_INIT(blsp1_qup1_spi_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk blsp1_qup2_spi_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_QUP2_SPI_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_qup2_spi_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+ CLK_INIT(blsp1_qup2_spi_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk blsp1_qup3_spi_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_QUP3_SPI_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_qup3_spi_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+ CLK_INIT(blsp1_qup3_spi_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk blsp1_qup4_spi_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_QUP4_SPI_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_qup4_spi_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+ CLK_INIT(blsp1_qup4_spi_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk blsp1_qup5_spi_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_QUP5_SPI_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_qup5_spi_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+ CLK_INIT(blsp1_qup5_spi_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk blsp1_qup6_spi_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_QUP6_SPI_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_qup6_spi_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
+ CLK_INIT(blsp1_qup6_spi_apps_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_gcc_blsp1_uart1_6_apps_clk[] = {
+ F( 3686400, gpll0, 1, 96, 15625),
+ F( 7372800, gpll0, 1, 192, 15625),
+ F(14745600, gpll0, 1, 384, 15625),
+ F(16000000, gpll0, 5, 2, 15),
+ F(19200000, gcc_xo, 1, 0, 0),
+ F(24000000, gpll0, 5, 1, 5),
+ F(32000000, gpll0, 1, 4, 75),
+ F(40000000, gpll0, 15, 0, 0),
+ F(46400000, gpll0, 1, 29, 375),
+ F(48000000, gpll0, 12.5, 0, 0),
+ F(51200000, gpll0, 1, 32, 375),
+ F(56000000, gpll0, 1, 7, 75),
+ F(58982400, gpll0, 1, 1536, 15625),
+ F(60000000, gpll0, 10, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk blsp1_uart1_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_UART1_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_uart1_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+ CLK_INIT(blsp1_uart1_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk blsp1_uart2_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_UART2_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_uart2_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+ CLK_INIT(blsp1_uart2_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk blsp1_uart3_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_UART3_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_uart3_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+ CLK_INIT(blsp1_uart3_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk blsp1_uart4_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_UART4_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_uart4_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+ CLK_INIT(blsp1_uart4_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk blsp1_uart5_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_UART5_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_uart5_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+ CLK_INIT(blsp1_uart5_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk blsp1_uart6_apps_clk_src = {
+ .cmd_rcgr_reg = BLSP1_UART6_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "blsp1_uart6_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
+ CLK_INIT(blsp1_uart6_apps_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_gcc_ce1_clk[] = {
+ F(50000000, gpll0, 12, 0, 0),
+ F(100000000, gpll0, 6, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk ce1_clk_src = {
+ .cmd_rcgr_reg = CE1_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_gcc_ce1_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "ce1_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
+ CLK_INIT(ce1_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_gcc_gp1_3_clk[] = {
+ F(19200000, gcc_xo, 1, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk gp1_clk_src = {
+ .cmd_rcgr_reg = GP1_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_gp1_3_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gp1_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+ CLK_INIT(gp1_clk_src.c),
+ },
+};
+
+static struct rcg_clk gp2_clk_src = {
+ .cmd_rcgr_reg = GP2_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_gp1_3_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gp2_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+ CLK_INIT(gp2_clk_src.c),
+ },
+};
+
+static struct rcg_clk gp3_clk_src = {
+ .cmd_rcgr_reg = GP3_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_gp1_3_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gp3_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+ CLK_INIT(gp3_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_gcc_pdm2_clk[] = {
+ F(60000000, gpll0, 10, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk pdm2_clk_src = {
+ .cmd_rcgr_reg = PDM2_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_gcc_pdm2_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "pdm2_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP1(LOW, 120000000),
+ CLK_INIT(pdm2_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_gcc_sdcc1_2_apps_clk[] = {
+ F( 144000, gcc_xo, 16, 3, 25),
+ F( 400000, gcc_xo, 12, 1, 4),
+ F( 20000000, gpll0, 15, 1, 2),
+ F( 25000000, gpll0, 12, 1, 2),
+ F( 50000000, gpll0, 12, 0, 0),
+ F(100000000, gpll0, 6, 0, 0),
+ F(200000000, gpll0, 3, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk sdcc1_apps_clk_src = {
+ .cmd_rcgr_reg = SDCC1_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_sdcc1_2_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "sdcc1_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+ CLK_INIT(sdcc1_apps_clk_src.c),
+ },
+};
+
+static struct rcg_clk sdcc2_apps_clk_src = {
+ .cmd_rcgr_reg = SDCC2_APPS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_gcc_sdcc1_2_apps_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "sdcc2_apps_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+ CLK_INIT(sdcc2_apps_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
+ F(75000000, gpll0, 8, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk usb_hs_system_clk_src = {
+ .cmd_rcgr_reg = USB_HS_SYSTEM_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_gcc_usb_hs_system_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "usb_hs_system_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP2(LOW, 60000000, NOMINAL, 100000000),
+ CLK_INIT(usb_hs_system_clk_src.c),
+ },
+};
+
+static struct local_vote_clk gcc_blsp1_ahb_clk = {
+ .cbcr_reg = BLSP1_AHB_CBCR,
+ .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+ .en_mask = BIT(17),
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_blsp1_ahb_clk",
+ .ops = &clk_ops_vote,
+ CLK_INIT(gcc_blsp1_ahb_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup1_i2c_apps_clk = {
+ .cbcr_reg = BLSP1_QUP1_I2C_APPS_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup1_i2c_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup1_i2c_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup1_spi_apps_clk = {
+ .cbcr_reg = BLSP1_QUP1_SPI_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_qup1_spi_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup1_spi_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup1_spi_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup2_i2c_apps_clk = {
+ .cbcr_reg = BLSP1_QUP2_I2C_APPS_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup2_i2c_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup2_i2c_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup2_spi_apps_clk = {
+ .cbcr_reg = BLSP1_QUP2_SPI_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_qup2_spi_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup2_spi_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup2_spi_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup3_i2c_apps_clk = {
+ .cbcr_reg = BLSP1_QUP3_I2C_APPS_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup3_i2c_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup3_i2c_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup3_spi_apps_clk = {
+ .cbcr_reg = BLSP1_QUP3_SPI_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_qup3_spi_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup3_spi_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup3_spi_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup4_i2c_apps_clk = {
+ .cbcr_reg = BLSP1_QUP4_I2C_APPS_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup4_i2c_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup4_i2c_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup4_spi_apps_clk = {
+ .cbcr_reg = BLSP1_QUP4_SPI_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_qup4_spi_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup4_spi_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup4_spi_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup5_i2c_apps_clk = {
+ .cbcr_reg = BLSP1_QUP5_I2C_APPS_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup5_i2c_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup5_i2c_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup5_spi_apps_clk = {
+ .cbcr_reg = BLSP1_QUP5_SPI_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_qup5_spi_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup5_spi_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup5_spi_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup6_i2c_apps_clk = {
+ .cbcr_reg = BLSP1_QUP6_I2C_APPS_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup6_i2c_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup6_i2c_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_qup6_spi_apps_clk = {
+ .cbcr_reg = BLSP1_QUP6_SPI_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_qup6_spi_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_qup6_spi_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_qup6_spi_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_uart1_apps_clk = {
+ .cbcr_reg = BLSP1_UART1_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_uart1_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_uart1_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_uart1_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_uart2_apps_clk = {
+ .cbcr_reg = BLSP1_UART2_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_uart2_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_uart2_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_uart2_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_uart3_apps_clk = {
+ .cbcr_reg = BLSP1_UART3_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_uart3_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_uart3_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_uart3_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_uart4_apps_clk = {
+ .cbcr_reg = BLSP1_UART4_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_uart4_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_uart4_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_uart4_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_uart5_apps_clk = {
+ .cbcr_reg = BLSP1_UART5_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_uart5_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_uart5_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_uart5_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_blsp1_uart6_apps_clk = {
+ .cbcr_reg = BLSP1_UART6_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &blsp1_uart6_apps_clk_src.c,
+ .dbg_name = "gcc_blsp1_uart6_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_blsp1_uart6_apps_clk.c),
+ },
+};
+
+static struct local_vote_clk gcc_boot_rom_ahb_clk = {
+ .cbcr_reg = BOOT_ROM_AHB_CBCR,
+ .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+ .en_mask = BIT(10),
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_ops_vote,
+ CLK_INIT(gcc_boot_rom_ahb_clk.c),
+ },
+};
+
+static struct local_vote_clk gcc_ce1_ahb_clk = {
+ .cbcr_reg = CE1_AHB_CBCR,
+ .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+ .en_mask = BIT(3),
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_ce1_ahb_clk",
+ .ops = &clk_ops_vote,
+ CLK_INIT(gcc_ce1_ahb_clk.c),
+ },
+};
+
+static struct local_vote_clk gcc_ce1_axi_clk = {
+ .cbcr_reg = CE1_AXI_CBCR,
+ .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+ .en_mask = BIT(4),
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_ce1_axi_clk",
+ .ops = &clk_ops_vote,
+ CLK_INIT(gcc_ce1_axi_clk.c),
+ },
+};
+
+static struct local_vote_clk gcc_ce1_clk = {
+ .cbcr_reg = CE1_CBCR,
+ .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+ .en_mask = BIT(5),
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_ce1_clk",
+ .ops = &clk_ops_vote,
+ CLK_INIT(gcc_ce1_clk.c),
+ },
+};
+
+static struct branch_clk gcc_copss_smmu_ahb_clk = {
+ .cbcr_reg = COPSS_SMMU_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_copss_smmu_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_copss_smmu_ahb_clk.c),
+ },
+};
+
+static struct branch_clk gcc_lpss_smmu_ahb_clk = {
+ .cbcr_reg = LPSS_SMMU_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_lpss_smmu_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_lpss_smmu_ahb_clk.c),
+ },
+};
+
+static struct branch_clk gcc_gp1_clk = {
+ .cbcr_reg = GP1_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &gp1_clk_src.c,
+ .dbg_name = "gcc_gp1_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_gp1_clk.c),
+ },
+};
+
+static struct branch_clk gcc_gp2_clk = {
+ .cbcr_reg = GP2_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &gp2_clk_src.c,
+ .dbg_name = "gcc_gp2_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_gp2_clk.c),
+ },
+};
+
+static struct branch_clk gcc_gp3_clk = {
+ .cbcr_reg = GP3_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &gp3_clk_src.c,
+ .dbg_name = "gcc_gp3_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_gp3_clk.c),
+ },
+};
+
+static struct branch_clk gcc_lpass_q6_axi_clk = {
+ .cbcr_reg = LPASS_Q6_AXI_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_lpass_q6_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_lpass_q6_axi_clk.c),
+ },
+};
+
+static struct branch_clk gcc_mmss_noc_cfg_ahb_clk = {
+ .cbcr_reg = MMSS_NOC_CFG_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_mmss_noc_cfg_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_mmss_noc_cfg_ahb_clk.c),
+ },
+};
+
+static struct branch_clk gcc_mss_cfg_ahb_clk = {
+ .cbcr_reg = MSS_CFG_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_mss_cfg_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_mss_cfg_ahb_clk.c),
+ },
+};
+
+static struct branch_clk gcc_mss_q6_bimc_axi_clk = {
+ .cbcr_reg = MSS_Q6_BIMC_AXI_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_mss_q6_bimc_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_mss_q6_bimc_axi_clk.c),
+ },
+};
+
+static struct branch_clk gcc_pdm2_clk = {
+ .cbcr_reg = PDM2_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &pdm2_clk_src.c,
+ .dbg_name = "gcc_pdm2_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_pdm2_clk.c),
+ },
+};
+
+static struct branch_clk gcc_pdm_ahb_clk = {
+ .cbcr_reg = PDM_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_pdm_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_pdm_ahb_clk.c),
+ },
+};
+
+static struct local_vote_clk gcc_prng_ahb_clk = {
+ .cbcr_reg = PRNG_AHB_CBCR,
+ .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+ .en_mask = BIT(13),
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_prng_ahb_clk",
+ .ops = &clk_ops_vote,
+ CLK_INIT(gcc_prng_ahb_clk.c),
+ },
+};
+
+static struct branch_clk gcc_sdcc1_ahb_clk = {
+ .cbcr_reg = SDCC1_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_sdcc1_ahb_clk.c),
+ },
+};
+
+static struct branch_clk gcc_sdcc1_apps_clk = {
+ .cbcr_reg = SDCC1_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &sdcc1_apps_clk_src.c,
+ .dbg_name = "gcc_sdcc1_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_sdcc1_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_sdcc2_ahb_clk = {
+ .cbcr_reg = SDCC2_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_sdcc2_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_sdcc2_ahb_clk.c),
+ },
+};
+
+static struct branch_clk gcc_sdcc2_apps_clk = {
+ .cbcr_reg = SDCC2_APPS_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &sdcc2_apps_clk_src.c,
+ .dbg_name = "gcc_sdcc2_apps_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_sdcc2_apps_clk.c),
+ },
+};
+
+static struct branch_clk gcc_usb2a_phy_sleep_clk = {
+ .cbcr_reg = USB2A_PHY_SLEEP_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_usb2a_phy_sleep_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb2a_phy_sleep_clk.c),
+ },
+};
+
+static struct branch_clk gcc_usb_hs_ahb_clk = {
+ .cbcr_reg = USB_HS_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_usb_hs_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb_hs_ahb_clk.c),
+ },
+};
+
+static struct branch_clk gcc_usb_hs_system_clk = {
+ .cbcr_reg = USB_HS_SYSTEM_CBCR,
+ .has_sibling = 0,
+ .bcr_reg = USB_HS_BCR,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .parent = &usb_hs_system_clk_src.c,
+ .dbg_name = "gcc_usb_hs_system_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb_hs_system_clk.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_csi0_1_clk[] = {
+ F_MM(100000000, gpll0, 6, 0, 0),
+ F_MM(200000000, mmpll0, 4, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk csi0_clk_src = {
+ .cmd_rcgr_reg = CSI0_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_csi0_1_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "csi0_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+ CLK_INIT(csi0_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_mmss_mmssnoc_ahb_clk[] = {
+ F_MM(19200000, gcc_xo, 1, 0, 0),
+ F_MM(40000000, gpll0, 15, 0, 0),
+ F_MM(80000000, mmpll0, 10, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk ahb_clk_src = {
+ .cmd_rcgr_reg = AHB_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_mmss_mmssnoc_ahb_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "ahb_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP2(LOW, 40000000, NOMINAL, 80000000),
+ CLK_INIT(ahb_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_mmss_mmssnoc_axi_clk[] = {
+ F_MM( 19200000, gcc_xo, 1, 0, 0),
+ F_MM( 37500000, gpll0, 16, 0, 0),
+ F_MM( 50000000, gpll0, 12, 0, 0),
+ F_MM( 75000000, gpll0, 8, 0, 0),
+ F_MM(100000000, gpll0, 6, 0, 0),
+ F_MM(150000000, gpll0, 4, 0, 0),
+ F_MM(200000000, mmpll0, 4, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk axi_clk_src = {
+ .cmd_rcgr_reg = AXI_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_mmss_mmssnoc_axi_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "axi_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+ CLK_INIT(axi_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_dsi_pclk_clk[] = {
+ F_MDSS( 50000000, dsipll, 10, 0, 0),
+ F_MDSS(103330000, dsipll, 9, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk dsi_pclk_clk_src = {
+ .cmd_rcgr_reg = DSI_PCLK_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_dsi_pclk_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "dsi_pclk_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 103330000),
+ CLK_INIT(dsi_pclk_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_oxili_gfx3d_clk[] = {
+ F_MM( 19200000, gcc_xo, 1, 0, 0),
+ F_MM( 37500000, gpll0, 16, 0, 0),
+ F_MM( 50000000, gpll0, 12, 0, 0),
+ F_MM( 75000000, gpll0, 8, 0, 0),
+ F_MM(100000000, gpll0, 6, 0, 0),
+ F_MM(150000000, gpll0, 4, 0, 0),
+ F_MM(200000000, gpll0, 3, 0, 0),
+ F_MM(300000000, gpll0, 2, 0, 0),
+ F_MM(400000000, mmpll1, 3, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk gfx3d_clk_src = {
+ .cmd_rcgr_reg = GFX3D_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_oxili_gfx3d_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "gfx3d_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP3(LOW, 150000000, NOMINAL, 300000000, HIGH,
+ 400000000),
+ CLK_INIT(gfx3d_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_vfe_clk[] = {
+ F_MM( 37500000, gpll0, 16, 0, 0),
+ F_MM( 50000000, gpll0, 12, 0, 0),
+ F_MM( 60000000, gpll0, 10, 0, 0),
+ F_MM( 80000000, gpll0, 7.5, 0, 0),
+ F_MM(100000000, gpll0, 6, 0, 0),
+ F_MM(109090000, gpll0, 5.5, 0, 0),
+ F_MM(133330000, gpll0, 4.5, 0, 0),
+ F_MM(200000000, gpll0, 3, 0, 0),
+ F_MM(228570000, mmpll0, 3.5, 0, 0),
+ F_MM(266670000, mmpll0, 3, 0, 0),
+ F_MM(320000000, mmpll0, 2.5, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk vfe_clk_src = {
+ .cmd_rcgr_reg = VFE_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_vfe_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "vfe_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP3(LOW, 133330000, NOMINAL, 266670000, HIGH,
+ 320000000),
+ CLK_INIT(vfe_clk_src.c),
+ },
+};
+
+static struct rcg_clk csi1_clk_src = {
+ .cmd_rcgr_reg = CSI1_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_csi0_1_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "csi1_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+ CLK_INIT(csi1_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_csi0_1phytimer_clk[] = {
+ F_MM(100000000, gpll0, 6, 0, 0),
+ F_MM(200000000, mmpll0, 4, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk csi0phytimer_clk_src = {
+ .cmd_rcgr_reg = CSI0PHYTIMER_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_csi0_1phytimer_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "csi0phytimer_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+ CLK_INIT(csi0phytimer_clk_src.c),
+ },
+};
+
+static struct rcg_clk csi1phytimer_clk_src = {
+ .cmd_rcgr_reg = CSI1PHYTIMER_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_csi0_1phytimer_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "csi1phytimer_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
+ CLK_INIT(csi1phytimer_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_dsi_clk[] = {
+ F_MDSS(155000000, dsipll, 6, 0, 0),
+ F_MDSS(310000000, dsipll, 3, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk dsi_clk_src = {
+ .cmd_rcgr_reg = DSI_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_dsi_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "dsi_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 155000000, NOMINAL, 310000000),
+ CLK_INIT(dsi_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_dsi_byte_clk[] = {
+ F_MDSS( 62500000, dsipll, 12, 0, 0),
+ F_MDSS(125000000, dsipll, 6, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk dsi_byte_clk_src = {
+ .cmd_rcgr_reg = DSI_BYTE_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_dsi_byte_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "dsi_byte_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP2(LOW, 62500000, NOMINAL, 125000000),
+ CLK_INIT(dsi_byte_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_dsi_esc_clk[] = {
+ F_MM(19200000, gcc_xo, 1, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk dsi_esc_clk_src = {
+ .cmd_rcgr_reg = DSI_ESC_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_dsi_esc_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "dsi_esc_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP1(LOW, 19200000),
+ CLK_INIT(dsi_esc_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_mclk0_1_clk[] = {
+ F_MM(66670000, gpll0, 9, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk mclk0_clk_src = {
+ .cmd_rcgr_reg = MCLK0_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_mclk0_1_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "mclk0_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP1(LOW, 66670000),
+ CLK_INIT(mclk0_clk_src.c),
+ },
+};
+
+static struct rcg_clk mclk1_clk_src = {
+ .cmd_rcgr_reg = MCLK1_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_mclk0_1_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "mclk1_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP1(LOW, 66670000),
+ CLK_INIT(mclk1_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_mdp_vsync_clk[] = {
+ F_MM(19200000, gcc_xo, 1, 0, 0),
+ F_END,
+};
+
+static struct rcg_clk mdp_vsync_clk_src = {
+ .cmd_rcgr_reg = MDP_VSYNC_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_mdp_vsync_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "mdp_vsync_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP1(LOW, 19200000),
+ CLK_INIT(mdp_vsync_clk_src.c),
+ },
+};
+
+static struct branch_clk bimc_gfx_clk = {
+ .cbcr_reg = BIMC_GFX_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "bimc_gfx_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(bimc_gfx_clk.c),
+ },
+};
+
+static struct branch_clk csi0_clk = {
+ .cbcr_reg = CSI0_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &csi0_clk_src.c,
+ .dbg_name = "csi0_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi0_clk.c),
+ },
+};
+
+static struct branch_clk csi0phy_clk = {
+ .cbcr_reg = CSI0PHY_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &csi0_clk_src.c,
+ .dbg_name = "csi0phy_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi0phy_clk.c),
+ },
+};
+
+static struct branch_clk csi0phytimer_clk = {
+ .cbcr_reg = CSI0PHYTIMER_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &csi0phytimer_clk_src.c,
+ .dbg_name = "csi0phytimer_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi0phytimer_clk.c),
+ },
+};
+
+static struct branch_clk csi0pix_clk = {
+ .cbcr_reg = CSI0PIX_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &csi0_clk_src.c,
+ .dbg_name = "csi0pix_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi0pix_clk.c),
+ },
+};
+
+static struct branch_clk csi0rdi_clk = {
+ .cbcr_reg = CSI0RDI_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &csi0_clk_src.c,
+ .dbg_name = "csi0rdi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi0rdi_clk.c),
+ },
+};
+
+static struct branch_clk csi1_clk = {
+ .cbcr_reg = CSI1_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &csi1_clk_src.c,
+ .dbg_name = "csi1_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi1_clk.c),
+ },
+};
+
+static struct branch_clk csi1phy_clk = {
+ .cbcr_reg = CSI1PHY_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &csi1_clk_src.c,
+ .dbg_name = "csi1phy_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi1phy_clk.c),
+ },
+};
+
+static struct branch_clk csi1phytimer_clk = {
+ .cbcr_reg = CSI1PHYTIMER_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &csi1phytimer_clk_src.c,
+ .dbg_name = "csi1phytimer_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi1phytimer_clk.c),
+ },
+};
+
+static struct branch_clk csi1pix_clk = {
+ .cbcr_reg = CSI1PIX_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &csi0_clk_src.c,
+ .dbg_name = "csi1pix_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi1pix_clk.c),
+ },
+};
+
+static struct branch_clk csi1rdi_clk = {
+ .cbcr_reg = CSI1RDI_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &csi0_clk_src.c,
+ .dbg_name = "csi1rdi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi1rdi_clk.c),
+ },
+};
+
+static struct branch_clk csi_ahb_clk = {
+ .cbcr_reg = CSI_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "csi_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi_ahb_clk.c),
+ },
+};
+
+static struct branch_clk csi_vfe_clk = {
+ .cbcr_reg = CSI_VFE_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &vfe_clk_src.c,
+ .dbg_name = "csi_vfe_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(csi_vfe_clk.c),
+ },
+};
+
+static struct branch_clk dsi_clk = {
+ .cbcr_reg = DSI_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &dsi_clk_src.c,
+ .dbg_name = "dsi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(dsi_clk.c),
+ },
+};
+
+static struct branch_clk dsi_ahb_clk = {
+ .cbcr_reg = DSI_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "dsi_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(dsi_ahb_clk.c),
+ },
+};
+
+static struct branch_clk dsi_byte_clk = {
+ .cbcr_reg = DSI_BYTE_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &dsi_byte_clk_src.c,
+ .dbg_name = "dsi_byte_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(dsi_byte_clk.c),
+ },
+};
+
+static struct branch_clk dsi_esc_clk = {
+ .cbcr_reg = DSI_ESC_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &dsi_esc_clk_src.c,
+ .dbg_name = "dsi_esc_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(dsi_esc_clk.c),
+ },
+};
+
+static struct branch_clk dsi_pclk_clk = {
+ .cbcr_reg = DSI_PCLK_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &dsi_pclk_clk_src.c,
+ .dbg_name = "dsi_pclk_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(dsi_pclk_clk.c),
+ },
+};
+
+static struct branch_clk gmem_gfx3d_clk = {
+ .cbcr_reg = GMEM_GFX3D_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &gfx3d_clk_src.c,
+ .dbg_name = "gmem_gfx3d_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gmem_gfx3d_clk.c),
+ },
+};
+
+static struct branch_clk mclk0_clk = {
+ .cbcr_reg = MCLK0_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &mclk0_clk_src.c,
+ .dbg_name = "mclk0_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mclk0_clk.c),
+ },
+};
+
+static struct branch_clk mclk1_clk = {
+ .cbcr_reg = MCLK1_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &mclk1_clk_src.c,
+ .dbg_name = "mclk1_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mclk1_clk.c),
+ },
+};
+
+static struct branch_clk mdp_ahb_clk = {
+ .cbcr_reg = MDP_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "mdp_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mdp_ahb_clk.c),
+ },
+};
+
+static struct branch_clk mdp_axi_clk = {
+ .cbcr_reg = MDP_AXI_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &axi_clk_src.c,
+ .dbg_name = "mdp_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mdp_axi_clk.c),
+ },
+};
+
+static struct branch_clk mdp_dsi_clk = {
+ .cbcr_reg = MDP_DSI_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &dsi_pclk_clk_src.c,
+ .dbg_name = "mdp_dsi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mdp_dsi_clk.c),
+ },
+};
+
+static struct branch_clk mdp_lcdc_clk = {
+ .cbcr_reg = MDP_LCDC_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &dsi_pclk_clk_src.c,
+ .dbg_name = "mdp_lcdc_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mdp_lcdc_clk.c),
+ },
+};
+
+static struct branch_clk mdp_vsync_clk = {
+ .cbcr_reg = MDP_VSYNC_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &mdp_vsync_clk_src.c,
+ .dbg_name = "mdp_vsync_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mdp_vsync_clk.c),
+ },
+};
+
+static struct branch_clk mmss_misc_ahb_clk = {
+ .cbcr_reg = MMSS_MISC_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "mmss_misc_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mmss_misc_ahb_clk.c),
+ },
+};
+
+static struct branch_clk mmss_mmssnoc_axi_clk = {
+ .cbcr_reg = MMSS_MMSSNOC_AXI_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &axi_clk_src.c,
+ .dbg_name = "mmss_mmssnoc_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mmss_mmssnoc_axi_clk.c),
+ },
+};
+
+static struct branch_clk mmss_s0_axi_clk = {
+ .cbcr_reg = MMSS_S0_AXI_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &axi_clk_src.c,
+ .dbg_name = "mmss_s0_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mmss_s0_axi_clk.c),
+ .depends = &mmss_mmssnoc_axi_clk.c,
+ },
+};
+
+static struct branch_clk mmss_mmssnoc_ahb_clk = {
+ .cbcr_reg = MMSS_MMSSNOC_AHB_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &ahb_clk_src.c,
+ .dbg_name = "mmss_mmssnoc_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mmss_mmssnoc_ahb_clk.c),
+ },
+};
+
+static struct branch_clk mmss_mmssnoc_bto_ahb_clk = {
+ .cbcr_reg = MMSS_MMSSNOC_BTO_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "mmss_mmssnoc_bto_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(mmss_mmssnoc_bto_ahb_clk.c),
+ },
+};
+
+static struct branch_clk oxili_ahb_clk = {
+ .cbcr_reg = OXILI_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "oxili_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(oxili_ahb_clk.c),
+ },
+};
+
+static struct branch_clk oxili_gfx3d_clk = {
+ .cbcr_reg = OXILI_GFX3D_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &gfx3d_clk_src.c,
+ .dbg_name = "oxili_gfx3d_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(oxili_gfx3d_clk.c),
+ },
+};
+
+static struct branch_clk vfe_clk = {
+ .cbcr_reg = VFE_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &vfe_clk_src.c,
+ .dbg_name = "vfe_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(vfe_clk.c),
+ },
+};
+
+static struct branch_clk vfe_ahb_clk = {
+ .cbcr_reg = VFE_AHB_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "vfe_ahb_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(vfe_ahb_clk.c),
+ },
+};
+
+static struct branch_clk vfe_axi_clk = {
+ .cbcr_reg = VFE_AXI_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .parent = &axi_clk_src.c,
+ .dbg_name = "vfe_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(vfe_axi_clk.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_audio_core_lpaif_clk[] = {
+ F_LPASS( 512000, lpapll0, 16, 1, 60),
+ F_LPASS( 768000, lpapll0, 16, 1, 40),
+ F_LPASS( 1024000, lpapll0, 16, 1, 30),
+ F_LPASS( 1536000, lpapll0, 16, 1, 20),
+ F_LPASS( 2048000, lpapll0, 16, 1, 15),
+ F_LPASS( 3072000, lpapll0, 16, 1, 10),
+ F_LPASS( 4096000, lpapll0, 15, 1, 8),
+ F_LPASS( 6144000, lpapll0, 10, 1, 8),
+ F_LPASS( 8192000, lpapll0, 15, 1, 4),
+ F_LPASS(12288000, lpapll0, 10, 1, 4),
+ F_END,
+};
+
+static struct rcg_clk lpaif_pri_clk_src = {
+ .cmd_rcgr_reg = LPAIF_PRI_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_audio_core_lpaif_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "lpaif_pri_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+ CLK_INIT(lpaif_pri_clk_src.c),
+ },
+};
+
+static struct rcg_clk lpaif_quad_clk_src = {
+ .cmd_rcgr_reg = LPAIF_QUAD_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_audio_core_lpaif_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "lpaif_quad_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+ CLK_INIT(lpaif_quad_clk_src.c),
+ },
+};
+
+static struct rcg_clk lpaif_sec_clk_src = {
+ .cmd_rcgr_reg = LPAIF_SEC_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_audio_core_lpaif_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "lpaif_sec_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+ CLK_INIT(lpaif_sec_clk_src.c),
+ },
+};
+
+static struct rcg_clk lpaif_spkr_clk_src = {
+ .cmd_rcgr_reg = LPAIF_SPKR_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_audio_core_lpaif_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "lpaif_spkr_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+ CLK_INIT(lpaif_spkr_clk_src.c),
+ },
+};
+
+static struct rcg_clk lpaif_ter_clk_src = {
+ .cmd_rcgr_reg = LPAIF_TER_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_audio_core_lpaif_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "lpaif_ter_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
+ CLK_INIT(lpaif_ter_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_audio_core_lpaif_pcm0_1_clk[] = {
+ F_LPASS( 512000, lpapll0, 16, 1, 60),
+ F_LPASS( 768000, lpapll0, 16, 1, 40),
+ F_LPASS(1024000, lpapll0, 16, 1, 30),
+ F_LPASS(1536000, lpapll0, 16, 1, 20),
+ F_LPASS(2048000, lpapll0, 16, 1, 15),
+ F_LPASS(3072000, lpapll0, 16, 1, 10),
+ F_LPASS(4096000, lpapll0, 15, 1, 8),
+ F_LPASS(6144000, lpapll0, 10, 1, 8),
+ F_LPASS(8192000, lpapll0, 15, 1, 4),
+ F_END,
+};
+
+static struct rcg_clk lpaif_pcm0_clk_src = {
+ .cmd_rcgr_reg = LPAIF_PCM0_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_audio_core_lpaif_pcm0_1_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "lpaif_pcm0_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 4100000, NOMINAL, 8192000),
+ CLK_INIT(lpaif_pcm0_clk_src.c),
+ },
+};
+
+static struct rcg_clk lpaif_pcm1_clk_src = {
+ .cmd_rcgr_reg = LPAIF_PCM1_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_audio_core_lpaif_pcm0_1_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "lpaif_pcm1_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 4100000, NOMINAL, 8192000),
+ CLK_INIT(lpaif_pcm1_clk_src.c),
+ },
+};
+
+static struct rcg_clk lpaif_pcmoe_clk_src = {
+ .cmd_rcgr_reg = LPAIF_PCMOE_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_audio_core_lpaif_pcm0_1_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "lpaif_pcmoe_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 6140000, NOMINAL, 12290000),
+ CLK_INIT(lpaif_pcmoe_clk_src.c),
+ },
+};
+
+static struct clk_freq_tbl ftbl_audio_core_slimbus_core_clock[] = {
+ F_LPASS(24576000, lpapll0, 4, 1, 5),
+ F_END
+};
+
+static struct rcg_clk audio_core_slimbus_core_clk_src = {
+ .cmd_rcgr_reg = SLIMBUS_CMD_RCGR,
+ .set_rate = set_rate_mnd,
+ .freq_tbl = ftbl_audio_core_slimbus_core_clock,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_slimbus_core_clk_src",
+ .ops = &clk_ops_rcg_mnd,
+ VDD_DIG_FMAX_MAP2(LOW, 12935000, NOMINAL, 25869000),
+ CLK_INIT(audio_core_slimbus_core_clk_src.c),
+ },
+};
+
+static struct branch_clk audio_core_slimbus_core_clk = {
+ .cbcr_reg = AUDIO_CORE_SLIMBUS_CORE_CBCR,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &audio_core_slimbus_core_clk_src.c,
+ .dbg_name = "audio_core_slimbus_core_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_slimbus_core_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_ixfabric_clk = {
+ .cbcr_reg = AUDIO_CORE_IXFABRIC_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_ixfabric_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_ixfabric_clk.c),
+ },
+};
+
+static struct branch_clk audio_wrapper_br_clk = {
+ .cbcr_reg = AUDIO_WRAPPER_BR_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_wrapper_br_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_wrapper_br_clk.c),
+ },
+};
+
+static struct branch_clk q6ss_ahb_lfabif_clk = {
+ .cbcr_reg = Q6SS_AHB_LFABIF_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "q6ss_ahb_lfabif_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(q6ss_ahb_lfabif_clk.c),
+ },
+};
+
+static struct branch_clk q6ss_ahbm_clk = {
+ .cbcr_reg = Q6SS_AHBM_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "q6ss_ahbm_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(q6ss_ahbm_clk.c),
+ },
+};
+
+static struct branch_clk q6ss_xo_clk = {
+ .cbcr_reg = Q6SS_XO_CBCR,
+ .has_sibling = 1,
+ .bcr_reg = LPASS_Q6SS_BCR,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &gcc_xo_clk_src.c,
+ .dbg_name = "q6ss_xo_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(q6ss_xo_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_pcm_data_oe_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_pcmoe_clk_src.c,
+ .dbg_name = "audio_core_lpaif_pcm_data_oe_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_pcm_data_oe_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_pri_ebit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_PRI_EBIT_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_lpaif_pri_ebit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_pri_ebit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_pri_ibit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_PRI_IBIT_CBCR,
+ .has_sibling = 0,
+ .max_div = 511,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_pri_clk_src.c,
+ .dbg_name = "audio_core_lpaif_pri_ibit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_pri_ibit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_pri_osr_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_PRI_OSR_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_pri_clk_src.c,
+ .dbg_name = "audio_core_lpaif_pri_osr_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_pri_osr_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_pcm0_ebit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_lpaif_pcm0_ebit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_pcm0_ebit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_pcm0_ibit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_pcm0_clk_src.c,
+ .dbg_name = "audio_core_lpaif_pcm0_ibit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_pcm0_ibit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_quad_ebit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_QUAD_EBIT_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_lpaif_quad_ebit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_quad_ebit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_quad_ibit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_QUAD_IBIT_CBCR,
+ .has_sibling = 0,
+ .max_div = 511,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_quad_clk_src.c,
+ .dbg_name = "audio_core_lpaif_quad_ibit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_quad_ibit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_quad_osr_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_QUAD_OSR_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_quad_clk_src.c,
+ .dbg_name = "audio_core_lpaif_quad_osr_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_quad_osr_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_sec_ebit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_SEC_EBIT_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_lpaif_sec_ebit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_sec_ebit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_sec_ibit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_SEC_IBIT_CBCR,
+ .has_sibling = 0,
+ .max_div = 511,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_sec_clk_src.c,
+ .dbg_name = "audio_core_lpaif_sec_ibit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_sec_ibit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_sec_osr_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_SEC_OSR_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_sec_clk_src.c,
+ .dbg_name = "audio_core_lpaif_sec_osr_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_sec_osr_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_pcm1_ebit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_lpaif_pcm1_ebit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_pcm1_ebit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_pcm1_ibit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_pcm1_clk_src.c,
+ .dbg_name = "audio_core_lpaif_pcm1_ibit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_pcm1_ibit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_codec_spkr_ebit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_lpaif_codec_spkr_ebit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_codec_spkr_ebit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_codec_spkr_ibit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR,
+ .has_sibling = 1,
+ .max_div = 511,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_spkr_clk_src.c,
+ .dbg_name = "audio_core_lpaif_codec_spkr_ibit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_codec_spkr_ibit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_codec_spkr_osr_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_spkr_clk_src.c,
+ .dbg_name = "audio_core_lpaif_codec_spkr_osr_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_codec_spkr_osr_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_ter_ebit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_TER_EBIT_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_lpaif_ter_ebit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_ter_ebit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_ter_ibit_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_TER_IBIT_CBCR,
+ .has_sibling = 0,
+ .max_div = 511,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_ter_clk_src.c,
+ .dbg_name = "audio_core_lpaif_ter_ibit_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_ter_ibit_clk.c),
+ },
+};
+
+static struct branch_clk audio_core_lpaif_ter_osr_clk = {
+ .cbcr_reg = AUDIO_CORE_LPAIF_TER_OSR_CBCR,
+ .has_sibling = 0,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .parent = &lpaif_ter_clk_src.c,
+ .dbg_name = "audio_core_lpaif_ter_osr_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_lpaif_ter_osr_clk.c),
+ },
+};
+
+#ifdef CONFIG_DEBUG_FS
+
+struct measure_mux_entry {
+ struct clk *c;
+ int base;
+ u32 debug_mux;
+};
+
+static struct measure_mux_entry measure_mux[] = {
+ { &snoc_clk.c, GCC_BASE, 0x0000},
+ { &cnoc_clk.c, GCC_BASE, 0x0008},
+ { &gcc_copss_smmu_ahb_clk.c, GCC_BASE, 0x000c},
+ { &gcc_lpss_smmu_ahb_clk.c, GCC_BASE, 0x000d},
+ { &pnoc_clk.c, GCC_BASE, 0x0010},
+ { &gcc_mmss_noc_cfg_ahb_clk.c, GCC_BASE, 0x002a},
+ { &gcc_mss_cfg_ahb_clk.c, GCC_BASE, 0x0030},
+ { &gcc_mss_q6_bimc_axi_clk.c, GCC_BASE, 0x0031},
+ { &gcc_usb_hs_system_clk.c, GCC_BASE, 0x0060},
+ { &gcc_usb_hs_ahb_clk.c, GCC_BASE, 0x0061},
+ { &gcc_usb2a_phy_sleep_clk.c, GCC_BASE, 0x0063},
+ { &gcc_sdcc1_apps_clk.c, GCC_BASE, 0x0068},
+ { &gcc_sdcc1_ahb_clk.c, GCC_BASE, 0x0069},
+ { &gcc_sdcc2_apps_clk.c, GCC_BASE, 0x0070},
+ { &gcc_sdcc2_ahb_clk.c, GCC_BASE, 0x0071},
+ { &gcc_blsp1_ahb_clk.c, GCC_BASE, 0x0088},
+ {&gcc_blsp1_qup1_spi_apps_clk.c, GCC_BASE, 0x008a},
+ {&gcc_blsp1_qup1_i2c_apps_clk.c, GCC_BASE, 0x008b},
+ { &gcc_blsp1_uart1_apps_clk.c, GCC_BASE, 0x008c},
+ {&gcc_blsp1_qup2_spi_apps_clk.c, GCC_BASE, 0x008e},
+ {&gcc_blsp1_qup2_i2c_apps_clk.c, GCC_BASE, 0x0090},
+ { &gcc_blsp1_uart2_apps_clk.c, GCC_BASE, 0x0091},
+ {&gcc_blsp1_qup3_spi_apps_clk.c, GCC_BASE, 0x0093},
+ {&gcc_blsp1_qup3_i2c_apps_clk.c, GCC_BASE, 0x0094},
+ { &gcc_blsp1_uart3_apps_clk.c, GCC_BASE, 0x0095},
+ {&gcc_blsp1_qup4_spi_apps_clk.c, GCC_BASE, 0x0098},
+ {&gcc_blsp1_qup4_i2c_apps_clk.c, GCC_BASE, 0x0099},
+ { &gcc_blsp1_uart4_apps_clk.c, GCC_BASE, 0x009a},
+ {&gcc_blsp1_qup5_spi_apps_clk.c, GCC_BASE, 0x009c},
+ {&gcc_blsp1_qup5_i2c_apps_clk.c, GCC_BASE, 0x009d},
+ { &gcc_blsp1_uart5_apps_clk.c, GCC_BASE, 0x009e},
+ {&gcc_blsp1_qup6_spi_apps_clk.c, GCC_BASE, 0x00a1},
+ {&gcc_blsp1_qup6_i2c_apps_clk.c, GCC_BASE, 0x00a2},
+ { &gcc_blsp1_uart6_apps_clk.c, GCC_BASE, 0x00a3},
+ { &gcc_pdm_ahb_clk.c, GCC_BASE, 0x00d0},
+ { &gcc_pdm2_clk.c, GCC_BASE, 0x00d2},
+ { &gcc_prng_ahb_clk.c, GCC_BASE, 0x00d8},
+ { &gcc_boot_rom_ahb_clk.c, GCC_BASE, 0x00f8},
+ { &gcc_ce1_clk.c, GCC_BASE, 0x0138},
+ { &gcc_ce1_axi_clk.c, GCC_BASE, 0x0139},
+ { &gcc_ce1_ahb_clk.c, GCC_BASE, 0x013a},
+ { &gcc_xo_clk_src.c, GCC_BASE, 0x0149},
+ { &bimc_clk.c, GCC_BASE, 0x0154},
+ { &gcc_lpass_q6_axi_clk.c, GCC_BASE, 0x0160},
+
+ {&mmss_mmssnoc_ahb_clk.c, MMSS_BASE, 0x0001},
+ { &mmss_misc_ahb_clk.c, MMSS_BASE, 0x0003},
+ {&mmss_mmssnoc_axi_clk.c, MMSS_BASE, 0x0004},
+ { &mmss_s0_axi_clk.c, MMSS_BASE, 0x0005},
+ { &oxili_ahb_clk.c, MMSS_BASE, 0x0007},
+ { &oxili_gfx3d_clk.c, MMSS_BASE, 0x0008},
+ { &gmem_gfx3d_clk.c, MMSS_BASE, 0x0009},
+ { &mdp_axi_clk.c, MMSS_BASE, 0x000a},
+ { &mdp_vsync_clk.c, MMSS_BASE, 0x000b},
+ { &mdp_ahb_clk.c, MMSS_BASE, 0x000c},
+ { &dsi_pclk_clk.c, MMSS_BASE, 0x000d},
+ { &mdp_dsi_clk.c, MMSS_BASE, 0x000e},
+ { &mdp_lcdc_clk.c, MMSS_BASE, 0x000f},
+ { &dsi_clk.c, MMSS_BASE, 0x0010},
+ { &dsi_byte_clk.c, MMSS_BASE, 0x0011},
+ { &dsi_esc_clk.c, MMSS_BASE, 0x0012},
+ { &dsi_ahb_clk.c, MMSS_BASE, 0x0013},
+ { &mclk0_clk.c, MMSS_BASE, 0x0015},
+ { &mclk1_clk.c, MMSS_BASE, 0x0016},
+ { &csi0phytimer_clk.c, MMSS_BASE, 0x0017},
+ { &csi1phytimer_clk.c, MMSS_BASE, 0x0018},
+ { &vfe_clk.c, MMSS_BASE, 0x0019},
+ { &vfe_ahb_clk.c, MMSS_BASE, 0x001a},
+ { &vfe_axi_clk.c, MMSS_BASE, 0x001b},
+ { &csi_vfe_clk.c, MMSS_BASE, 0x001c},
+ { &csi0_clk.c, MMSS_BASE, 0x001d},
+ { &csi_ahb_clk.c, MMSS_BASE, 0x001e},
+ { &csi0phy_clk.c, MMSS_BASE, 0x001f},
+ { &csi0rdi_clk.c, MMSS_BASE, 0x0020},
+ { &csi0pix_clk.c, MMSS_BASE, 0x0021},
+ { &csi1_clk.c, MMSS_BASE, 0x0022},
+ { &csi1phy_clk.c, MMSS_BASE, 0x0023},
+ { &csi1rdi_clk.c, MMSS_BASE, 0x0024},
+ { &csi1pix_clk.c, MMSS_BASE, 0x0025},
+ { &bimc_gfx_clk.c, MMSS_BASE, 0x0032},
+
+ { &lpaif_pcmoe_clk_src.c, LPASS_BASE, 0x000f},
+ { &lpaif_pcm1_clk_src.c, LPASS_BASE, 0x0012},
+ { &lpaif_pcm0_clk_src.c, LPASS_BASE, 0x0013},
+ { &lpaif_quad_clk_src.c, LPASS_BASE, 0x0014},
+ { &lpaif_ter_clk_src.c, LPASS_BASE, 0x0015},
+ { &lpaif_sec_clk_src.c, LPASS_BASE, 0x0016},
+ { &lpaif_pri_clk_src.c, LPASS_BASE, 0x0017},
+ { &lpaif_spkr_clk_src.c, LPASS_BASE, 0x0018},
+ { &q6ss_ahbm_clk.c, LPASS_BASE, 0x001d},
+ { &q6ss_ahb_lfabif_clk.c, LPASS_BASE, 0x001e},
+ { &audio_wrapper_br_clk.c, LPASS_BASE, 0x0022},
+ { &q6ss_xo_clk.c, LPASS_BASE, 0x002b},
+ {&audio_core_lpaif_pcm_data_oe_clk.c, LPASS_BASE, 0x0030},
+ { &audio_core_ixfabric_clk.c, LPASS_BASE, 0x0059},
+
+ {&dummy_clk, N_BASES, 0x0000},
+};
+
+#define GCC_DEBUG_CLK_CTL 0x1880
+#define MMSS_DEBUG_CLK_CTL 0x0900
+#define LPASS_DEBUG_CLK_CTL 0x29000
+#define GLB_CLK_DIAG 0x001C
+
+static int measure_clk_set_parent(struct clk *c, struct clk *parent)
+{
+ struct measure_clk *clk = to_measure_clk(c);
+ unsigned long flags;
+ u32 regval, clk_sel, i;
+
+ if (!parent)
+ return -EINVAL;
+
+ for (i = 0; i < (ARRAY_SIZE(measure_mux) - 1); i++)
+ if (measure_mux[i].c == parent)
+ break;
+
+ if (measure_mux[i].c == &dummy_clk)
+ return -EINVAL;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ /*
+ * Program the test vector, measurement period (sample_ticks)
+ * and scaling multiplier.
+ */
+ clk->sample_ticks = 0x10000;
+ clk->multiplier = 1;
+
+ switch (measure_mux[i].base) {
+
+ case GCC_BASE:
+ writel_relaxed(0, GCC_REG_BASE(GCC_DEBUG_CLK_CTL));
+ clk_sel = measure_mux[i].debug_mux;
+ break;
+
+ case MMSS_BASE:
+ writel_relaxed(0, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL));
+ clk_sel = 0x02C;
+ regval = BVAL(11, 0, measure_mux[i].debug_mux);
+ writel_relaxed(regval, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL));
+
+ /* Activate debug clock output */
+ regval |= BIT(16);
+ writel_relaxed(regval, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL));
+ break;
+
+ case LPASS_BASE:
+ writel_relaxed(0, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL));
+ clk_sel = 0x161;
+ regval = BVAL(11, 0, measure_mux[i].debug_mux);
+ writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL));
+
+ /* Activate debug clock output */
+ regval |= BIT(20);
+ writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL));
+ break;
+
+ case APCS_BASE:
+ clk->multiplier = 4;
+ clk_sel = 0x16A;
+ regval = measure_mux[i].debug_mux;
+ writel_relaxed(regval, APCS_REG_BASE(GLB_CLK_DIAG));
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Set debug mux clock index */
+ regval = BVAL(8, 0, clk_sel);
+ writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL));
+
+ /* Activate debug clock output */
+ regval |= BIT(16);
+ writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL));
+
+ /* Make sure test vector is set before starting measurements. */
+ mb();
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ return 0;
+}
+
+#define CLOCK_FRQ_MEASURE_CTL 0x1884
+#define CLOCK_FRQ_MEASURE_STATUS 0x1888
+
+/* Sample clock for 'ticks' reference clock ticks. */
+static u32 run_measurement(unsigned ticks)
+{
+ /* Stop counters and set the XO4 counter start value. */
+ writel_relaxed(ticks, GCC_REG_BASE(CLOCK_FRQ_MEASURE_CTL));
+
+ /* Wait for timer to become ready. */
+ while ((readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS)) &
+ BIT(25)) != 0)
+ cpu_relax();
+
+ /* Run measurement and wait for completion. */
+ writel_relaxed(BIT(20)|ticks, GCC_REG_BASE(CLOCK_FRQ_MEASURE_CTL));
+ while ((readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS)) &
+ BIT(25)) == 0)
+ cpu_relax();
+
+ /* Return measured ticks. */
+ return readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS)) &
+ BM(24, 0);
+}
+
+#define GCC_XO_DIV4_CBCR 0x10C8
+#define PLLTEST_PAD_CFG 0x188C
+
+/*
+ * Perform a hardware rate measurement for a given clock.
+ * FOR DEBUG USE ONLY: Measurements take ~15 ms!
+ */
+static unsigned long measure_clk_get_rate(struct clk *c)
+{
+ unsigned long flags;
+ u32 gcc_xo4_reg_backup;
+ u64 raw_count_short, raw_count_full;
+ struct measure_clk *clk = to_measure_clk(c);
+ unsigned ret;
+
+ ret = clk_prepare_enable(&gcc_xo_clk_src.c);
+ if (ret) {
+ pr_warning("CXO clock failed to enable. Can't measure\n");
+ return 0;
+ }
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+ /* Enable CXO/4 and RINGOSC branch. */
+ gcc_xo4_reg_backup = readl_relaxed(GCC_REG_BASE(GCC_XO_DIV4_CBCR));
+ writel_relaxed(0x1, GCC_REG_BASE(GCC_XO_DIV4_CBCR));
+
+ /*
+ * The ring oscillator counter will not reset if the measured clock
+ * is not running. To detect this, run a short measurement before
+ * the full measurement. If the raw results of the two are the same
+ * then the clock must be off.
+ */
+
+ /* Run a short measurement. (~1 ms) */
+ raw_count_short = run_measurement(0x1000);
+ /* Run a full measurement. (~14 ms) */
+ raw_count_full = run_measurement(clk->sample_ticks);
+
+ writel_relaxed(gcc_xo4_reg_backup, GCC_REG_BASE(GCC_XO_DIV4_CBCR));
+
+ /* Return 0 if the clock is off. */
+ if (raw_count_full == raw_count_short) {
+ ret = 0;
+ } else {
+ /* Compute rate in Hz. */
+ raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
+ do_div(raw_count_full, ((clk->sample_ticks * 10) + 35));
+ ret = (raw_count_full * clk->multiplier);
+ }
+
+ writel_relaxed(0x51A00, GCC_REG_BASE(PLLTEST_PAD_CFG));
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ clk_disable_unprepare(&gcc_xo_clk_src.c);
+
+ return ret;
+}
+#else /* !CONFIG_DEBUG_FS */
+static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ return -EINVAL;
+}
+
+static unsigned long measure_clk_get_rate(struct clk *clk)
+{
+ return 0;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static struct clk_ops clk_ops_measure = {
+ .set_parent = measure_clk_set_parent,
+ .get_rate = measure_clk_get_rate,
+};
+
+static struct measure_clk measure_clk = {
+ .c = {
+ .dbg_name = "measure_clk",
+ .ops = &clk_ops_measure,
+ CLK_INIT(measure_clk.c),
+ },
+ .multiplier = 1,
+};
+
+static struct clk_lookup msm_clocks_8910[] = {
+ CLK_LOOKUP("xo", gcc_xo_clk_src.c, "msm_otg"),
+ CLK_LOOKUP("xo", gcc_xo_clk_src.c, "fe200000.qcom,lpass"),
+ CLK_LOOKUP("xo", gcc_xo_clk_src.c, "pil-q6v5-mss"),
+ CLK_LOOKUP("xo", gcc_xo_clk_src.c, "pil-mba"),
+ CLK_LOOKUP("xo", gcc_xo_clk_src.c, "fb000000.qcom,wcnss-wlan"),
+ CLK_LOOKUP("xo", gcc_xo_clk_src.c, "pil_pronto"),
+ CLK_LOOKUP("measure", measure_clk.c, "debug"),
+
+ CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f991f000.serial"),
+ CLK_LOOKUP("core_clk", gcc_blsp1_uart3_apps_clk.c, "f991f000.serial"),
+
+ CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
+ CLK_LOOKUP("bus_clk", pnoc_qseecom_clk.c, "qseecom"),
+
+ CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
+ CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cnoc_clk.c, ""),
+ CLK_LOOKUP("mem_clk", bimc_clk.c, ""),
+ CLK_LOOKUP("bus_clk", snoc_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", pnoc_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cnoc_a_clk.c, ""),
+ CLK_LOOKUP("mem_clk", bimc_a_clk.c, ""),
+
+ CLK_LOOKUP("bus_clk", cnoc_msmbus_clk.c, "msm_config_noc"),
+ CLK_LOOKUP("bus_a_clk", cnoc_msmbus_a_clk.c, "msm_config_noc"),
+ CLK_LOOKUP("bus_clk", snoc_msmbus_clk.c, "msm_sys_noc"),
+ CLK_LOOKUP("bus_a_clk", snoc_msmbus_a_clk.c, "msm_sys_noc"),
+ CLK_LOOKUP("bus_clk", pnoc_msmbus_clk.c, "msm_periph_noc"),
+ CLK_LOOKUP("bus_a_clk", pnoc_msmbus_a_clk.c, "msm_periph_noc"),
+ CLK_LOOKUP("mem_clk", bimc_msmbus_clk.c, "msm_bimc"),
+ CLK_LOOKUP("mem_a_clk", bimc_msmbus_a_clk.c, "msm_bimc"),
+ CLK_LOOKUP("mem_clk", bimc_acpu_a_clk.c, ""),
+
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etr"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-replicator"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etf"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-merg"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in1"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-kpss"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-mmss"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-stm"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm1"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm2"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm3"),
+
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etr"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tpiu"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-replicator"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etf"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-merg"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in0"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in1"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-kpss"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-mmss"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-stm"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm0"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm1"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm2"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm3"),
+
+ CLK_LOOKUP("core_clk_src", blsp1_qup1_spi_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_qup2_spi_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_qup3_spi_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_qup4_spi_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_qup5_spi_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_qup6_spi_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_uart1_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_uart2_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_uart3_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_uart4_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_uart5_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", blsp1_uart6_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", ce1_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", gp1_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", gp2_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", gp3_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", pdm2_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", sdcc1_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", sdcc2_apps_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", usb_hs_system_clk_src.c, ""),
+
+ CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup1_i2c_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup2_i2c_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup2_spi_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup3_i2c_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup3_spi_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup4_i2c_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup4_spi_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup5_i2c_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup5_spi_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup6_i2c_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup6_spi_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_uart1_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_uart2_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_uart3_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_uart4_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_uart5_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp1_uart6_apps_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_boot_rom_ahb_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_ce1_axi_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_ce1_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_copss_smmu_ahb_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_lpss_smmu_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_gp1_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_gp2_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_gp3_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_lpass_q6_axi_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_mss_q6_bimc_axi_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_pdm2_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_pdm_ahb_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_prng_ahb_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_sdcc1_ahb_clk.c, "msm_sdcc.1"),
+ CLK_LOOKUP("core_clk", gcc_sdcc1_apps_clk.c, "msm_sdcc.1"),
+ CLK_LOOKUP("iface_clk", gcc_sdcc2_ahb_clk.c, "msm_sdcc.2"),
+ CLK_LOOKUP("core_clk", gcc_sdcc2_apps_clk.c, "msm_sdcc.2"),
+ CLK_LOOKUP("core_clk", gcc_usb2a_phy_sleep_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c, "f9a55000.usb"),
+ CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, "f9a55000.usb"),
+
+ CLK_LOOKUP("core_clk_src", csi0_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", axi_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", dsi_pclk_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", gfx3d_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", vfe_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", csi1_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", csi0phytimer_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", csi1phytimer_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", dsi_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", dsi_byte_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", dsi_esc_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", mclk0_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", mclk1_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", mdp_vsync_clk_src.c, ""),
+
+ CLK_LOOKUP("core_clk", bimc_gfx_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi0_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi0phy_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi0phytimer_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi0pix_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi0rdi_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi1_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi1phy_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi1phytimer_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi1pix_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi1rdi_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", csi_vfe_clk.c, ""),
+ CLK_LOOKUP("core_clk", dsi_clk.c, ""),
+ CLK_LOOKUP("core_clk", dsi_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", dsi_byte_clk.c, ""),
+ CLK_LOOKUP("core_clk", dsi_esc_clk.c, ""),
+ CLK_LOOKUP("core_clk", dsi_pclk_clk.c, ""),
+ CLK_LOOKUP("core_clk", gmem_gfx3d_clk.c, ""),
+ CLK_LOOKUP("core_clk", mclk0_clk.c, ""),
+ CLK_LOOKUP("core_clk", mclk1_clk.c, ""),
+ CLK_LOOKUP("core_clk", mdp_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", mdp_axi_clk.c, ""),
+ CLK_LOOKUP("core_clk", mdp_dsi_clk.c, ""),
+ CLK_LOOKUP("core_clk", mdp_lcdc_clk.c, ""),
+ CLK_LOOKUP("core_clk", mdp_vsync_clk.c, ""),
+ CLK_LOOKUP("core_clk", mmss_misc_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", mmss_s0_axi_clk.c, ""),
+ CLK_LOOKUP("core_clk", mmss_mmssnoc_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", mmss_mmssnoc_bto_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", mmss_mmssnoc_axi_clk.c, ""),
+ CLK_LOOKUP("core_clk", vfe_clk.c, ""),
+ CLK_LOOKUP("core_clk", vfe_ahb_clk.c, ""),
+ CLK_LOOKUP("core_clk", vfe_axi_clk.c, ""),
+
+ CLK_LOOKUP("core_clk", oxili_gfx3d_clk.c, "fdc00000.qcom,kgsl-3d0"),
+ CLK_LOOKUP("iface_clk", oxili_ahb_clk.c, "fdc00000.qcom,kgsl-3d0"),
+ CLK_LOOKUP("mem_iface_clk", bimc_gfx_clk.c, "fdc00000.qcom,kgsl-3d0"),
+ CLK_LOOKUP("mem_clk", gmem_gfx3d_clk.c, "fdc00000.qcom,kgsl-3d0"),
+
+ CLK_LOOKUP("iface_clk", vfe_ahb_clk.c, "fd890000.qcom,iommu"),
+ CLK_LOOKUP("core_clk", vfe_axi_clk.c, "fd890000.qcom,iommu"),
+ CLK_LOOKUP("iface_clk", mdp_ahb_clk.c, "fd860000.qcom,iommu"),
+ CLK_LOOKUP("core_clk", mdp_axi_clk.c, "fd860000.qcom,iommu"),
+ CLK_LOOKUP("iface_clk", mdp_ahb_clk.c, "fd870000.qcom,iommu"),
+ CLK_LOOKUP("core_clk", mdp_axi_clk.c, "fd870000.qcom,iommu"),
+ CLK_LOOKUP("iface_clk", oxili_ahb_clk.c, "fd880000.qcom,iommu"),
+ CLK_LOOKUP("core_clk", bimc_gfx_clk.c, "fd880000.qcom,iommu"),
+ CLK_LOOKUP("iface_clk", gcc_lpss_smmu_ahb_clk.c, "fd000000.qcom,iommu"),
+ CLK_LOOKUP("core_clk", gcc_lpass_q6_axi_clk.c, "fd000000.qcom,iommu"),
+ CLK_LOOKUP("iface_clk", gcc_copss_smmu_ahb_clk.c,
+ "fd010000.qcom,iommu"),
+ CLK_LOOKUP("core_clk", pnoc_iommu_clk.c, "fd010000.qcom,iommu"),
+
+ CLK_LOOKUP("core_clk_src", lpaif_pri_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", lpaif_quad_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", lpaif_sec_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", lpaif_spkr_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", lpaif_ter_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", lpaif_pcm0_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", lpaif_pcm1_clk_src.c, ""),
+ CLK_LOOKUP("core_clk_src", lpaif_pcmoe_clk_src.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_ixfabric_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_wrapper_br_clk.c, ""),
+ CLK_LOOKUP("core_clk", q6ss_ahb_lfabif_clk.c, ""),
+ CLK_LOOKUP("core_clk", q6ss_ahbm_clk.c, ""),
+ CLK_LOOKUP("core_clk", q6ss_xo_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_pcm_data_oe_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_pri_ebit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_pri_ibit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_pri_osr_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_ibit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_quad_ebit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_quad_ibit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_quad_osr_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_sec_ebit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_sec_ibit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_sec_osr_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_codec_spkr_ebit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_codec_spkr_ibit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_codec_spkr_osr_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_ter_ebit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_ter_ibit_clk.c, ""),
+ CLK_LOOKUP("core_clk", audio_core_lpaif_ter_osr_clk.c, ""),
+
+ CLK_LOOKUP("core_clk", q6ss_xo_clk.c, "fe200000.qcom,lpass"),
+ CLK_LOOKUP("bus_clk", gcc_lpass_q6_axi_clk.c, "fe200000.qcom,lpass"),
+ CLK_LOOKUP("iface_clk", q6ss_ahb_lfabif_clk.c, "fe200000.qcom,lpass"),
+ CLK_LOOKUP("reg_clk", q6ss_ahbm_clk.c, "fe200000.qcom,lpass"),
+};
+
+static struct clk_lookup msm_clocks_8910_rumi[] = {
+ CLK_DUMMY("core_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+ CLK_DUMMY("iface_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+ CLK_DUMMY("iface_clk", HSUSB_IFACE_CLK, "f9a55000.usb", OFF),
+ CLK_DUMMY("core_clk", HSUSB_CORE_CLK, "f9a55000.usb", OFF),
+ CLK_DUMMY("iface_clk", NULL, "msm_sdcc.1", OFF),
+ CLK_DUMMY("core_clk", NULL, "msm_sdcc.1", OFF),
+ CLK_DUMMY("bus_clk", NULL, "msm_sdcc.1", OFF),
+ CLK_DUMMY("iface_clk", NULL, "msm_sdcc.2", OFF),
+ CLK_DUMMY("core_clk", NULL, "msm_sdcc.2", OFF),
+ CLK_DUMMY("bus_clk", NULL, "msm_sdcc.2", OFF),
+ CLK_DUMMY("dfab_clk", DFAB_CLK, "msm_sps", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fd890000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fd890000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fd860000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fd860000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fd870000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fd870000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fd880000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fd880000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fd000000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fd000000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fd010000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fd010000.qcom,iommu", OFF),
+};
+
+struct clock_init_data msm8910_rumi_clock_init_data __initdata = {
+ .table = msm_clocks_8910_rumi,
+ .size = ARRAY_SIZE(msm_clocks_8910_rumi),
+};
+
+static struct pll_config_regs gpll0_regs __initdata = {
+ .l_reg = (void __iomem *)GPLL0_L_VAL,
+ .m_reg = (void __iomem *)GPLL0_M_VAL,
+ .n_reg = (void __iomem *)GPLL0_N_VAL,
+ .config_reg = (void __iomem *)GPLL0_USER_CTL,
+ .mode_reg = (void __iomem *)GPLL0_MODE,
+ .base = &virt_bases[GCC_BASE],
+};
+
+/* GPLL0 at 600 MHz, main output enabled. */
+static struct pll_config gpll0_config __initdata = {
+ .l = 0x1f,
+ .m = 0x1,
+ .n = 0x4,
+ .vco_val = 0x0,
+ .vco_mask = BM(21, 20),
+ .pre_div_val = 0x0,
+ .pre_div_mask = BM(14, 12),
+ .post_div_val = 0x0,
+ .post_div_mask = BM(9, 8),
+ .mn_ena_val = BIT(24),
+ .mn_ena_mask = BIT(24),
+ .main_output_val = BIT(0),
+ .main_output_mask = BIT(0),
+};
+
+/* MMPLL0 at 800 MHz, main output enabled. */
+static struct pll_config mmpll0_config __initdata = {
+ .l = 0x29,
+ .m = 0x2,
+ .n = 0x3,
+ .vco_val = 0x0,
+ .vco_mask = BM(21, 20),
+ .pre_div_val = 0x0,
+ .pre_div_mask = BM(14, 12),
+ .post_div_val = 0x0,
+ .post_div_mask = BM(9, 8),
+ .mn_ena_val = BIT(24),
+ .mn_ena_mask = BIT(24),
+ .main_output_val = BIT(0),
+ .main_output_mask = BIT(0),
+};
+
+/* MMPLL1 at 1200 MHz, main output enabled. */
+static struct pll_config mmpll1_config __initdata = {
+ .l = 0x3E,
+ .m = 0x1,
+ .n = 0x2,
+ .vco_val = 0x0,
+ .vco_mask = BM(21, 20),
+ .pre_div_val = 0x0,
+ .pre_div_mask = BM(14, 12),
+ .post_div_val = 0x0,
+ .post_div_mask = BM(9, 8),
+ .mn_ena_val = BIT(24),
+ .mn_ena_mask = BIT(24),
+ .main_output_val = BIT(0),
+ .main_output_mask = BIT(0),
+};
+
+static struct pll_config_regs lpapll0_regs __initdata = {
+ .l_reg = (void __iomem *)LPAAUDIO_PLL_L_VAL,
+ .m_reg = (void __iomem *)LPAAUDIO_PLL_M_VAL,
+ .n_reg = (void __iomem *)LPAAUDIO_PLL_N_VAL,
+ .config_reg = (void __iomem *)LPAAUDIO_PLL_USER_CTL,
+ .mode_reg = (void __iomem *)LPAAUDIO_PLL_MODE,
+ .base = &virt_bases[LPASS_BASE],
+};
+
+/* LPAPLL0 at 491.52 MHz, main output enabled. */
+static struct pll_config lpapll0_config __initdata = {
+ .l = 0x33,
+ .m = 0x1,
+ .n = 0x5,
+ .vco_val = 0x0,
+ .vco_mask = BM(21, 20),
+ .pre_div_val = BVAL(14, 12, 0x1),
+ .pre_div_mask = BM(14, 12),
+ .post_div_val = 0x0,
+ .post_div_mask = BM(9, 8),
+ .mn_ena_val = BIT(24),
+ .mn_ena_mask = BIT(24),
+ .main_output_val = BIT(0),
+ .main_output_mask = BIT(0),
+};
+
+#define PLL_AUX_OUTPUT_BIT 1
+#define PLL_AUX2_OUTPUT_BIT 2
+
+#define PWR_ON_MASK BIT(31)
+#define EN_REST_WAIT_MASK (0xF << 20)
+#define EN_FEW_WAIT_MASK (0xF << 16)
+#define CLK_DIS_WAIT_MASK (0xF << 12)
+#define SW_OVERRIDE_MASK BIT(2)
+#define HW_CONTROL_MASK BIT(1)
+#define SW_COLLAPSE_MASK BIT(0)
+
+/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
+#define EN_REST_WAIT_VAL (0x2 << 20)
+#define EN_FEW_WAIT_VAL (0x2 << 16)
+#define CLK_DIS_WAIT_VAL (0x2 << 12)
+#define GDSC_TIMEOUT_US 50000
+
+static void __init reg_init(void)
+{
+ u32 regval, status;
+ int ret;
+
+ if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS))
+ & gpll0_clk_src.status_mask))
+ configure_sr_hpm_lp_pll(&gpll0_config, &gpll0_regs, 1);
+
+ configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
+ configure_sr_hpm_lp_pll(&mmpll1_config, &mmpll1_regs, 1);
+ configure_sr_hpm_lp_pll(&lpapll0_config, &lpapll0_regs, 1);
+
+ /* Enable GPLL0's aux outputs. */
+ regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL));
+ regval |= BIT(PLL_AUX_OUTPUT_BIT) | BIT(PLL_AUX2_OUTPUT_BIT);
+ writel_relaxed(regval, GCC_REG_BASE(GPLL0_USER_CTL));
+
+ /* Vote for GPLL0 to turn on. Needed by acpuclock. */
+ regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE));
+ regval |= BIT(0);
+ writel_relaxed(regval, GCC_REG_BASE(APCS_GPLL_ENA_VOTE));
+
+ /*
+ * TODO: Confirm that no clocks need to be voted on in this sleep vote
+ * register.
+ */
+ writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
+
+ /*
+ * TODO: The following sequence enables the LPASS audio core GDSC.
+ * Remove when this becomes unnecessary.
+ */
+
+ /*
+ * Disable HW trigger: collapse/restore occur based on registers writes.
+ * Disable SW override: Use hardware state-machine for sequencing.
+ */
+ regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+ regval &= ~(HW_CONTROL_MASK | SW_OVERRIDE_MASK);
+
+ /* Configure wait time between states. */
+ regval &= ~(EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK);
+ regval |= EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
+ writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+
+ regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+ regval &= ~BIT(0);
+ writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+
+ ret = readl_poll_timeout(LPASS_REG_BASE(AUDIO_CORE_GDSCR), status,
+ status & PWR_ON_MASK, 50, GDSC_TIMEOUT_US);
+ WARN(ret, "LPASS Audio Core GDSC did not power on.\n");
+}
+
+static void __init msm8910_clock_post_init(void)
+{
+ /*
+ * Hold an active set vote for CXO; this is because CXO is expected
+ * to remain on whenever CPUs aren't power collapsed.
+ */
+ clk_prepare_enable(&gcc_xo_a_clk_src.c);
+
+
+ /* Set rates for single-rate clocks. */
+ clk_set_rate(&usb_hs_system_clk_src.c,
+ usb_hs_system_clk_src.freq_tbl[0].freq_hz);
+ clk_set_rate(&pdm2_clk_src.c, pdm2_clk_src.freq_tbl[0].freq_hz);
+ clk_set_rate(&mclk0_clk_src.c, mclk0_clk_src.freq_tbl[0].freq_hz);
+ clk_set_rate(&mclk1_clk_src.c, mclk1_clk_src.freq_tbl[0].freq_hz);
+ clk_set_rate(&audio_core_slimbus_core_clk_src.c,
+ audio_core_slimbus_core_clk_src.freq_tbl[0].freq_hz);
+}
+
+#define GCC_CC_PHYS 0xFC400000
+#define GCC_CC_SIZE SZ_16K
+
+#define MMSS_CC_PHYS 0xFD8C0000
+#define MMSS_CC_SIZE SZ_256K
+
+#define LPASS_CC_PHYS 0xFE000000
+#define LPASS_CC_SIZE SZ_256K
+
+#define APCS_GCC_CC_PHYS 0xF9011000
+#define APCS_GCC_CC_SIZE SZ_4K
+
+static void __init msm8910_clock_pre_init(void)
+{
+ virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
+ if (!virt_bases[GCC_BASE])
+ panic("clock-8910: Unable to ioremap GCC memory!");
+
+ virt_bases[MMSS_BASE] = ioremap(MMSS_CC_PHYS, MMSS_CC_SIZE);
+ if (!virt_bases[MMSS_BASE])
+ panic("clock-8910: Unable to ioremap MMSS_CC memory!");
+
+ virt_bases[LPASS_BASE] = ioremap(LPASS_CC_PHYS, LPASS_CC_SIZE);
+ if (!virt_bases[LPASS_BASE])
+ panic("clock-8910: Unable to ioremap LPASS_CC memory!");
+
+ virt_bases[APCS_BASE] = ioremap(APCS_GCC_CC_PHYS, APCS_GCC_CC_SIZE);
+ if (!virt_bases[APCS_BASE])
+ panic("clock-8910: Unable to ioremap APCS_GCC_CC memory!");
+
+ clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
+
+ vdd_dig_reg = rpm_regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig_reg))
+ panic("clock-8910: Unable to get the vdd_dig regulator!");
+
+ /*
+ * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
+ * until late_init. This may not be necessary with clock handoff;
+ * Investigate this code on a real non-simulator target to determine
+ * its necessity.
+ */
+ vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ rpm_regulator_enable(vdd_dig_reg);
+
+ enable_rpm_scaling();
+
+ /* Enable a clock to allow access to MMSS clock registers */
+ clk_prepare_enable(&gcc_mmss_noc_cfg_ahb_clk.c),
+
+ reg_init();
+
+ /* TODO: Remove this once the bus driver is in place */
+ clk_set_rate(&ahb_clk_src.c, 40000000);
+ clk_set_rate(&axi_clk_src.c, 200000000);
+ clk_prepare_enable(&mmss_mmssnoc_ahb_clk.c);
+ clk_prepare_enable(&mmss_s0_axi_clk.c);
+
+ /* TODO: Temporarily enable a clock to allow access to LPASS core
+ * registers.
+ */
+ clk_prepare_enable(&audio_core_ixfabric_clk.c);
+}
+
+static int __init msm8910_clock_late_init(void)
+{
+ return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+}
+
+struct clock_init_data msm8910_clock_init_data __initdata = {
+ .table = msm_clocks_8910,
+ .size = ARRAY_SIZE(msm_clocks_8910),
+ .pre_init = msm8910_clock_pre_init,
+ .post_init = msm8910_clock_post_init,
+ .late_init = msm8910_clock_late_init,
+};
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 4a885c8..94fb856 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -3020,34 +3020,17 @@
static int hdmi_pll_clk_enable(struct clk *c)
{
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&local_clock_reg_lock, flags);
- ret = hdmi_pll_enable();
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
- return ret;
+ return hdmi_pll_enable();
}
static void hdmi_pll_clk_disable(struct clk *c)
{
- unsigned long flags;
-
- spin_lock_irqsave(&local_clock_reg_lock, flags);
hdmi_pll_disable();
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
static int hdmi_pll_clk_set_rate(struct clk *c, unsigned long rate)
{
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(&local_clock_reg_lock, flags);
- rc = hdmi_pll_set_rate(rate);
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
-
- return rc;
+ return hdmi_pll_set_rate(rate);
}
static struct clk_ops clk_ops_hdmi_pll = {
@@ -3084,21 +3067,39 @@
* Unlike other clocks, the HDMI rate is adjusted through PLL
* re-programming. It is also routed through an HID divider.
*/
-static void set_rate_hdmi(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
+static int rcg_clk_set_rate_hdmi(struct clk *c, unsigned long rate)
{
- clk_set_rate(nf->src_clk, nf->freq_hz);
+ struct clk_freq_tbl *nf;
+ struct rcg_clk *rcg = to_rcg_clk(c);
+ 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;
}
+static struct clk_ops clk_ops_rcg_hdmi;
+
static struct rcg_clk extpclk_clk_src = {
.cmd_rcgr_reg = EXTPCLK_CMD_RCGR,
- .set_rate = set_rate_hdmi,
.freq_tbl = ftbl_mdss_extpclk_clk,
.current_freq = &rcg_dummy_freq,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "extpclk_clk_src",
- .ops = &clk_ops_rcg,
+ .ops = &clk_ops_rcg_hdmi,
VDD_DIG_FMAX_MAP2(LOW, 148500000, NOMINAL, 297000000),
CLK_INIT(extpclk_clk_src.c),
},
@@ -5687,6 +5688,9 @@
clk_ops_pixel = clk_ops_rcg;
clk_ops_pixel.set_rate = set_rate_pixel;
+ clk_ops_rcg_hdmi = clk_ops_rcg;
+ clk_ops_rcg_hdmi.set_rate = rcg_clk_set_rate_hdmi;
+
mdss_clk_ctrl_init();
}
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index c30e566..79bc639 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -350,9 +350,11 @@
void hdmi_pll_disable(void)
{
+ clk_enable(mdss_dsi_ahb_clk);
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_dsi_ahb_clk);
hdmi_pll_on = 0;
} /* hdmi_pll_disable */
@@ -362,6 +364,7 @@
u32 status;
u32 max_reads, timeout_us;
+ clk_enable(mdss_dsi_ahb_clk);
/* Global Enable */
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
/* Power up power gen */
@@ -387,6 +390,7 @@
pr_err("%s: hdmi phy pll status=%x failed to Lock\n",
__func__, status);
hdmi_pll_disable();
+ clk_disable(mdss_dsi_ahb_clk);
return -EINVAL;
}
pr_debug("%s: hdmi phy pll is locked\n", __func__);
@@ -400,9 +404,11 @@
pr_err("%s: hdmi phy status=%x failed to Lock\n",
__func__, status);
hdmi_pll_disable();
+ clk_disable(mdss_dsi_ahb_clk);
return -EINVAL;
}
pr_debug("%s: hdmi phy is locked\n", __func__);
+ clk_disable(mdss_dsi_ahb_clk);
hdmi_pll_on = 1;
@@ -418,6 +424,7 @@
set_power_dwn = 1;
}
+ clk_enable(mdss_dsi_ahb_clk);
pr_debug("%s: rate=%ld\n", __func__, rate);
switch (rate) {
case 0:
@@ -746,6 +753,8 @@
/* Make sure writes complete before disabling iface clock */
mb();
+ clk_disable(mdss_dsi_ahb_clk);
+
if (set_power_dwn)
hdmi_pll_enable();
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 8a75d390..181cf4c 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -49,6 +49,8 @@
extern struct clock_init_data msm8930_pm8917_clock_init_data;
extern struct clock_init_data msm8974_clock_init_data;
extern struct clock_init_data msm8974_rumi_clock_init_data;
+extern struct clock_init_data msm8910_clock_init_data;
+extern struct clock_init_data msm8910_rumi_clock_init_data;
int msm_clock_init(struct clock_init_data *data);
int find_vdd_level(struct clk *clk, unsigned long rate);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 0bfaa71..fd5fc81 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2796,7 +2796,7 @@
.slack_weight_thresh_pct = 3,
.slack_time_min_us = 45000,
.slack_time_max_us = 45000,
- .ss_iobusy_conv = 100,
+ .ss_no_corr_below_freq = 0,
.ss_win_size_min_us = 1000000,
.ss_win_size_max_us = 1000000,
.ss_util_pct = 95,
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 0b10784..4780c57 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -3030,7 +3030,7 @@
.ss_win_size_min_us = 1000000,
.ss_win_size_max_us = 1000000,
.ss_util_pct = 95,
- .ss_iobusy_conv = 100,
+ .ss_no_corr_below_freq = 0,
},
.energy_coeffs = {
.active_coeff_a = 2492,
@@ -3067,7 +3067,7 @@
.ss_win_size_min_us = 1000000,
.ss_win_size_max_us = 1000000,
.ss_util_pct = 95,
- .ss_iobusy_conv = 100,
+ .ss_no_corr_below_freq = 0,
},
.energy_coeffs = {
.active_coeff_a = 2492,
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index a6cd4e5..d708055 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1791,13 +1791,6 @@
},
};
-struct msm_cpr_vp_data vp_data = {
- .min_volt = 1000000,
- .max_volt = 1350000,
- .default_volt = 1300000,
- .step_size = 12500,
-};
-
static uint32_t
msm_cpr_get_quot(uint32_t max_quot, uint32_t max_freq, uint32_t new_freq)
{
@@ -1839,7 +1832,7 @@
.max_freq = 1401600,
.max_quot = 0,
.disable_cpr = false,
- .vp_data = &vp_data,
+ .step_size = 12500,
.get_quot = msm_cpr_get_quot,
.clk_enable = msm_cpr_clk_enable,
};
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
index 597fdc0..7eefd54 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
@@ -48,7 +48,7 @@
uint32_t slack_time_min_us;
uint32_t slack_time_max_us;
uint32_t slack_weight_thresh_pct;
- uint32_t ss_iobusy_conv;
+ uint32_t ss_no_corr_below_freq;
uint32_t ss_win_size_min_us;
uint32_t ss_win_size_max_us;
uint32_t ss_util_pct;
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8910.h b/arch/arm/mach-msm/include/mach/msm_iomap-8910.h
index 08f21b6..64990da 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8910.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8910.h
@@ -22,7 +22,7 @@
*
*/
-#define MSM8910_MSM_SHARED_RAM_PHYS 0x0FA00000
+#define MSM8910_MSM_SHARED_RAM_PHYS 0x0D600000
#define MSM8910_APCS_GCC_PHYS 0xF9011000
#define MSM8910_APCS_GCC_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
index 17156b1..fe928b9 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
@@ -127,6 +127,7 @@
#define MSM_HDMI_SIZE SZ_4K
/* Needed to keep the unified iomap happy */
+#define MSM_APCS_GCC_BASE IOMEM(0xFA006000) /* 4K */
#define MSM_MPM2_PSHOLD_BASE MSM_TLMM_BASE
#ifdef CONFIG_DEBUG_MSM8660_UART
diff --git a/arch/arm/mach-msm/include/mach/rpc_server_handset.h b/arch/arm/mach-msm/include/mach/rpc_server_handset.h
index e1dc841..0856a4a 100644
--- a/arch/arm/mach-msm/include/mach/rpc_server_handset.h
+++ b/arch/arm/mach-msm/include/mach/rpc_server_handset.h
@@ -17,6 +17,7 @@
struct msm_handset_platform_data {
const char *hs_name;
uint32_t pwr_key_delay_ms; /* default 500ms */
+ bool ignore_end_key;
};
void report_headset_status(bool connected);
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 0499a7a..d41a1f0 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -60,6 +60,8 @@
of_machine_is_compatible("qcom,msm8910")
#define machine_is_msm8910_sim() \
of_machine_is_compatible("qcom,msm8910-sim")
+#define machine_is_msm8910_rumi() \
+ of_machine_is_compatible("qcom,msm8910-rumi")
#else
#define early_machine_is_msm8974() 0
#define machine_is_msm8974() 0
@@ -75,6 +77,7 @@
#define early_machine_is_msm8910() 0
#define machine_is_msm8910() 0
#define machine_is_msm8910_sim() 0
+#define machine_is_msm8910_rumi() 0
#endif
diff --git a/arch/arm/mach-msm/msm_cpr.c b/arch/arm/mach-msm/msm_cpr.c
index c7a8b98..dd6ffab 100644
--- a/arch/arm/mach-msm/msm_cpr.c
+++ b/arch/arm/mach-msm/msm_cpr.c
@@ -91,7 +91,7 @@
struct regulator *vreg_cx;
const struct msm_cpr_config *config;
struct notifier_block freq_transition;
- struct msm_cpr_vp_data *vp;
+ uint32_t step_size;
};
/* Need to maintain state data for suspend and resume APIs */
@@ -219,7 +219,7 @@
*
*/
level_uV = chip_data->turbo_Vmax -
- (chip_data->tgt_volt_offset * cpr->vp->step_size);
+ (chip_data->tgt_volt_offset * cpr->step_size);
msm_cpr_debug(MSM_CPR_DEBUG_CONFIG,
"tgt_volt_uV = %d\n", level_uV);
@@ -260,7 +260,7 @@
quot1 = (cpr_read_reg(cpr, RBCPR_DEBUG1) & QUOT_SLOW_M) >> 12;
/* Take second CPR measurement at a lower voltage to get QUOT2 */
- level_uV -= 4 * cpr->vp->step_size;
+ level_uV -= 4 * cpr->step_size;
msm_cpr_debug(MSM_CPR_DEBUG_CONFIG,
"tgt_volt_uV = %d\n", level_uV);
@@ -493,7 +493,7 @@
error_step += 1;
/* Calculte new PMIC voltage */
- new_volt = curr_volt + (error_step * cpr->vp->step_size);
+ new_volt = curr_volt + (error_step * cpr->step_size);
msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
"UP_INT: new_volt: %d, error_step=%d\n",
new_volt, error_step);
@@ -531,7 +531,7 @@
error_step = 2;
/* Calculte new PMIC voltage */
- new_volt = curr_volt - (error_step * cpr->vp->step_size);
+ new_volt = curr_volt - (error_step * cpr->step_size);
msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
"DOWN_INT: new_volt: %d, error_step=%d\n",
new_volt, error_step);
@@ -953,7 +953,7 @@
cpr->base = base;
- cpr->vp = pdata->vp_data;
+ cpr->step_size = pdata->step_size;
spin_lock_init(&cpr->cpr_lock);
diff --git a/arch/arm/mach-msm/msm_cpr.h b/arch/arm/mach-msm/msm_cpr.h
index 3d10478..d9c8e9b 100644
--- a/arch/arm/mach-msm/msm_cpr.h
+++ b/arch/arm/mach-msm/msm_cpr.h
@@ -122,20 +122,6 @@
};
/**
- * struct msm_vp_data - structure for VP configuration
- * @min_volt: minimum microvolt level for VP
- * @max_volt: maximum microvolt level for VP
- * @default_volt: default microvolt for VP
- * @step_size: step size of voltage in microvolt
- */
-struct msm_cpr_vp_data {
- int min_volt;
- int max_volt;
- int default_volt;
- int step_size;
-};
-
-/**
* struct msm_cpr_osc - Data for CPR ring oscillator
* @gcnt: gate count value for the oscillator
* @quot: target value for ring oscillator
@@ -189,7 +175,7 @@
uint32_t max_freq;
uint32_t max_quot;
bool disable_cpr;
- struct msm_cpr_vp_data *vp_data;
+ uint32_t step_size;
uint32_t (*get_quot)(uint32_t max_quot, uint32_t max_freq,
uint32_t new_freq);
void (*clk_enable)(void);
diff --git a/arch/arm/mach-msm/msm_cpu_pwrctl.c b/arch/arm/mach-msm/msm_cpu_pwrctl.c
new file mode 100644
index 0000000..6e339dd
--- /dev/null
+++ b/arch/arm/mach-msm/msm_cpu_pwrctl.c
@@ -0,0 +1,93 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/compiler.h>
+#include <linux/notifier.h>
+#include <linux/percpu.h>
+#include <linux/workqueue.h>
+
+#define MSM_CPU_SECONDARY_CORE_OFFSET 0x10000
+
+static const phys_addr_t primary_cpu_pwrctl_phys = 0x2088004;
+static DEFINE_PER_CPU(int, pll_clamp_set);
+static void msm_cpu_pwrctl_work_cb(struct work_struct *work);
+static __cpuinitdata DECLARE_WORK(msm_cpu_pwrctl_work, msm_cpu_pwrctl_work_cb);
+static int nr_cpus_done;
+static int __cpuinit msm_cpu_pwrctl_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu);
+static struct notifier_block __cpuinitdata msm_cpu_pwrctl_cpu_notifier = {
+ .notifier_call = msm_cpu_pwrctl_cpu_callback,
+};
+
+static void __cpuinit msm_cpu_pwrctl_work_cb(struct work_struct *work)
+{
+ unregister_hotcpu_notifier(&msm_cpu_pwrctl_cpu_notifier);
+}
+
+static int __cpuinit msm_cpu_pwrctl_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ int cpu = (int) hcpu;
+ int *pll_clamp;
+ void *pwrctl_ptr;
+ unsigned int value;
+
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_ONLINE:
+ pll_clamp = &per_cpu(pll_clamp_set, cpu);
+ if (likely(*pll_clamp))
+ goto done;
+
+ pwrctl_ptr = ioremap_nocache(primary_cpu_pwrctl_phys +
+ (cpu * MSM_CPU_SECONDARY_CORE_OFFSET), SZ_4K);
+ if (unlikely(!pwrctl_ptr))
+ goto done;
+
+ value = readl_relaxed(pwrctl_ptr);
+ value |= 0x100;
+ writel_relaxed(value, pwrctl_ptr);
+ *pll_clamp = 1;
+ iounmap(pwrctl_ptr);
+
+ if (++nr_cpus_done == cpumask_weight(cpu_possible_mask))
+ schedule_work(&msm_cpu_pwrctl_work);
+done:
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+
+}
+
+static int __init msm_cpu_pwrctl_init(void)
+{
+ int cpu = smp_processor_id();
+
+ /* We won't get cpu online notification for this CPU,
+ * so take this opportunity to process this CPU.
+ */
+ msm_cpu_pwrctl_cpu_callback(&msm_cpu_pwrctl_cpu_notifier,
+ CPU_ONLINE, (void *) cpu);
+
+ register_hotcpu_notifier(&msm_cpu_pwrctl_cpu_notifier);
+ return 0;
+}
+
+early_initcall(msm_cpu_pwrctl_init);
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c
index 3b9656e..9e0be63 100644
--- a/arch/arm/mach-msm/msm_dcvs.c
+++ b/arch/arm/mach-msm/msm_dcvs.c
@@ -49,7 +49,7 @@
struct kobj_attribute slack_time_min_us;
struct kobj_attribute slack_time_max_us;
struct kobj_attribute slack_weight_thresh_pct;
- struct kobj_attribute ss_iobusy_conv;
+ struct kobj_attribute ss_no_corr_below_freq;
struct kobj_attribute ss_win_size_min_us;
struct kobj_attribute ss_win_size_max_us;
struct kobj_attribute ss_util_pct;
@@ -151,6 +151,7 @@
static unsigned num_cpu_freqs;
static struct msm_dcvs_platform_data *dcvs_pdata;
+static DEFINE_MUTEX(param_update_mutex);
static DEFINE_MUTEX(gpu_floor_mutex);
static void force_stop_slack_timer(struct dcvs_core *core)
@@ -309,6 +310,20 @@
mutex_unlock(&gpu_floor_mutex);
}
+static void check_power_collapse_modes(struct dcvs_core *core)
+{
+ struct msm_dcvs_algo_param *params;
+
+ params = &core_list[CPU_OFFSET + num_online_cpus() - 1].algo_param;
+
+ if (core->actual_freq >= params->disable_pc_threshold)
+ core->idle_enable(core->type_core_num,
+ MSM_DCVS_DISABLE_HIGH_LATENCY_MODES);
+ else
+ core->idle_enable(core->type_core_num,
+ MSM_DCVS_ENABLE_HIGH_LATENCY_MODES);
+}
+
static int __msm_dcvs_change_freq(struct dcvs_core *core)
{
int ret = 0;
@@ -355,16 +370,11 @@
core->freq_change_us = (uint32_t)ktime_to_us(
ktime_sub(ktime_get(), time_start));
- /**
- * Disable low power modes if the actual frequency is >
- * disable_pc_threshold.
- */
- if (core->actual_freq > core->algo_param.disable_pc_threshold) {
- core->idle_enable(core->type_core_num,
- MSM_DCVS_DISABLE_HIGH_LATENCY_MODES);
- } else if (core->actual_freq <= core->algo_param.disable_pc_threshold) {
- core->idle_enable(core->type_core_num,
- MSM_DCVS_ENABLE_HIGH_LATENCY_MODES);
+ if (core->type == MSM_DCVS_CORE_TYPE_CPU &&
+ core->type_core_num == 0) {
+ mutex_lock(¶m_update_mutex);
+ check_power_collapse_modes(core);
+ mutex_unlock(¶m_update_mutex);
}
/**
@@ -556,7 +566,6 @@
int msm_dcvs_update_algo_params(void)
{
static struct msm_dcvs_algo_param curr_params;
- static DEFINE_MUTEX(param_update_mutex);
struct msm_dcvs_algo_param *new_params;
int cpu, ret = 0;
@@ -566,6 +575,7 @@
if (memcmp(&curr_params, new_params,
sizeof(struct msm_dcvs_algo_param))) {
for_each_possible_cpu(cpu) {
+ struct dcvs_core *core = &core_list[CPU_OFFSET + cpu];
ret = msm_dcvs_scm_set_algo_params(CPU_OFFSET + cpu,
new_params);
if (ret) {
@@ -574,6 +584,8 @@
mutex_unlock(¶m_update_mutex);
return ret;
}
+ if (cpu == 0)
+ check_power_collapse_modes(core);
}
memcpy(&curr_params, new_params,
sizeof(struct msm_dcvs_algo_param));
@@ -706,7 +718,7 @@
DCVS_ALGO_PARAM(slack_time_min_us)
DCVS_ALGO_PARAM(slack_time_max_us)
DCVS_ALGO_PARAM(slack_weight_thresh_pct)
-DCVS_ALGO_PARAM(ss_iobusy_conv)
+DCVS_ALGO_PARAM(ss_no_corr_below_freq)
DCVS_ALGO_PARAM(ss_win_size_min_us)
DCVS_ALGO_PARAM(ss_win_size_max_us)
DCVS_ALGO_PARAM(ss_util_pct)
@@ -892,7 +904,7 @@
DCVS_RW_ATTRIB(8, slack_weight_thresh_pct);
DCVS_RW_ATTRIB(9, slack_time_min_us);
DCVS_RW_ATTRIB(10, slack_time_max_us);
- DCVS_RW_ATTRIB(11, ss_iobusy_conv);
+ DCVS_RW_ATTRIB(11, ss_no_corr_below_freq);
DCVS_RW_ATTRIB(12, ss_win_size_min_us);
DCVS_RW_ATTRIB(13, ss_win_size_max_us);
DCVS_RW_ATTRIB(14, ss_util_pct);
diff --git a/arch/arm/mach-msm/msm_mpdecision.c b/arch/arm/mach-msm/msm_mpdecision.c
index 910804b..746bbe8 100644
--- a/arch/arm/mach-msm/msm_mpdecision.c
+++ b/arch/arm/mach-msm/msm_mpdecision.c
@@ -41,12 +41,14 @@
#include <trace/events/mpdcvs_trace.h>
#define DEFAULT_RQ_AVG_POLL_MS (1)
+#define DEFAULT_RQ_AVG_DIVIDE (25)
struct mpd_attrib {
struct kobj_attribute enabled;
struct kobj_attribute rq_avg_poll_ms;
- struct kobj_attribute iowait_threshold_pct;
+ struct kobj_attribute iowait_threshold_pct;
+ struct kobj_attribute rq_avg_divide;
struct kobj_attribute em_win_size_min_us;
struct kobj_attribute em_win_size_max_us;
struct kobj_attribute em_max_util_pct;
@@ -75,6 +77,7 @@
atomic_t algo_cpu_mask;
uint32_t rq_avg_poll_ms;
uint32_t iowait_threshold_pct;
+ uint32_t rq_avg_divide;
ktime_t next_update;
uint32_t slack_us;
struct msm_mpd_algo_param mp_param;
@@ -125,20 +128,19 @@
static int num_present_hundreds;
static ktime_t last_down_time;
-#define RQ_AVG_INSIGNIFICANT_BITS 3
static bool ok_to_update_tz(int nr, int last_nr)
{
/*
* Exclude unnecessary TZ reports if run queue haven't changed much from
- * the last reported value. The left shift by INSIGNIFICANT_BITS is to
+ * the last reported value. The divison by rq_avg_divide is to
* filter out small changes in the run queue average which won't cause
* a online cpu mask change. Also if the cpu online count does not match
* the count requested by TZ and we are not in the process of bringing
* cpus online as indicated by a HPUPDATE_IN_PROGRESS in msm_mpd.hpdata
*/
return
- (((nr >> RQ_AVG_INSIGNIFICANT_BITS)
- != (last_nr >> RQ_AVG_INSIGNIFICANT_BITS))
+ (((nr / msm_mpd.rq_avg_divide)
+ != (last_nr / msm_mpd.rq_avg_divide))
|| ((hweight32(atomic_read(&msm_mpd.algo_cpu_mask))
!= num_online_cpus())
&& (msm_mpd.hpupdate != HPUPDATE_IN_PROGRESS)));
@@ -509,6 +511,20 @@
return 0;
}
+static int msm_mpd_set_rq_avg_divide(uint32_t val)
+{
+ /*
+ * No need to do anything. New value will be used next time
+ * the decision is made as to whether to update tz.
+ */
+
+ if (val == 0)
+ return -EINVAL;
+
+ msm_mpd.rq_avg_divide = val;
+ return 0;
+}
+
#define MPD_ALGO_PARAM(_name, _param) \
static ssize_t msm_mpd_attr_##_name##_show(struct kobject *kobj, \
struct kobj_attribute *attr, char *buf) \
@@ -580,6 +596,7 @@
MPD_PARAM(enabled, msm_mpd.enabled);
MPD_PARAM(rq_avg_poll_ms, msm_mpd.rq_avg_poll_ms);
MPD_PARAM(iowait_threshold_pct, msm_mpd.iowait_threshold_pct);
+MPD_PARAM(rq_avg_divide, msm_mpd.rq_avg_divide);
MPD_ALGO_PARAM(em_win_size_min_us, msm_mpd.mp_param.em_win_size_min_us);
MPD_ALGO_PARAM(em_win_size_max_us, msm_mpd.mp_param.em_win_size_max_us);
MPD_ALGO_PARAM(em_max_util_pct, msm_mpd.mp_param.em_max_util_pct);
@@ -602,7 +619,7 @@
{
struct kobject *module_kobj = NULL;
int ret = 0;
- const int attr_count = 19;
+ const int attr_count = 20;
struct msm_mpd_algo_param *param = NULL;
param = pdev->dev.platform_data;
@@ -624,28 +641,30 @@
MPD_RW_ATTRIB(0, enabled);
MPD_RW_ATTRIB(1, rq_avg_poll_ms);
MPD_RW_ATTRIB(2, iowait_threshold_pct);
- MPD_RW_ATTRIB(3, em_win_size_min_us);
- MPD_RW_ATTRIB(4, em_win_size_max_us);
- MPD_RW_ATTRIB(5, em_max_util_pct);
- MPD_RW_ATTRIB(6, mp_em_rounding_point_min);
- MPD_RW_ATTRIB(7, mp_em_rounding_point_max);
- MPD_RW_ATTRIB(8, online_util_pct_min);
- MPD_RW_ATTRIB(9, online_util_pct_max);
- MPD_RW_ATTRIB(10, slack_time_min_us);
- MPD_RW_ATTRIB(11, slack_time_max_us);
- MPD_RW_ATTRIB(12, hp_up_max_ms);
- MPD_RW_ATTRIB(13, hp_up_ms);
- MPD_RW_ATTRIB(14, hp_up_count);
- MPD_RW_ATTRIB(15, hp_dw_max_ms);
- MPD_RW_ATTRIB(16, hp_dw_ms);
- MPD_RW_ATTRIB(17, hp_dw_count);
+ MPD_RW_ATTRIB(3, rq_avg_divide);
+ MPD_RW_ATTRIB(4, em_win_size_min_us);
+ MPD_RW_ATTRIB(5, em_win_size_max_us);
+ MPD_RW_ATTRIB(6, em_max_util_pct);
+ MPD_RW_ATTRIB(7, mp_em_rounding_point_min);
+ MPD_RW_ATTRIB(8, mp_em_rounding_point_max);
+ MPD_RW_ATTRIB(9, online_util_pct_min);
+ MPD_RW_ATTRIB(10, online_util_pct_max);
+ MPD_RW_ATTRIB(11, slack_time_min_us);
+ MPD_RW_ATTRIB(12, slack_time_max_us);
+ MPD_RW_ATTRIB(13, hp_up_max_ms);
+ MPD_RW_ATTRIB(14, hp_up_ms);
+ MPD_RW_ATTRIB(15, hp_up_count);
+ MPD_RW_ATTRIB(16, hp_dw_max_ms);
+ MPD_RW_ATTRIB(17, hp_dw_ms);
+ MPD_RW_ATTRIB(18, hp_dw_count);
- msm_mpd.attrib.attrib_group.attrs[18] = NULL;
+ msm_mpd.attrib.attrib_group.attrs[19] = NULL;
ret = sysfs_create_group(module_kobj, &msm_mpd.attrib.attrib_group);
if (ret)
pr_err("Unable to create sysfs objects :%d\n", ret);
msm_mpd.rq_avg_poll_ms = DEFAULT_RQ_AVG_POLL_MS;
+ msm_mpd.rq_avg_divide = DEFAULT_RQ_AVG_DIVIDE;
memcpy(&msm_mpd.mp_param, param, sizeof(struct msm_mpd_algo_param));
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 94632da..5e03aa8 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -195,15 +195,10 @@
void *ss_handle)
{
int ret;
- switch (code) {
- case SUBSYS_BEFORE_SHUTDOWN:
- pr_debug("%s: M-Notify: Shutdown started\n", __func__);
- ret = sysmon_send_event(SYSMON_SS_LPASS, "modem",
- SUBSYS_BEFORE_SHUTDOWN);
- if (ret < 0)
- pr_err("%s: sysmon_send_event error %d", __func__, ret);
- break;
- }
+ pr_debug("%s: M-Notify: event %lu\n", __func__, code);
+ ret = sysmon_send_event(SYSMON_SS_LPASS, "modem", code);
+ if (ret < 0)
+ pr_err("%s: sysmon_send_event error %d", __func__, ret);
return NOTIFY_DONE;
}
@@ -295,15 +290,8 @@
{
struct lpass_data *drv = subsys_to_lpass(subsys);
int ret = 0;
-
- if (get_restart_level() == RESET_SUBSYS_INDEPENDENT) {
- pr_debug("%s: Wait for ADSP power up!", __func__);
- msleep(10000);
- }
-
ret = pil_boot(&drv->q6->desc);
enable_irq(drv->wdog_irq);
-
return ret;
}
diff --git a/arch/arm/mach-msm/rpc_server_handset.c b/arch/arm/mach-msm/rpc_server_handset.c
index 6d173fb..3a458c8 100644
--- a/arch/arm/mach-msm/rpc_server_handset.c
+++ b/arch/arm/mach-msm/rpc_server_handset.c
@@ -280,6 +280,13 @@
switch (key) {
case KEY_POWER:
case KEY_END:
+ if (hs->hs_pdata->ignore_end_key)
+ input_report_key(hs->ipdev, KEY_POWER,
+ (key_code != HS_REL_K));
+ else
+ input_report_key(hs->ipdev, key,
+ (key_code != HS_REL_K));
+ break;
case KEY_MEDIA:
case KEY_VOLUMEUP:
case KEY_VOLUMEDOWN:
diff --git a/arch/arm/mach-msm/spm.h b/arch/arm/mach-msm/spm.h
index a353ce0..01f6787 100644
--- a/arch/arm/mach-msm/spm.h
+++ b/arch/arm/mach-msm/spm.h
@@ -130,7 +130,14 @@
int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm);
int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel);
unsigned int msm_spm_get_vdd(unsigned int cpu);
+#if defined(CONFIG_MSM_SPM_V2)
int msm_spm_turn_on_cpu_rail(unsigned int cpu);
+#else
+static inline int msm_spm_turn_on_cpu_rail(unsigned int cpu)
+{
+ return -ENOSYS;
+}
+#endif
/* Internal low power management specific functions */
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 8f3c107..8a75cd9 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -1160,7 +1160,6 @@
dbs_timer_exit(this_dbs_info);
mutex_lock(&dbs_mutex);
- mutex_destroy(&this_dbs_info->timer_mutex);
dbs_enable--;
/* If device is being removed, policy is no longer
* valid. */
@@ -1239,7 +1238,14 @@
static void __exit cpufreq_gov_dbs_exit(void)
{
+ unsigned int i;
+
cpufreq_unregister_governor(&cpufreq_gov_ondemand);
+ for_each_possible_cpu(i) {
+ struct cpu_dbs_info_s *this_dbs_info =
+ &per_cpu(od_cpu_dbs_info, i);
+ mutex_destroy(&this_dbs_info->timer_mutex);
+ }
destroy_workqueue(input_wq);
}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 55597fc..24be1b0 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -884,8 +884,8 @@
if (adreno_of_read_property(node, "qcom,algo-ss-util-pct",
&info->algo_param.ss_util_pct))
goto err;
- if (adreno_of_read_property(node, "qcom,algo-ss-iobusy-conv",
- &info->algo_param.ss_iobusy_conv))
+ if (adreno_of_read_property(node, "qcom,algo-ss-no-corr-below-freq",
+ &info->algo_param.ss_no_corr_below_freq))
goto err;
if (adreno_of_read_property(node, "qcom,energy-active-coeff-a",
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index ee6c8b4..818bd63 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -261,7 +261,7 @@
}
static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
- struct device *dev, unsigned long addr, int flags)
+ struct device *dev, unsigned long addr, int flags, void *token)
{
int ret = 0;
struct kgsl_mmu *mmu;
@@ -575,7 +575,7 @@
return NULL;
} else {
iommu_set_fault_handler(iommu_pt->domain,
- kgsl_iommu_fault_handler);
+ kgsl_iommu_fault_handler, NULL);
}
return iommu_pt;
@@ -1521,11 +1521,16 @@
pt_base &= (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask <<
iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift);
+ /* For v1 SMMU GPU needs to be idle for tlb invalidate as well */
+ if (msm_soc_version_supports_iommu_v1())
+ kgsl_idle(mmu->device);
+
/* Acquire GPU-CPU sync Lock here */
msm_iommu_lock();
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
- kgsl_idle(mmu->device);
+ if (!msm_soc_version_supports_iommu_v1())
+ kgsl_idle(mmu->device);
for (i = 0; i < iommu->unit_count; i++) {
/* get the lsb value which should not change when
* changing ttbr0 */
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index a5bee8e..32c00cd 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3193,26 +3193,6 @@
return 0;
}
-static int amd_iommu_device_group(struct device *dev, unsigned int *groupid)
-{
- struct iommu_dev_data *dev_data = dev->archdata.iommu;
- struct pci_dev *pdev = to_pci_dev(dev);
- u16 devid;
-
- if (!dev_data)
- return -ENODEV;
-
- if (pdev->is_virtfn || !iommu_group_mf)
- devid = dev_data->devid;
- else
- devid = calc_devid(pdev->bus->number,
- PCI_DEVFN(PCI_SLOT(pdev->devfn), 0));
-
- *groupid = amd_iommu_alias_table[devid];
-
- return 0;
-}
-
static struct iommu_ops amd_iommu_ops = {
.domain_init = amd_iommu_domain_init,
.domain_destroy = amd_iommu_domain_destroy,
@@ -3222,7 +3202,6 @@
.unmap = amd_iommu_unmap,
.iova_to_phys = amd_iommu_iova_to_phys,
.domain_has_cap = amd_iommu_domain_has_cap,
- .device_group = amd_iommu_device_group,
.pgsize_bitmap = AMD_IOMMU_PGSIZES,
};
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index f93d5ac..d4a0ff7 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4087,54 +4087,6 @@
return 0;
}
-/*
- * Group numbers are arbitrary. Device with the same group number
- * indicate the iommu cannot differentiate between them. To avoid
- * tracking used groups we just use the seg|bus|devfn of the lowest
- * level we're able to differentiate devices
- */
-static int intel_iommu_device_group(struct device *dev, unsigned int *groupid)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct pci_dev *bridge;
- union {
- struct {
- u8 devfn;
- u8 bus;
- u16 segment;
- } pci;
- u32 group;
- } id;
-
- if (iommu_no_mapping(dev))
- return -ENODEV;
-
- id.pci.segment = pci_domain_nr(pdev->bus);
- id.pci.bus = pdev->bus->number;
- id.pci.devfn = pdev->devfn;
-
- if (!device_to_iommu(id.pci.segment, id.pci.bus, id.pci.devfn))
- return -ENODEV;
-
- bridge = pci_find_upstream_pcie_bridge(pdev);
- if (bridge) {
- if (pci_is_pcie(bridge)) {
- id.pci.bus = bridge->subordinate->number;
- id.pci.devfn = 0;
- } else {
- id.pci.bus = bridge->bus->number;
- id.pci.devfn = bridge->devfn;
- }
- }
-
- if (!pdev->is_virtfn && iommu_group_mf)
- id.pci.devfn = PCI_DEVFN(PCI_SLOT(id.pci.devfn), 0);
-
- *groupid = id.group;
-
- return 0;
-}
-
static struct iommu_ops intel_iommu_ops = {
.domain_init = intel_iommu_domain_init,
.domain_destroy = intel_iommu_domain_destroy,
@@ -4144,7 +4096,6 @@
.unmap = intel_iommu_unmap,
.iova_to_phys = intel_iommu_iova_to_phys,
.domain_has_cap = intel_iommu_domain_has_cap,
- .device_group = intel_iommu_device_group,
.pgsize_bitmap = INTEL_IOMMU_PGSIZES,
};
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index ef69d91..d07fb96 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -27,60 +27,535 @@
#include <linux/errno.h>
#include <linux/iommu.h>
#include <linux/scatterlist.h>
+#include <linux/idr.h>
+#include <linux/notifier.h>
+#include <linux/err.h>
-static ssize_t show_iommu_group(struct device *dev,
- struct device_attribute *attr, char *buf)
+static struct kset *iommu_group_kset;
+static struct ida iommu_group_ida;
+static struct mutex iommu_group_mutex;
+
+struct iommu_group {
+ struct kobject kobj;
+ struct kobject *devices_kobj;
+ struct list_head devices;
+ struct mutex mutex;
+ struct blocking_notifier_head notifier;
+ void *iommu_data;
+ void (*iommu_data_release)(void *iommu_data);
+ char *name;
+ int id;
+};
+
+struct iommu_device {
+ struct list_head list;
+ struct device *dev;
+ char *name;
+};
+
+struct iommu_group_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct iommu_group *group, char *buf);
+ ssize_t (*store)(struct iommu_group *group,
+ const char *buf, size_t count);
+};
+
+#define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \
+struct iommu_group_attribute iommu_group_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+#define to_iommu_group_attr(_attr) \
+ container_of(_attr, struct iommu_group_attribute, attr)
+#define to_iommu_group(_kobj) \
+ container_of(_kobj, struct iommu_group, kobj)
+
+static ssize_t iommu_group_attr_show(struct kobject *kobj,
+ struct attribute *__attr, char *buf)
{
- unsigned int groupid;
+ struct iommu_group_attribute *attr = to_iommu_group_attr(__attr);
+ struct iommu_group *group = to_iommu_group(kobj);
+ ssize_t ret = -EIO;
- if (iommu_device_group(dev, &groupid))
- return 0;
-
- return sprintf(buf, "%u", groupid);
+ if (attr->show)
+ ret = attr->show(group, buf);
+ return ret;
}
-static DEVICE_ATTR(iommu_group, S_IRUGO, show_iommu_group, NULL);
+
+static ssize_t iommu_group_attr_store(struct kobject *kobj,
+ struct attribute *__attr,
+ const char *buf, size_t count)
+{
+ struct iommu_group_attribute *attr = to_iommu_group_attr(__attr);
+ struct iommu_group *group = to_iommu_group(kobj);
+ ssize_t ret = -EIO;
+
+ if (attr->store)
+ ret = attr->store(group, buf, count);
+ return ret;
+}
+
+static const struct sysfs_ops iommu_group_sysfs_ops = {
+ .show = iommu_group_attr_show,
+ .store = iommu_group_attr_store,
+};
+
+static int iommu_group_create_file(struct iommu_group *group,
+ struct iommu_group_attribute *attr)
+{
+ return sysfs_create_file(&group->kobj, &attr->attr);
+}
+
+static void iommu_group_remove_file(struct iommu_group *group,
+ struct iommu_group_attribute *attr)
+{
+ sysfs_remove_file(&group->kobj, &attr->attr);
+}
+
+static ssize_t iommu_group_show_name(struct iommu_group *group, char *buf)
+{
+ return sprintf(buf, "%s\n", group->name);
+}
+
+static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL);
+
+static void iommu_group_release(struct kobject *kobj)
+{
+ struct iommu_group *group = to_iommu_group(kobj);
+
+ if (group->iommu_data_release)
+ group->iommu_data_release(group->iommu_data);
+
+ mutex_lock(&iommu_group_mutex);
+ ida_remove(&iommu_group_ida, group->id);
+ mutex_unlock(&iommu_group_mutex);
+
+ kfree(group->name);
+ kfree(group);
+}
+
+static struct kobj_type iommu_group_ktype = {
+ .sysfs_ops = &iommu_group_sysfs_ops,
+ .release = iommu_group_release,
+};
+
+/**
+ * iommu_group_alloc - Allocate a new group
+ * @name: Optional name to associate with group, visible in sysfs
+ *
+ * This function is called by an iommu driver to allocate a new iommu
+ * group. The iommu group represents the minimum granularity of the iommu.
+ * Upon successful return, the caller holds a reference to the supplied
+ * group in order to hold the group until devices are added. Use
+ * iommu_group_put() to release this extra reference count, allowing the
+ * group to be automatically reclaimed once it has no devices or external
+ * references.
+ */
+struct iommu_group *iommu_group_alloc(void)
+{
+ struct iommu_group *group;
+ int ret;
+
+ group = kzalloc(sizeof(*group), GFP_KERNEL);
+ if (!group)
+ return ERR_PTR(-ENOMEM);
+
+ group->kobj.kset = iommu_group_kset;
+ mutex_init(&group->mutex);
+ INIT_LIST_HEAD(&group->devices);
+ BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier);
+
+ mutex_lock(&iommu_group_mutex);
+
+again:
+ if (unlikely(0 == ida_pre_get(&iommu_group_ida, GFP_KERNEL))) {
+ kfree(group);
+ mutex_unlock(&iommu_group_mutex);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ if (-EAGAIN == ida_get_new(&iommu_group_ida, &group->id))
+ goto again;
+
+ mutex_unlock(&iommu_group_mutex);
+
+ ret = kobject_init_and_add(&group->kobj, &iommu_group_ktype,
+ NULL, "%d", group->id);
+ if (ret) {
+ mutex_lock(&iommu_group_mutex);
+ ida_remove(&iommu_group_ida, group->id);
+ mutex_unlock(&iommu_group_mutex);
+ kfree(group);
+ return ERR_PTR(ret);
+ }
+
+ group->devices_kobj = kobject_create_and_add("devices", &group->kobj);
+ if (!group->devices_kobj) {
+ kobject_put(&group->kobj); /* triggers .release & free */
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /*
+ * The devices_kobj holds a reference on the group kobject, so
+ * as long as that exists so will the group. We can therefore
+ * use the devices_kobj for reference counting.
+ */
+ kobject_put(&group->kobj);
+
+ return group;
+}
+EXPORT_SYMBOL_GPL(iommu_group_alloc);
+
+/**
+ * iommu_group_get_iommudata - retrieve iommu_data registered for a group
+ * @group: the group
+ *
+ * iommu drivers can store data in the group for use when doing iommu
+ * operations. This function provides a way to retrieve it. Caller
+ * should hold a group reference.
+ */
+void *iommu_group_get_iommudata(struct iommu_group *group)
+{
+ return group->iommu_data;
+}
+EXPORT_SYMBOL_GPL(iommu_group_get_iommudata);
+
+/**
+ * iommu_group_set_iommudata - set iommu_data for a group
+ * @group: the group
+ * @iommu_data: new data
+ * @release: release function for iommu_data
+ *
+ * iommu drivers can store data in the group for use when doing iommu
+ * operations. This function provides a way to set the data after
+ * the group has been allocated. Caller should hold a group reference.
+ */
+void iommu_group_set_iommudata(struct iommu_group *group, void *iommu_data,
+ void (*release)(void *iommu_data))
+{
+ group->iommu_data = iommu_data;
+ group->iommu_data_release = release;
+}
+EXPORT_SYMBOL_GPL(iommu_group_set_iommudata);
+
+/**
+ * iommu_group_set_name - set name for a group
+ * @group: the group
+ * @name: name
+ *
+ * Allow iommu driver to set a name for a group. When set it will
+ * appear in a name attribute file under the group in sysfs.
+ */
+int iommu_group_set_name(struct iommu_group *group, const char *name)
+{
+ int ret;
+
+ if (group->name) {
+ iommu_group_remove_file(group, &iommu_group_attr_name);
+ kfree(group->name);
+ group->name = NULL;
+ if (!name)
+ return 0;
+ }
+
+ group->name = kstrdup(name, GFP_KERNEL);
+ if (!group->name)
+ return -ENOMEM;
+
+ ret = iommu_group_create_file(group, &iommu_group_attr_name);
+ if (ret) {
+ kfree(group->name);
+ group->name = NULL;
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iommu_group_set_name);
+
+/**
+ * iommu_group_add_device - add a device to an iommu group
+ * @group: the group into which to add the device (reference should be held)
+ * @dev: the device
+ *
+ * This function is called by an iommu driver to add a device into a
+ * group. Adding a device increments the group reference count.
+ */
+int iommu_group_add_device(struct iommu_group *group, struct device *dev)
+{
+ int ret, i = 0;
+ struct iommu_device *device;
+
+ device = kzalloc(sizeof(*device), GFP_KERNEL);
+ if (!device)
+ return -ENOMEM;
+
+ device->dev = dev;
+
+ ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group");
+ if (ret) {
+ kfree(device);
+ return ret;
+ }
+
+ device->name = kasprintf(GFP_KERNEL, "%s", kobject_name(&dev->kobj));
+rename:
+ if (!device->name) {
+ sysfs_remove_link(&dev->kobj, "iommu_group");
+ kfree(device);
+ return -ENOMEM;
+ }
+
+ ret = sysfs_create_link_nowarn(group->devices_kobj,
+ &dev->kobj, device->name);
+ if (ret) {
+ kfree(device->name);
+ if (ret == -EEXIST && i >= 0) {
+ /*
+ * Account for the slim chance of collision
+ * and append an instance to the name.
+ */
+ device->name = kasprintf(GFP_KERNEL, "%s.%d",
+ kobject_name(&dev->kobj), i++);
+ goto rename;
+ }
+
+ sysfs_remove_link(&dev->kobj, "iommu_group");
+ kfree(device);
+ return ret;
+ }
+
+ kobject_get(group->devices_kobj);
+
+ dev->iommu_group = group;
+
+ mutex_lock(&group->mutex);
+ list_add_tail(&device->list, &group->devices);
+ mutex_unlock(&group->mutex);
+
+ /* Notify any listeners about change to group. */
+ blocking_notifier_call_chain(&group->notifier,
+ IOMMU_GROUP_NOTIFY_ADD_DEVICE, dev);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iommu_group_add_device);
+
+/**
+ * iommu_group_remove_device - remove a device from it's current group
+ * @dev: device to be removed
+ *
+ * This function is called by an iommu driver to remove the device from
+ * it's current group. This decrements the iommu group reference count.
+ */
+void iommu_group_remove_device(struct device *dev)
+{
+ struct iommu_group *group = dev->iommu_group;
+ struct iommu_device *tmp_device, *device = NULL;
+
+ /* Pre-notify listeners that a device is being removed. */
+ blocking_notifier_call_chain(&group->notifier,
+ IOMMU_GROUP_NOTIFY_DEL_DEVICE, dev);
+
+ mutex_lock(&group->mutex);
+ list_for_each_entry(tmp_device, &group->devices, list) {
+ if (tmp_device->dev == dev) {
+ device = tmp_device;
+ list_del(&device->list);
+ break;
+ }
+ }
+ mutex_unlock(&group->mutex);
+
+ if (!device)
+ return;
+
+ sysfs_remove_link(group->devices_kobj, device->name);
+ sysfs_remove_link(&dev->kobj, "iommu_group");
+
+ kfree(device->name);
+ kfree(device);
+ dev->iommu_group = NULL;
+ kobject_put(group->devices_kobj);
+}
+EXPORT_SYMBOL_GPL(iommu_group_remove_device);
+
+/**
+ * iommu_group_for_each_dev - iterate over each device in the group
+ * @group: the group
+ * @data: caller opaque data to be passed to callback function
+ * @fn: caller supplied callback function
+ *
+ * This function is called by group users to iterate over group devices.
+ * Callers should hold a reference count to the group during callback.
+ * The group->mutex is held across callbacks, which will block calls to
+ * iommu_group_add/remove_device.
+ */
+int iommu_group_for_each_dev(struct iommu_group *group, void *data,
+ int (*fn)(struct device *, void *))
+{
+ struct iommu_device *device;
+ int ret = 0;
+
+ mutex_lock(&group->mutex);
+ list_for_each_entry(device, &group->devices, list) {
+ ret = fn(device->dev, data);
+ if (ret)
+ break;
+ }
+ mutex_unlock(&group->mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_group_for_each_dev);
+
+/**
+ * iommu_group_get - Return the group for a device and increment reference
+ * @dev: get the group that this device belongs to
+ *
+ * This function is called by iommu drivers and users to get the group
+ * for the specified device. If found, the group is returned and the group
+ * reference in incremented, else NULL.
+ */
+struct iommu_group *iommu_group_get(struct device *dev)
+{
+ struct iommu_group *group = dev->iommu_group;
+
+ if (group)
+ kobject_get(group->devices_kobj);
+
+ return group;
+}
+EXPORT_SYMBOL_GPL(iommu_group_get);
+
+/**
+ * iommu_group_put - Decrement group reference
+ * @group: the group to use
+ *
+ * This function is called by iommu drivers and users to release the
+ * iommu group. Once the reference count is zero, the group is released.
+ */
+void iommu_group_put(struct iommu_group *group)
+{
+ if (group)
+ kobject_put(group->devices_kobj);
+}
+EXPORT_SYMBOL_GPL(iommu_group_put);
+
+/**
+ * iommu_group_register_notifier - Register a notifier for group changes
+ * @group: the group to watch
+ * @nb: notifier block to signal
+ *
+ * This function allows iommu group users to track changes in a group.
+ * See include/linux/iommu.h for actions sent via this notifier. Caller
+ * should hold a reference to the group throughout notifier registration.
+ */
+int iommu_group_register_notifier(struct iommu_group *group,
+ struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&group->notifier, nb);
+}
+EXPORT_SYMBOL_GPL(iommu_group_register_notifier);
+
+/**
+ * iommu_group_unregister_notifier - Unregister a notifier
+ * @group: the group to watch
+ * @nb: notifier block to signal
+ *
+ * Unregister a previously registered group notifier block.
+ */
+int iommu_group_unregister_notifier(struct iommu_group *group,
+ struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&group->notifier, nb);
+}
+EXPORT_SYMBOL_GPL(iommu_group_unregister_notifier);
+
+/**
+ * iommu_group_id - Return ID for a group
+ * @group: the group to ID
+ *
+ * Return the unique ID for the group matching the sysfs group number.
+ */
+int iommu_group_id(struct iommu_group *group)
+{
+ return group->id;
+}
+EXPORT_SYMBOL_GPL(iommu_group_id);
static int add_iommu_group(struct device *dev, void *data)
{
- unsigned int groupid;
+ struct iommu_ops *ops = data;
- if (iommu_device_group(dev, &groupid) == 0)
- return device_create_file(dev, &dev_attr_iommu_group);
+ if (!ops->add_device)
+ return -ENODEV;
+
+ WARN_ON(dev->iommu_group);
+
+ ops->add_device(dev);
return 0;
}
-static int remove_iommu_group(struct device *dev)
-{
- unsigned int groupid;
-
- if (iommu_device_group(dev, &groupid) == 0)
- device_remove_file(dev, &dev_attr_iommu_group);
-
- return 0;
-}
-
-static int iommu_device_notifier(struct notifier_block *nb,
- unsigned long action, void *data)
+static int iommu_bus_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
{
struct device *dev = data;
+ struct iommu_ops *ops = dev->bus->iommu_ops;
+ struct iommu_group *group;
+ unsigned long group_action = 0;
- if (action == BUS_NOTIFY_ADD_DEVICE)
- return add_iommu_group(dev, NULL);
- else if (action == BUS_NOTIFY_DEL_DEVICE)
- return remove_iommu_group(dev);
+ /*
+ * ADD/DEL call into iommu driver ops if provided, which may
+ * result in ADD/DEL notifiers to group->notifier
+ */
+ if (action == BUS_NOTIFY_ADD_DEVICE) {
+ if (ops->add_device)
+ return ops->add_device(dev);
+ } else if (action == BUS_NOTIFY_DEL_DEVICE) {
+ if (ops->remove_device && dev->iommu_group) {
+ ops->remove_device(dev);
+ return 0;
+ }
+ }
+ /*
+ * Remaining BUS_NOTIFYs get filtered and republished to the
+ * group, if anyone is listening
+ */
+ group = iommu_group_get(dev);
+ if (!group)
+ return 0;
+
+ switch (action) {
+ case BUS_NOTIFY_BIND_DRIVER:
+ group_action = IOMMU_GROUP_NOTIFY_BIND_DRIVER;
+ break;
+ case BUS_NOTIFY_BOUND_DRIVER:
+ group_action = IOMMU_GROUP_NOTIFY_BOUND_DRIVER;
+ break;
+ case BUS_NOTIFY_UNBIND_DRIVER:
+ group_action = IOMMU_GROUP_NOTIFY_UNBIND_DRIVER;
+ break;
+ case BUS_NOTIFY_UNBOUND_DRIVER:
+ group_action = IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER;
+ break;
+ }
+
+ if (group_action)
+ blocking_notifier_call_chain(&group->notifier,
+ group_action, dev);
+
+ iommu_group_put(group);
return 0;
}
-static struct notifier_block iommu_device_nb = {
- .notifier_call = iommu_device_notifier,
+static struct notifier_block iommu_bus_nb = {
+ .notifier_call = iommu_bus_notifier,
};
static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops)
{
- bus_register_notifier(bus, &iommu_device_nb);
- bus_for_each_dev(bus, NULL, NULL, add_iommu_group);
+ bus_register_notifier(bus, &iommu_bus_nb);
+ bus_for_each_dev(bus, NULL, ops, add_iommu_group);
}
/**
@@ -120,6 +595,7 @@
* iommu_set_fault_handler() - set a fault handler for an iommu domain
* @domain: iommu domain
* @handler: fault handler
+ * @token: user data, will be passed back to the fault handler
*
* This function should be used by IOMMU users which want to be notified
* whenever an IOMMU fault happens.
@@ -128,11 +604,13 @@
* error code otherwise.
*/
void iommu_set_fault_handler(struct iommu_domain *domain,
- iommu_fault_handler_t handler)
+ iommu_fault_handler_t handler,
+ void *token)
{
BUG_ON(!domain);
domain->handler = handler;
+ domain->handler_token = token;
}
EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
@@ -190,6 +668,45 @@
}
EXPORT_SYMBOL_GPL(iommu_detach_device);
+/*
+ * IOMMU groups are really the natrual working unit of the IOMMU, but
+ * the IOMMU API works on domains and devices. Bridge that gap by
+ * iterating over the devices in a group. Ideally we'd have a single
+ * device which represents the requestor ID of the group, but we also
+ * allow IOMMU drivers to create policy defined minimum sets, where
+ * the physical hardware may be able to distiguish members, but we
+ * wish to group them at a higher level (ex. untrusted multi-function
+ * PCI devices). Thus we attach each device.
+ */
+static int iommu_group_do_attach_device(struct device *dev, void *data)
+{
+ struct iommu_domain *domain = data;
+
+ return iommu_attach_device(domain, dev);
+}
+
+int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group)
+{
+ return iommu_group_for_each_dev(group, domain,
+ iommu_group_do_attach_device);
+}
+EXPORT_SYMBOL_GPL(iommu_attach_group);
+
+static int iommu_group_do_detach_device(struct device *dev, void *data)
+{
+ struct iommu_domain *domain = data;
+
+ iommu_detach_device(domain, dev);
+
+ return 0;
+}
+
+void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group)
+{
+ iommu_group_for_each_dev(group, domain, iommu_group_do_detach_device);
+}
+EXPORT_SYMBOL_GPL(iommu_detach_group);
+
phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long iova)
{
@@ -367,11 +884,15 @@
}
EXPORT_SYMBOL_GPL(iommu_get_pt_base_addr);
-int iommu_device_group(struct device *dev, unsigned int *groupid)
+static int __init iommu_init(void)
{
- if (iommu_present(dev->bus) && dev->bus->iommu_ops->device_group)
- return dev->bus->iommu_ops->device_group(dev, groupid);
+ iommu_group_kset = kset_create_and_add("iommu_groups",
+ NULL, kernel_kobj);
+ ida_init(&iommu_group_ida);
+ mutex_init(&iommu_group_mutex);
- return -ENODEV;
+ BUG_ON(!iommu_group_kset);
+
+ return 0;
}
-EXPORT_SYMBOL_GPL(iommu_device_group);
+subsys_initcall(iommu_init);
diff --git a/drivers/media/dvb/mpq/adapter/mpq_stream_buffer.c b/drivers/media/dvb/mpq/adapter/mpq_stream_buffer.c
index 4b0e7be..f779851 100644
--- a/drivers/media/dvb/mpq/adapter/mpq_stream_buffer.c
+++ b/drivers/media/dvb/mpq/adapter/mpq_stream_buffer.c
@@ -14,17 +14,47 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/wait.h>
+#include <linux/uaccess.h>
#include "mpq_dvb_debug.h"
#include "mpq_stream_buffer.h"
-void mpq_streambuffer_init(
+
+
+int mpq_streambuffer_init(
struct mpq_streambuffer *sbuff,
- void *data_buff, size_t data_buff_len,
- void *packet_buff, size_t packet_buff_size)
+ enum mpq_streambuffer_mode mode,
+ struct mpq_streambuffer_buffer_desc *data_buffers,
+ u32 data_buff_num,
+ void *packet_buff,
+ size_t packet_buff_size)
{
- dvb_ringbuffer_init(&sbuff->raw_data, data_buff, data_buff_len);
+ if ((NULL == sbuff) || (NULL == data_buffers) || (NULL == packet_buff))
+ return -EINVAL;
+
+ if (data_buff_num > 1) {
+ if (mode != MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR)
+ return -EINVAL;
+ /* Linear buffer group */
+ dvb_ringbuffer_init(
+ &sbuff->raw_data,
+ data_buffers,
+ data_buff_num *
+ sizeof(struct mpq_streambuffer_buffer_desc));
+ } else if (data_buff_num == 1) {
+ if (mode != MPQ_STREAMBUFFER_BUFFER_MODE_RING)
+ return -EINVAL;
+ /* Single ring-buffer */
+ dvb_ringbuffer_init(&sbuff->raw_data,
+ data_buffers[0].base, data_buffers[0].size);
+ }
+ sbuff->mode = mode;
+ sbuff->buffers = data_buffers;
+ sbuff->pending_buffers_count = 0;
+ sbuff->buffers_num = data_buff_num;
dvb_ringbuffer_init(&sbuff->packet_data, packet_buff, packet_buff_size);
+
+ return 0;
}
EXPORT_SYMBOL(mpq_streambuffer_init);
@@ -87,34 +117,55 @@
int ret;
struct mpq_streambuffer_packet_header packet;
- if (dispose_data) {
- /* read-out the packet header first */
- ret = dvb_ringbuffer_pkt_read(
- &sbuff->packet_data,
- idx,
- 0,
- (u8 *)&packet,
- sizeof(struct mpq_streambuffer_packet_header));
+ if (NULL == sbuff)
+ return -EINVAL;
- if (ret != sizeof(struct mpq_streambuffer_packet_header))
- return -EINVAL;
+ /* read-out the packet header first */
+ ret = dvb_ringbuffer_pkt_read(&sbuff->packet_data, idx,
+ 0,
+ (u8 *)&packet,
+ sizeof(struct mpq_streambuffer_packet_header));
+ if (ret != sizeof(struct mpq_streambuffer_packet_header))
+ return -EINVAL;
+
+ if ((MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR == sbuff->mode) ||
+ (dispose_data)) {
/* Advance the read pointer in the raw-data buffer first */
- ret = mpq_streambuffer_data_read_dispose(
- sbuff,
- packet.raw_data_len);
+ ret = mpq_streambuffer_data_read_dispose(sbuff,
+ packet.raw_data_len);
if (ret != 0)
return ret;
}
+ /* Move read pointer to the next linear buffer for subsequent reads */
+ if ((MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR == sbuff->mode) &&
+ (packet.raw_data_len > 0)) {
+ struct mpq_streambuffer_buffer_desc *desc;
+
+ desc = (struct mpq_streambuffer_buffer_desc *)
+ &sbuff->raw_data.data[sbuff->raw_data.pread];
+
+ desc->write_ptr = 0;
+ desc->read_ptr = 0;
+
+ DVB_RINGBUFFER_SKIP(&sbuff->raw_data,
+ sizeof(struct mpq_streambuffer_buffer_desc));
+ sbuff->pending_buffers_count--;
+
+ wake_up_all(&sbuff->raw_data.queue);
+ }
+
/* Now clear the packet from the packet header */
dvb_ringbuffer_pkt_dispose(&sbuff->packet_data, idx);
+ if (sbuff->cb)
+ sbuff->cb(sbuff, sbuff->cb_user_data);
+
return 0;
}
EXPORT_SYMBOL(mpq_streambuffer_pkt_dispose);
-
int mpq_streambuffer_pkt_write(
struct mpq_streambuffer *sbuff,
struct mpq_streambuffer_packet_header *packet,
@@ -123,30 +174,48 @@
ssize_t idx;
size_t len;
- len =
- sizeof(struct mpq_streambuffer_packet_header) +
+ if ((NULL == sbuff) || (NULL == packet))
+ return -EINVAL;
+
+ MPQ_DVB_DBG_PRINT(
+ "%s: handle=%d, offset=%d, len=%d\n",
+ __func__,
+ packet->raw_data_handle,
+ packet->raw_data_offset,
+ packet->raw_data_len);
+
+ len = sizeof(struct mpq_streambuffer_packet_header) +
packet->user_data_len;
/* Make sure enough space available for packet header */
if (dvb_ringbuffer_free(&sbuff->packet_data) < len)
return -ENOSPC;
- /* Starting writting packet header */
+ /* Starting writing packet header */
idx = dvb_ringbuffer_pkt_start(&sbuff->packet_data, len);
/* Write non-user private data header */
- dvb_ringbuffer_write(
- &sbuff->packet_data,
- (u8 *)packet,
- sizeof(struct mpq_streambuffer_packet_header));
+ dvb_ringbuffer_write(&sbuff->packet_data,
+ (u8 *)packet,
+ sizeof(struct mpq_streambuffer_packet_header));
/* Write user's own private data header */
dvb_ringbuffer_write(&sbuff->packet_data,
- user_data,
- packet->user_data_len);
+ user_data,
+ packet->user_data_len);
dvb_ringbuffer_pkt_close(&sbuff->packet_data, idx);
+ /* Move write pointer to next linear buffer for subsequent writes */
+ if ((MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR == sbuff->mode) &&
+ (packet->raw_data_len > 0)) {
+ if (sbuff->pending_buffers_count == sbuff->buffers_num)
+ return -ENOSPC;
+ DVB_RINGBUFFER_PUSH(&sbuff->raw_data,
+ sizeof(struct mpq_streambuffer_buffer_desc));
+ sbuff->pending_buffers_count++;
+ }
+
wake_up_all(&sbuff->packet_data.queue);
return 0;
@@ -160,11 +229,52 @@
{
int res;
- if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len))
- return -ENOSPC;
+ if ((NULL == sbuff) || (NULL == buf))
+ return -EINVAL;
- res = dvb_ringbuffer_write(&sbuff->raw_data, buf, len);
- wake_up_all(&sbuff->raw_data.queue);
+ if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
+ if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len))
+ return -ENOSPC;
+ /*
+ * Secure buffers are not permitted to be mapped into kernel
+ * memory, and so buffer base address may be NULL
+ */
+ if (NULL == sbuff->raw_data.data)
+ return -EPERM;
+ res = dvb_ringbuffer_write(&sbuff->raw_data, buf, len);
+ wake_up_all(&sbuff->raw_data.queue);
+ } else {
+ /* Linear buffer group */
+ struct mpq_streambuffer_buffer_desc *desc;
+
+ desc = (struct mpq_streambuffer_buffer_desc *)
+ &sbuff->raw_data.data[sbuff->raw_data.pwrite];
+
+ /*
+ * Secure buffers are not permitted to be mapped into kernel
+ * memory, and so buffer base address may be NULL
+ */
+ if (NULL == desc->base)
+ return -EPERM;
+
+ if ((sbuff->pending_buffers_count == sbuff->buffers_num) ||
+ ((desc->size - desc->write_ptr) < len)) {
+ MPQ_DVB_ERR_PRINT(
+ "%s: No space available! %d pending buffers out of %d total buffers. write_ptr=%d, size=%d\n",
+ __func__,
+ sbuff->pending_buffers_count,
+ sbuff->buffers_num,
+ desc->write_ptr,
+ desc->size);
+ return -ENOSPC;
+ }
+ memcpy(desc->base + desc->write_ptr, buf, len);
+ desc->write_ptr += len;
+ MPQ_DVB_DBG_PRINT(
+ "%s: copied %d data bytes. handle=%d, write_ptr=%d\n",
+ __func__, len, desc->handle, desc->write_ptr);
+ res = len;
+ }
return res;
}
@@ -175,50 +285,244 @@
struct mpq_streambuffer *sbuff,
size_t len)
{
+ if (NULL == sbuff)
+ return -EINVAL;
+
if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len))
return -ENOSPC;
- sbuff->raw_data.pwrite =
- (sbuff->raw_data.pwrite+len) % sbuff->raw_data.size;
+ if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
+ DVB_RINGBUFFER_PUSH(&sbuff->raw_data, len);
+ wake_up_all(&sbuff->raw_data.queue);
+ } else {
+ /* Linear buffer group */
+ struct mpq_streambuffer_buffer_desc *desc;
+ desc = (struct mpq_streambuffer_buffer_desc *)
+ &sbuff->raw_data.data[sbuff->raw_data.pwrite];
- wake_up_all(&sbuff->raw_data.queue);
+ if ((sbuff->pending_buffers_count == sbuff->buffers_num) ||
+ ((desc->size - desc->write_ptr) < len)) {
+ MPQ_DVB_ERR_PRINT(
+ "%s: No space available!\n",
+ __func__);
+ return -ENOSPC;
+ }
+ desc->write_ptr += len;
+ }
return 0;
}
EXPORT_SYMBOL(mpq_streambuffer_data_write_deposit);
-size_t mpq_streambuffer_data_read(
+ssize_t mpq_streambuffer_data_read(
struct mpq_streambuffer *sbuff,
u8 *buf, size_t len)
{
- ssize_t actual_len;
+ ssize_t actual_len = 0;
- actual_len = dvb_ringbuffer_avail(&sbuff->raw_data);
- if (actual_len < len)
- len = actual_len;
+ if ((NULL == sbuff) || (NULL == buf))
+ return -EINVAL;
- if (len)
- dvb_ringbuffer_read(&sbuff->raw_data, buf, len);
+ if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
+ /*
+ * Secure buffers are not permitted to be mapped into kernel
+ * memory, and so buffer base address may be NULL
+ */
+ if (NULL == sbuff->raw_data.data)
+ return -EPERM;
- wake_up_all(&sbuff->raw_data.queue);
+ actual_len = dvb_ringbuffer_avail(&sbuff->raw_data);
+ if (actual_len < len)
+ len = actual_len;
+ if (len)
+ dvb_ringbuffer_read(&sbuff->raw_data, buf, len);
+
+ wake_up_all(&sbuff->raw_data.queue);
+ } else {
+ /* Linear buffer group */
+ struct mpq_streambuffer_buffer_desc *desc;
+
+ desc = (struct mpq_streambuffer_buffer_desc *)
+ &sbuff->raw_data.data[sbuff->raw_data.pread];
+
+ /*
+ * Secure buffers are not permitted to be mapped into kernel
+ * memory, and so buffer base address may be NULL
+ */
+ if (NULL == desc->base)
+ return -EPERM;
+
+ actual_len = (desc->write_ptr - desc->read_ptr);
+ if (actual_len < len)
+ len = actual_len;
+ memcpy(buf, desc->base + desc->read_ptr, len);
+ desc->read_ptr += len;
+ }
return len;
}
EXPORT_SYMBOL(mpq_streambuffer_data_read);
+ssize_t mpq_streambuffer_data_read_user(
+ struct mpq_streambuffer *sbuff,
+ u8 __user *buf, size_t len)
+{
+ ssize_t actual_len = 0;
+
+ if ((NULL == sbuff) || (NULL == buf))
+ return -EINVAL;
+
+ if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
+ /*
+ * Secure buffers are not permitted to be mapped into kernel
+ * memory, and so buffer base address may be NULL
+ */
+ if (NULL == sbuff->raw_data.data)
+ return -EPERM;
+
+ actual_len = dvb_ringbuffer_avail(&sbuff->raw_data);
+ if (actual_len < len)
+ len = actual_len;
+ if (len)
+ dvb_ringbuffer_read_user(&sbuff->raw_data, buf, len);
+ wake_up_all(&sbuff->raw_data.queue);
+ } else {
+ /* Linear buffer group */
+ struct mpq_streambuffer_buffer_desc *desc;
+
+ desc = (struct mpq_streambuffer_buffer_desc *)
+ &sbuff->raw_data.data[sbuff->raw_data.pread];
+
+ /*
+ * Secure buffers are not permitted to be mapped into kernel
+ * memory, and so buffer base address may be NULL
+ */
+ if (NULL == desc->base)
+ return -EPERM;
+
+ actual_len = (desc->write_ptr - desc->read_ptr);
+ if (actual_len < len)
+ len = actual_len;
+ if (copy_to_user(buf, desc->base + desc->read_ptr, len))
+ return -EFAULT;
+ desc->read_ptr += len;
+ }
+
+ return len;
+}
+EXPORT_SYMBOL(mpq_streambuffer_data_read_user);
+
+
int mpq_streambuffer_data_read_dispose(
struct mpq_streambuffer *sbuff,
size_t len)
{
- if (unlikely(dvb_ringbuffer_avail(&sbuff->raw_data) < len))
+ if (NULL == sbuff)
return -EINVAL;
- DVB_RINGBUFFER_SKIP(&sbuff->raw_data, len);
+ if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
+ if (unlikely(dvb_ringbuffer_avail(&sbuff->raw_data) < len))
+ return -EINVAL;
- wake_up_all(&sbuff->raw_data.queue);
+ DVB_RINGBUFFER_SKIP(&sbuff->raw_data, len);
+ wake_up_all(&sbuff->raw_data.queue);
+ } else {
+ struct mpq_streambuffer_buffer_desc *desc;
+
+ desc = (struct mpq_streambuffer_buffer_desc *)
+ &sbuff->raw_data.data[sbuff->raw_data.pread];
+ if ((desc->read_ptr + len) > desc->size)
+ desc->read_ptr = desc->size;
+ else
+ desc->read_ptr += len;
+ }
+
return 0;
}
EXPORT_SYMBOL(mpq_streambuffer_data_read_dispose);
+
+int mpq_streambuffer_get_buffer_handle(
+ struct mpq_streambuffer *sbuff,
+ int read_buffer,
+ int *handle)
+{
+ struct mpq_streambuffer_buffer_desc *desc = NULL;
+
+ if ((NULL == sbuff) || (NULL == handle))
+ return -EINVAL;
+
+ if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
+ *handle = sbuff->buffers[0].handle;
+ } else {
+ if (read_buffer)
+ desc = (struct mpq_streambuffer_buffer_desc *)
+ &sbuff->raw_data.data[sbuff->raw_data.pread];
+ else
+ desc = (struct mpq_streambuffer_buffer_desc *)
+ &sbuff->raw_data.data[sbuff->raw_data.pwrite];
+ *handle = desc->handle;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(mpq_streambuffer_get_buffer_handle);
+
+
+int mpq_streambuffer_register_pkt_dispose(
+ struct mpq_streambuffer *sbuff,
+ mpq_streambuffer_pkt_dispose_cb cb_func,
+ void *user_data)
+{
+ if ((NULL == sbuff) || (NULL == cb_func))
+ return -EINVAL;
+
+ sbuff->cb = cb_func;
+ sbuff->cb_user_data = user_data;
+
+ return 0;
+}
+EXPORT_SYMBOL(mpq_streambuffer_register_pkt_dispose);
+
+
+ssize_t mpq_streambuffer_data_free(
+ struct mpq_streambuffer *sbuff)
+{
+ struct mpq_streambuffer_buffer_desc *desc;
+
+ if (NULL == sbuff)
+ return -EINVAL;
+
+ if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode)
+ return dvb_ringbuffer_free(&sbuff->raw_data);
+
+ if (sbuff->pending_buffers_count == sbuff->buffers_num)
+ return 0;
+
+ desc = (struct mpq_streambuffer_buffer_desc *)
+ &sbuff->raw_data.data[sbuff->raw_data.pwrite];
+
+ return desc->size - desc->write_ptr;
+}
+EXPORT_SYMBOL(mpq_streambuffer_data_free);
+
+
+ssize_t mpq_streambuffer_data_avail(
+ struct mpq_streambuffer *sbuff)
+{
+ struct mpq_streambuffer_buffer_desc *desc;
+
+ if (NULL == sbuff)
+ return -EINVAL;
+
+ if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode)
+ return dvb_ringbuffer_avail(&sbuff->raw_data);
+
+ desc = (struct mpq_streambuffer_buffer_desc *)
+ &sbuff->raw_data.data[sbuff->raw_data.pread];
+
+ return desc->write_ptr - desc->read_ptr;
+}
+EXPORT_SYMBOL(mpq_streambuffer_data_avail);
+
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
index e2ef6a0..2a60840 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
+#include <linux/file.h>
#include "mpq_dvb_debug.h"
#include "mpq_dmx_plugin_common.h"
@@ -983,6 +984,19 @@
goto init_failed_free_payload_buffer;
}
+ feed_data->buffer_desc.read_ptr = 0;
+ feed_data->buffer_desc.write_ptr = 0;
+ feed_data->buffer_desc.base = payload_buffer;
+ feed_data->buffer_desc.size = actual_buffer_size;
+ feed_data->buffer_desc.handle =
+ ion_share_dma_buf(
+ mpq_demux->ion_client,
+ feed_data->payload_buff_handle);
+ if (feed_data->buffer_desc.handle < 0) {
+ ret = -EFAULT;
+ goto init_failed_unmap_payload_buffer;
+ }
+
/* Register the new stream-buffer interface to MPQ adapter */
switch (feed->pes_type) {
case DMX_TS_PES_VIDEO0:
@@ -1011,7 +1025,7 @@
__func__,
feed->pes_type);
ret = -EINVAL;
- goto init_failed_unmap_payload_buffer;
+ goto init_failed_unshare_payload_buffer;
}
/* make sure not occupied already */
@@ -1025,30 +1039,36 @@
__func__,
feed_data->stream_interface);
ret = -EBUSY;
- goto init_failed_unmap_payload_buffer;
+ goto init_failed_unshare_payload_buffer;
}
feed_data->video_buffer =
&mpq_dmx_info.decoder_buffers[feed_data->stream_interface];
- mpq_streambuffer_init(
- feed_data->video_buffer,
- payload_buffer,
- actual_buffer_size,
- packet_buffer,
- VIDEO_META_DATA_BUFFER_SIZE);
+ ret = mpq_streambuffer_init(
+ feed_data->video_buffer,
+ MPQ_STREAMBUFFER_BUFFER_MODE_RING,
+ &feed_data->buffer_desc,
+ 1,
+ packet_buffer,
+ VIDEO_META_DATA_BUFFER_SIZE);
+ if (ret < 0) {
+ MPQ_DVB_ERR_PRINT(
+ "%s: mpq_streambuffer_init failed, err = %d\n",
+ __func__, ret);
+ goto init_failed_unshare_payload_buffer;
+ }
- ret =
- mpq_adapter_register_stream_if(
- feed_data->stream_interface,
- feed_data->video_buffer);
+ ret = mpq_adapter_register_stream_if(
+ feed_data->stream_interface,
+ feed_data->video_buffer);
if (ret < 0) {
MPQ_DVB_ERR_PRINT(
"%s: mpq_adapter_register_stream_if failed, "
"err = %d\n",
__func__, ret);
- goto init_failed_unmap_payload_buffer;
+ goto init_failed_unshare_payload_buffer;
}
feed->buffer_size = actual_buffer_size;
@@ -1067,7 +1087,13 @@
sizeof(struct mpq_framing_prefix_size_masks));
feed_data->first_pattern_offset = 0;
feed_data->first_prefix_size = 0;
- feed_data->write_pts_dts = 0;
+ feed_data->saved_pts_dts_info.pts_exist = 0;
+ feed_data->saved_pts_dts_info.dts_exist = 0;
+ feed_data->new_pts_dts_info.pts_exist = 0;
+ feed_data->new_pts_dts_info.dts_exist = 0;
+ feed_data->saved_info_used = 1;
+ feed_data->new_info_exists = 0;
+ feed_data->first_pts_dts_copy = 1;
spin_lock(&mpq_demux->feed_lock);
feed->priv = (void *)feed_data;
@@ -1075,6 +1101,8 @@
return 0;
+init_failed_unshare_payload_buffer:
+ put_unused_fd(feed_data->buffer_desc.handle);
init_failed_unmap_payload_buffer:
ion_unmap_kernel(mpq_demux->ion_client,
feed_data->payload_buff_handle);
@@ -1119,6 +1147,8 @@
vfree(feed_data->video_buffer->packet_data.data);
+ put_unused_fd(feed_data->buffer_desc.handle);
+
ion_unmap_kernel(mpq_demux->ion_client,
feed_data->payload_buff_handle);
@@ -1338,6 +1368,83 @@
return 0;
}
+static inline void mpq_dmx_save_pts_dts(struct mpq_video_feed_info *feed_data)
+{
+ if (feed_data->new_info_exists) {
+ feed_data->saved_pts_dts_info.pts_exist =
+ feed_data->new_pts_dts_info.pts_exist;
+ feed_data->saved_pts_dts_info.pts =
+ feed_data->new_pts_dts_info.pts;
+ feed_data->saved_pts_dts_info.dts_exist =
+ feed_data->new_pts_dts_info.dts_exist;
+ feed_data->saved_pts_dts_info.dts =
+ feed_data->new_pts_dts_info.dts;
+
+ feed_data->new_info_exists = 0;
+ feed_data->saved_info_used = 0;
+ }
+}
+
+static inline void mpq_dmx_write_pts_dts(struct mpq_video_feed_info *feed_data,
+ struct dmx_pts_dts_info *info)
+{
+ if (!feed_data->saved_info_used) {
+ info->pts_exist = feed_data->saved_pts_dts_info.pts_exist;
+ info->pts = feed_data->saved_pts_dts_info.pts;
+ info->dts_exist = feed_data->saved_pts_dts_info.dts_exist;
+ info->dts = feed_data->saved_pts_dts_info.dts;
+
+ feed_data->saved_info_used = 1;
+ } else {
+ info->pts_exist = 0;
+ info->dts_exist = 0;
+ }
+}
+
+static inline void mpq_dmx_get_pts_dts(struct mpq_video_feed_info *feed_data,
+ struct pes_packet_header *pes_header)
+{
+ struct dmx_pts_dts_info *info = &(feed_data->new_pts_dts_info);
+
+ /* Get PTS/DTS information from PES header */
+
+ if ((pes_header->pts_dts_flag == 2) ||
+ (pes_header->pts_dts_flag == 3)) {
+ info->pts_exist = 1;
+
+ info->pts =
+ ((u64)pes_header->pts_1 << 30) |
+ ((u64)pes_header->pts_2 << 22) |
+ ((u64)pes_header->pts_3 << 15) |
+ ((u64)pes_header->pts_4 << 7) |
+ (u64)pes_header->pts_5;
+ } else {
+ info->pts_exist = 0;
+ info->pts = 0;
+ }
+
+ if (pes_header->pts_dts_flag == 3) {
+ info->dts_exist = 1;
+
+ info->dts =
+ ((u64)pes_header->dts_1 << 30) |
+ ((u64)pes_header->dts_2 << 22) |
+ ((u64)pes_header->dts_3 << 15) |
+ ((u64)pes_header->dts_4 << 7) |
+ (u64)pes_header->dts_5;
+ } else {
+ info->dts_exist = 0;
+ info->dts = 0;
+ }
+
+ feed_data->new_info_exists = 1;
+
+ if (feed_data->first_pts_dts_copy) {
+ mpq_dmx_save_pts_dts(feed_data);
+ feed_data->first_pts_dts_copy = 0;
+ }
+}
+
static inline int mpq_dmx_parse_remaining_pes_header(
struct dvb_demux_feed *feed,
struct mpq_video_feed_info *feed_data,
@@ -1381,7 +1488,6 @@
/* else - we have the PTS */
*bytes_avail -= copy_len;
*ts_payload_offset += copy_len;
- feed_data->write_pts_dts = 1;
}
/* Did we capture the DTS value (if exist)? */
@@ -1412,7 +1518,6 @@
/* else - we have the DTS */
*bytes_avail -= copy_len;
*ts_payload_offset += copy_len;
- feed_data->write_pts_dts = 1;
}
/* Any more header bytes?! */
@@ -1421,6 +1526,9 @@
return -EINVAL;
}
+ /* get PTS/DTS information from PES header to be written later */
+ mpq_dmx_get_pts_dts(feed_data, pes_header);
+
/* Got PES header, process payload */
*bytes_avail -= feed_data->pes_header_left_bytes;
*ts_payload_offset += feed_data->pes_header_left_bytes;
@@ -1429,53 +1537,6 @@
return 0;
}
-static inline void mpq_dmx_get_pts_dts(struct mpq_video_feed_info *feed_data,
- struct pes_packet_header *pes_header,
- struct mpq_adapter_video_meta_data *meta_data,
- enum dmx_packet_type packet_type)
-{
- struct dmx_pts_dts_info *info;
-
- if (packet_type == DMX_PES_PACKET)
- info = &(meta_data->info.pes.pts_dts_info);
- else
- info = &(meta_data->info.framing.pts_dts_info);
-
- if (feed_data->write_pts_dts) {
- if ((pes_header->pts_dts_flag == 2) ||
- (pes_header->pts_dts_flag == 3)) {
- info->pts_exist = 1;
-
- info->pts =
- ((u64)pes_header->pts_1 << 30) |
- ((u64)pes_header->pts_2 << 22) |
- ((u64)pes_header->pts_3 << 15) |
- ((u64)pes_header->pts_4 << 7) |
- (u64)pes_header->pts_5;
- } else {
- info->pts_exist = 0;
- info->pts = 0;
- }
-
- if (pes_header->pts_dts_flag == 3) {
- info->dts_exist = 1;
-
- info->dts =
- ((u64)pes_header->dts_1 << 30) |
- ((u64)pes_header->dts_2 << 22) |
- ((u64)pes_header->dts_3 << 15) |
- ((u64)pes_header->dts_4 << 7) |
- (u64)pes_header->dts_5;
- } else {
- info->dts_exist = 0;
- info->dts = 0;
- }
- } else {
- info->pts_exist = 0;
- info->dts_exist = 0;
- }
-}
-
static int mpq_dmx_process_video_packet_framing(
struct dvb_demux_feed *feed,
const u8 *buf)
@@ -1550,7 +1611,6 @@
feed_data->pes_header_offset = 0;
feed_data->pes_header_left_bytes =
PES_MANDATORY_FIELDS_LEN;
- feed_data->write_pts_dts = 0;
} else {
feed->pusi_seen = 1;
}
@@ -1692,6 +1752,8 @@
feed->peslen += bytes_avail;
meta_data.packet_type = DMX_FRAMING_INFO_PACKET;
+ packet.raw_data_handle = feed_data->buffer_desc.handle;
+ packet.raw_data_offset = 0;
packet.user_data_len =
sizeof(struct mpq_adapter_video_meta_data);
@@ -1701,10 +1763,10 @@
feed->indexing_params.standard,
feed_data->last_framing_match_type);
if (is_video_frame == 1) {
- mpq_dmx_get_pts_dts(feed_data,
- pes_header,
- &meta_data,
- DMX_FRAMING_INFO_PACKET);
+ mpq_dmx_write_pts_dts(feed_data,
+ &(meta_data.info.framing.
+ pts_dts_info));
+ mpq_dmx_save_pts_dts(feed_data);
} else {
meta_data.info.framing.
pts_dts_info.pts_exist = 0;
@@ -1717,8 +1779,6 @@
*/
meta_data.info.framing.pattern_type =
feed_data->last_framing_match_type;
- packet.raw_data_addr =
- feed_data->last_framing_match_address;
pattern_addr = feed_data->pes_payload_address +
framing_res.info[i].offset -
@@ -1742,10 +1802,8 @@
feed_data->first_pattern_offset;
}
- MPQ_DVB_DBG_PRINT("Writing Packet: "
- "addr = 0x%X, len = %d, type = %d, "
- "isPts = %d, isDts = %d\n",
- packet.raw_data_addr,
+ MPQ_DVB_DBG_PRINT(
+ "Writing Packet: len = %d, type = %d, isPts = %d, isDts = %d\n",
packet.raw_data_len,
meta_data.info.framing.pattern_type,
meta_data.info.framing.
@@ -1754,16 +1812,11 @@
pts_dts_info.dts_exist);
if (mpq_streambuffer_pkt_write(stream_buffer,
- &packet,
- (u8 *)&meta_data) < 0) {
- MPQ_DVB_ERR_PRINT(
- "%s: "
- "Couldn't write packet. "
- "Should never happen\n",
+ &packet,
+ (u8 *)&meta_data) < 0) {
+ MPQ_DVB_ERR_PRINT(
+ "%s: Couldn't write packet. Should never happen\n",
__func__);
- } else {
- if (is_video_frame == 1)
- feed_data->write_pts_dts = 0;
}
}
@@ -1855,18 +1908,17 @@
*/
if (0 == feed_data->pes_header_left_bytes) {
- packet.raw_data_addr =
- feed_data->pes_payload_address;
-
packet.raw_data_len = feed->peslen;
-
+ packet.raw_data_handle =
+ feed_data->buffer_desc.handle;
+ packet.raw_data_offset = 0;
packet.user_data_len =
sizeof(struct
mpq_adapter_video_meta_data);
- mpq_dmx_get_pts_dts(feed_data, pes_header,
- &meta_data,
- DMX_PES_PACKET);
+ mpq_dmx_write_pts_dts(feed_data,
+ &(meta_data.info.pes.pts_dts_info));
+ mpq_dmx_save_pts_dts(feed_data);
meta_data.packet_type = DMX_PES_PACKET;
@@ -1879,8 +1931,6 @@
"Couldn't write packet. "
"Should never happen\n",
__func__);
- else
- feed_data->write_pts_dts = 0;
} else {
MPQ_DVB_ERR_PRINT(
"%s: received PUSI"
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h
index 69305b6..f7af1ef 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h
@@ -275,6 +275,7 @@
* @plugin_data: Underlying plugin's own private data.
* @video_buffer: Holds the streamer buffer shared with
* the decoder for feeds having the data going to the decoder.
+ * @buffer_desc: Holds decoder buffer(s) information used for stream buffer.
* @pes_header: Used for feeds that output data to decoder,
* holds PES header of current processed PES.
* @pes_header_left_bytes: Used for feeds that output data to decoder,
@@ -308,14 +309,18 @@
* to the stream buffer.
* @first_prefix_size: used to save the prefix size used to find the first
* pattern written to the stream buffer.
- * @write_pts_dts: Flag used to decide if to write PTS/DTS information
- * (if it is available in the PES header) in the meta-data passed
- * to the video decoder. PTS/DTS information is written in the first
- * packet after it is available.
+ * @saved_pts_dts_info: used to save PTS/DTS information until it is written.
+ * @new_pts_dts_info: used to store PTS/DTS information from current PES header.
+ * @saved_info_used: indicates if saved PTS/DTS information was used.
+ * @new_info_exists: indicates if new PTS/DTS information exists in
+ * new_pts_dts_info that should be saved to saved_pts_dts_info.
+ * @first_pts_dts_copy: a flag used to indicate if PTS/DTS information needs
+ * to be copied from the currently parsed PES header to the saved_pts_dts_info.
*/
struct mpq_video_feed_info {
void *plugin_data;
struct mpq_streambuffer *video_buffer;
+ struct mpq_streambuffer_buffer_desc buffer_desc;
struct pes_packet_header pes_header;
u32 pes_header_left_bytes;
u32 pes_header_offset;
@@ -331,7 +336,11 @@
struct mpq_framing_prefix_size_masks prefix_size;
u32 first_pattern_offset;
u32 first_prefix_size;
- int write_pts_dts;
+ struct dmx_pts_dts_info saved_pts_dts_info;
+ struct dmx_pts_dts_info new_pts_dts_info;
+ int saved_info_used;
+ int new_info_exists;
+ int first_pts_dts_copy;
};
/**
diff --git a/drivers/media/dvb/mpq/include/mpq_stream_buffer.h b/drivers/media/dvb/mpq/include/mpq_stream_buffer.h
index 4ea4222..9476c73 100644
--- a/drivers/media/dvb/mpq/include/mpq_stream_buffer.h
+++ b/drivers/media/dvb/mpq/include/mpq_stream_buffer.h
@@ -19,7 +19,7 @@
/**
* DOC: MPQ Stream Buffer
*
- * A stream buffer implmenetation used to transfer data between two units
+ * A stream buffer implementation is used to transfer data between two units
* such as demux and decoders. The implementation relies on dvb_ringbuffer
* implementation. Refer to dvb_ringbuffer.h for details.
*
@@ -28,8 +28,19 @@
* meta-data (information from PES header for example).
*
* The meta-data uses dvb_ringbuffer packet interface. Each meta-data
- * packet hold the address and size of raw-data described by the
- * meta-data packet, in addition to user's own parameters if any required.
+ * packet points to the data buffer, and includes the offset to the data in the
+ * buffer, the size of raw-data described by the meta-data packet, and also the
+ * size of user's own parameters if any required.
+ *
+ * Data can be managed in two ways: ring-buffer & linear buffers, as specified
+ * in initialization when calling the mpq_streambuffer_init function.
+ * For managing data as a ring buffer exactly 1 data buffer descriptor must be
+ * specified in initialization. For this mode, dvb_ringbuffer is used "as-is".
+ * For managing data in several linear buffers, an array of buffer descriptors
+ * must be passed.
+ * For both modes, data descriptor(s) must be remain valid throughout the life
+ * span of the mpq_streambuffer object.
+ * Apart from initialization API remains the same for both modes.
*
* Contrary to dvb_ringbuffer implementation, this API makes sure there's
* enough data to read/write when making read/write operations.
@@ -44,18 +55,22 @@
*
* Typical call flow from producer:
*
- * - Start writting the raw-data of new packet, the following call is
+ * - Start writing the raw-data of new packet, the following call is
* repeated until end of data of the specific packet
*
- * mpq_streambuffer_data_write(...)
+ * mpq_streambuffer_data_write(...)
*
* - Now write a new packet describing the new available raw-data
- * mpq_streambuffer_pkt_write(...)
+ * mpq_streambuffer_pkt_write(...)
+ *
+ * For linear buffer mode, writing a new packet with data size > 0, causes the
+ * current buffer to be marked as pending for reading, and triggers moving to
+ * the next available buffer, that shall now be the current write buffer.
*
* Typical call flow from consumer:
*
* - Poll for next available packet:
- * mpq_streambuffer_pkt_next(&streambuff,-1)
+ * mpq_streambuffer_pkt_next(&streambuff,-1,&len)
*
* In different approach, consumer can wait on event for new data and then
* call mpq_streambuffer_pkt_next, waiting for data can be done as follows:
@@ -77,58 +92,126 @@
* data buffer, the amount of raw-data is provided part of the
* packet's information. User should then call mpq_streambuffer_pkt_dispose
* with dispose_data set to 0 as the raw-data was already disposed.
+ * Note that secure buffer cannot be accessed directly and an error will
+ * occur.
*
* 2. Access the data directly using the raw-data address. The address
* of the raw data is provided part of the packet's information. User
* then should call mpq_streambuffer_pkt_dispose with dispose_data set
* to 1 to dispose the packet along with it's raw-data.
+ *
+ * - Disposal of packets:
+ * mpq_streambuffer_pkt_dispose(...)
+ *
+ * For linear buffer mode, disposing of a packet with data size > 0, causes
+ * the current buffer to be marked as free for writing, and triggers moving to
+ * the next available buffer, that shall now be the current read buffer.
+
+ *
*/
+struct mpq_streambuffer;
+
+typedef void (*mpq_streambuffer_pkt_dispose_cb) (
+ struct mpq_streambuffer *sbuff,
+ void *user_data);
+
+enum mpq_streambuffer_mode {
+ MPQ_STREAMBUFFER_BUFFER_MODE_RING,
+ MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR
+};
+
/**
* struct mpq_streambuffer - mpq stream buffer representation
*
- * @raw_data: The buffer used to hold the raw-data
+ * @raw_data: The buffer used to hold raw-data, or linear buffer descriptors
* @packet_data: The buffer user to hold the meta-data
+ * @buffers: array of buffer descriptor(s) holding buffer initial & dynamic
+ * buffer information
+ * @mode: mpq_streambuffer buffer management work mode - Ring-buffer or Linear
+ * buffers
+ * @buffers_num: number of data buffers to manage
+ * @pending_buffers_count: for linear buffer management, counts the number of
+ * buffer that has been
*/
struct mpq_streambuffer {
struct dvb_ringbuffer raw_data;
struct dvb_ringbuffer packet_data;
+ struct mpq_streambuffer_buffer_desc *buffers;
+ enum mpq_streambuffer_mode mode;
+ u32 buffers_num;
+ u32 pending_buffers_count;
+ mpq_streambuffer_pkt_dispose_cb cb;
+ void *cb_user_data;
+};
+
+/**
+ * mpq_streambuffer_linear_desc
+ * @handle: ION handle's file descriptor of buffer
+ * @base: kernel mapped address to start of buffer.
+ * Can be NULL for secured buffers
+ * @size: size of buffer
+ * @read_ptr: initial read pointer value (should normally be 0)
+ * @write_ptr: initial write pointer value (should normally be 0)
+ */
+struct mpq_streambuffer_buffer_desc {
+ int handle;
+ void *base;
+ u32 size;
+ u32 read_ptr;
+ u32 write_ptr;
};
/**
* struct mpq_streambuffer_packet_header - packet header saved in packet buffer
* @user_data_len: length of private user (meta) data
- * @raw_data_addr: raw-data address in the raw-buffer described by the packet
+ * @raw_data_handle: ION handle's file descriptor of raw-data buffer
+ * @raw_data_offset: offset of raw-data from start of buffer (0 for linear)
* @raw_data_len: size of raw-data in the raw-data buffer (can be 0)
*
* The packet structure that is saved in each packet-buffer:
* user_data_len
- * raw_data_addr
+ * raw_data_handle
+ * raw_data_offset
* raw_data_len
* private user-data bytes
*/
struct mpq_streambuffer_packet_header {
u32 user_data_len;
- u32 raw_data_addr;
- u32 raw_data_len;
+ int raw_data_handle;
+ u32 raw_data_offset;
+ u32 raw_data_len;
} __packed;
/**
* mpq_streambuffer_init - Initialize a new stream buffer
*
* @sbuff: The buffer to initialize
- * @data_buff: The buffer holding raw-data
- * @data_buff_len: Size of raw-data buffer
+ * @data_buffers: array of data buffer descriptor(s).
+ * Data descriptor(s) must be remain valid throughout the life
+ * span of the mpq_streambuffer object
+ * @data_buff_num: number of data buffer in array
* @packet_buff: The buffer holding meta-data
* @packet_buff_size: Size of meta-data buffer
+ *
+ * Return Error status, -EINVAL if any of the arguments are invalid
+ *
+ * Note:
+ * for data_buff_num > 1, mpq_streambuffer object manages these buffers as a
+ * separated set of linear buffers. A linear buffer cannot wrap-around and one
+ * can only write as many data bytes as the buffer's size. Data will not be
+ * written to the next free buffer.
*/
-void mpq_streambuffer_init(
+int mpq_streambuffer_init(
struct mpq_streambuffer *sbuff,
- void *data_buff, size_t data_buff_len,
- void *packet_buff, size_t packet_buff_size);
+ enum mpq_streambuffer_mode mode,
+ struct mpq_streambuffer_buffer_desc *data_buffers,
+ u32 data_buff_num,
+ void *packet_buff,
+ size_t packet_buff_size);
/**
- * mpq_streambuffer_packet_next - Returns index of next avaialble packet.
+ * mpq_streambuffer_packet_next - Returns index of next available packet.
*
* @sbuff: The stream buffer
* @idx: Previous packet index or -1 to return index of the the first
@@ -234,19 +317,29 @@
* @buf: The buffer to read the raw-data data to
* @len: The length of the buffer that will hold the raw-data
*
- * Return The actual number of bytes read
+ * Return The actual number of bytes read or error code
*
- * This fucntion copies the data from the ring-buffer to the
+ * This function copies the data from the ring-buffer to the
* provided buf parameter. The user can save the extra copy by accessing
* the data pointer directly and reading from it, then update the
* read pointer by the amount of data that was read using
* mpq_streambuffer_data_read_dispose
*/
-size_t mpq_streambuffer_data_read(
+ssize_t mpq_streambuffer_data_read(
struct mpq_streambuffer *sbuff,
u8 *buf, size_t len);
/**
+ * mpq_streambuffer_data_read_user
+ *
+ * Same as mpq_streambuffer_data_read except data can be copied to user-space
+ * buffer.
+ */
+ssize_t mpq_streambuffer_data_read_user(
+ struct mpq_streambuffer *sbuff,
+ u8 __user *buf, size_t len);
+
+/**
* mpq_streambuffer_data_read_dispose - Advances the raw-buffer read pointer.
* Assumes the raw-data was read by the user directly.
*
@@ -256,12 +349,69 @@
* Return error status, -EINVAL if buffer there's no enough data to
* be disposed
*
- * The user can instead dipose a packet along with the data in the
+ * The user can instead dispose a packet along with the data in the
* raw-data buffer using mpq_streambuffer_pkt_dispose.
*/
int mpq_streambuffer_data_read_dispose(
struct mpq_streambuffer *sbuff,
size_t len);
+/**
+ * mpq_streambuffer_get_buffer_handle - Returns the current linear buffer
+ * ION handle.
+ * @sbuff: The stream buffer
+ * @read_buffer: specifies if a read buffer handle is requested (when set),
+ * or a write buffer handle is requested.
+ * For linear buffer mode read & write buffers may be different
+ * buffers. For ring buffer mode, the same (single) buffer handle
+ * is returned.
+ * buffer handle
+ * @handle: returned handle
+ *
+ * Return error status
+ * -EINVAL is arguments are invalid.
+ * -EPERM if stream buffer specified was not initialized with linear support.
+ */
+int mpq_streambuffer_get_buffer_handle(
+ struct mpq_streambuffer *sbuff,
+ int read_buffer,
+ int *handle);
+
+/**
+ * mpq_streambuffer_data_free - Returns number of free bytes in data buffer.
+ * @sbuff: The stream buffer object
+ *
+ * Note: for linear buffer management this return number of free bytes in the
+ * current write buffer only.
+ */
+ssize_t mpq_streambuffer_data_free(
+ struct mpq_streambuffer *sbuff);
+
+/**
+ * mpq_streambuffer_data_avail - Returns number of bytes in data buffer that
+ * can be read.
+ * @sbuff: The stream buffer object
+ *
+ * Note: for linear buffer management this return number of data bytes in the
+ * current read buffer only.
+ */
+ssize_t mpq_streambuffer_data_avail(
+ struct mpq_streambuffer *sbuff);
+
+/**
+ * mpq_streambuffer_register_pkt_dispose - Registers a callback to notify on
+ * packet disposal events.
+ * can be read.
+ * @sbuff: The stream buffer object
+ * @cb_func: user callback function
+ * @user_data: user data to be passed to callback function.
+ *
+ * Returns error status
+ * -EINVAL if arguments are invalid
+ */
+int mpq_streambuffer_register_pkt_dispose(
+ struct mpq_streambuffer *sbuff,
+ mpq_streambuffer_pkt_dispose_cb cb_func,
+ void *user_data);
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index e1b73ef..eae18c4 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -134,6 +134,9 @@
}
heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
+ if (!(flags & SMEM_SECURE))
+ heap_mask |= ION_HEAP(ION_IOMMU_HEAP_ID);
+
dprintk(VIDC_DBG, "domain: %d, partition: %d\n",
domain, partition);
hndl = ion_alloc(client->clnt, size, align, heap_mask, ionflags);
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 711b3007..fb920ca 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -1060,6 +1060,7 @@
inst->prop.height = DEFAULT_HEIGHT;
inst->prop.width = DEFAULT_WIDTH;
inst->prop.fps = 30;
+ inst->prop.prev_time_stamp = 0;
return rc;
}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index fa056ca..b9ff82e 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -63,6 +63,8 @@
int ret;
};
+#define TIME_DIFF_THRESHOLD 200
+
static const u32 bus_table[] = {
36000,
110400,
@@ -756,12 +758,58 @@
}
}
+static void msm_comm_update_clocks(struct msm_vidc_inst *inst,
+ u64 cur_time_stamp)
+{
+ u32 new_time_diff = 0, cur_time_diff = 0;
+ u8 updated_fps = 0;
+ struct v4l2_ctrl *ctrl = NULL;
+ u32 output_order = 0;
+
+ if (inst->session_type == MSM_VIDC_ENCODER)
+ goto exit;
+ ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
+ V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER);
+ if (!ctrl) {
+ dprintk(VIDC_WARN, "Unable to find output order control\n");
+ dprintk(VIDC_WARN,
+ "Performance might be impacted for higher fps clips\n");
+ goto exit;
+ }
+ output_order = v4l2_ctrl_g_ctrl(ctrl);
+ if (output_order == V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY) {
+ new_time_diff =
+ (u32)(cur_time_stamp - inst->prop.prev_time_stamp);
+ inst->prop.prev_time_stamp = cur_time_stamp;
+ if (!new_time_diff)
+ goto exit;
+ if (inst->prop.fps)
+ cur_time_diff = USEC_PER_SEC / inst->prop.fps;
+ cur_time_diff = cur_time_diff > new_time_diff ?
+ cur_time_diff - new_time_diff :
+ new_time_diff - cur_time_diff;
+ if (cur_time_diff > TIME_DIFF_THRESHOLD) {
+ updated_fps = (u8) (USEC_PER_SEC / new_time_diff);
+ if (updated_fps && (updated_fps != inst->prop.fps)) {
+ inst->prop.fps = updated_fps;
+ dprintk(VIDC_DBG,
+ "Updating clocks: Decoding fps = %d\n",
+ inst->prop.fps);
+ msm_comm_scale_clocks_and_bus(inst);
+ }
+ }
+ }
+exit:
+ return;
+}
+
static void handle_fbd(enum command_response cmd, void *data)
{
struct msm_vidc_cb_data_done *response = data;
struct msm_vidc_inst *inst;
struct vb2_buffer *vb;
struct vidc_hal_fbd *fill_buf_done;
+
if (!response) {
dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
return;
@@ -777,9 +825,9 @@
int64_t time_usec = fill_buf_done->timestamp_hi;
time_usec = (time_usec << 32) |
fill_buf_done->timestamp_lo;
-
vb->v4l2_buf.timestamp =
ns_to_timeval(time_usec * NSEC_PER_USEC);
+ msm_comm_update_clocks(inst, time_usec);
}
vb->v4l2_buf.flags = 0;
@@ -1013,16 +1061,17 @@
}
if (msm_comm_scale_clocks(core)) {
dprintk(VIDC_WARN,
- "Failed to scale clocks. Performance might be impacted\n");
+ "Failed to scale clocks. Performance might be impacted\n");
}
if (msm_comm_scale_bus(core, inst->session_type, DDR_MEM)) {
dprintk(VIDC_WARN,
- "Failed to scale DDR bus. Performance might be impacted\n");
+ "Failed to scale DDR bus. Performance might be impacted\n");
}
if (core->resources.ocmem.buf) {
- if (msm_comm_scale_bus(core, inst->session_type, OCMEM_MEM))
+ if (msm_comm_scale_bus(core, inst->session_type,
+ OCMEM_MEM))
dprintk(VIDC_WARN,
- "Failed to scale OCMEM bus. Performance might be impacted\n");
+ "Failed to scale OCMEM bus. Performance might be impacted\n");
}
}
@@ -1710,7 +1759,6 @@
inst->state, state);
return rc;
}
-
int msm_comm_qbuf(struct vb2_buffer *vb)
{
int rc = 0;
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index b274d13..b88f909 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -170,6 +170,7 @@
u32 height;
u32 fps;
u32 bitrate;
+ u64 prev_time_stamp;
};
struct buf_queue {
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index 5161b7b..06891899 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -166,17 +166,22 @@
void update_nr_value(struct vcap_dev *dev)
{
struct nr_param *par;
+ uint32_t val = 0;
par = &dev->nr_param;
if (par->mode == NR_MANUAL) {
writel_relaxed(par->window << 24 | par->decay_ratio << 20,
VCAP_VP_NR_CONFIG);
- writel_relaxed(par->luma.max_blend_ratio << 24 |
+ if (par->threshold)
+ val = VP_NR_DYNAMIC_THRESHOLD;
+ writel_relaxed(val |
+ par->luma.max_blend_ratio << 24 |
par->luma.scale_diff_ratio << 12 |
par->luma.diff_limit_ratio << 8 |
par->luma.scale_motion_ratio << 4 |
par->luma.blend_limit_ratio << 0,
VCAP_VP_NR_LUMA_CONFIG);
- writel_relaxed(par->chroma.max_blend_ratio << 24 |
+ writel_relaxed(val |
+ par->chroma.max_blend_ratio << 24 |
par->chroma.scale_diff_ratio << 12 |
par->chroma.diff_limit_ratio << 8 |
par->chroma.scale_motion_ratio << 4 |
@@ -646,6 +651,9 @@
param->decay_ratio = BITS_VALUE(rc, 20, 3);
rc = readl_relaxed(VCAP_VP_NR_LUMA_CONFIG);
+ param->threshold = NR_THRESHOLD_STATIC;
+ if (BITS_VALUE(rc, 16, 1))
+ param->threshold = NR_THRESHOLD_DYNAMIC;
param->luma.max_blend_ratio = BITS_VALUE(rc, 24, 4);
param->luma.scale_diff_ratio = BITS_VALUE(rc, 12, 4);
param->luma.diff_limit_ratio = BITS_VALUE(rc, 8, 4);
@@ -662,6 +670,7 @@
void s_default_nr_val(struct nr_param *param)
{
+ param->threshold = NR_THRESHOLD_STATIC;
param->window = 10;
param->decay_ratio = 0;
param->luma.max_blend_ratio = 0;
diff --git a/drivers/media/video/vcap_vp.h b/drivers/media/video/vcap_vp.h
index 2ad5848..70b10c3 100644
--- a/drivers/media/video/vcap_vp.h
+++ b/drivers/media/video/vcap_vp.h
@@ -90,6 +90,7 @@
#define VP_NR_MAX_WINDOW 120
#define VP_NR_MAX_RATIO 16
+#define VP_NR_DYNAMIC_THRESHOLD 0x000F0000
#define BITS_MASK(start, num_of_bits) \
(((1 << (num_of_bits)) - 1) << (start))
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index fa7c116..d43b399 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -37,6 +37,14 @@
#define SITAR_I2C_MODE 0x01
#define CODEC_DT_MAX_PROP_SIZE 40
#define WCD9XXX_I2C_GSBI_SLAVE_ID "3-000d"
+#define WCD9XXX_I2C_TOP_SLAVE_ADDR 0x0d
+#define WCD9XXX_ANALOG_I2C_SLAVE_ADDR 0x77
+#define WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR 0x66
+#define WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR 0x55
+#define WCD9XXX_I2C_TOP_LEVEL 0
+#define WCD9XXX_I2C_ANALOG 1
+#define WCD9XXX_I2C_DIGITAL_1 2
+#define WCD9XXX_I2C_DIGITAL_2 3
struct wcd9xxx_i2c {
struct i2c_client *client;
@@ -644,10 +652,11 @@
kfree(wcd9xxx->supplies);
}
-int wcd9xxx_get_intf_type(void)
+enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void)
{
return wcd9xxx_intf;
}
+
EXPORT_SYMBOL_GPL(wcd9xxx_get_intf_type);
struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
@@ -768,100 +777,146 @@
return wcd9xxx_i2c_write_device(reg, src, bytes);
}
+static int wcd9xxx_i2c_get_client_index(struct i2c_client *client,
+ int *wcd9xx_index)
+{
+ int ret = 0;
+ switch (client->addr) {
+ case WCD9XXX_I2C_TOP_SLAVE_ADDR:
+ *wcd9xx_index = WCD9XXX_I2C_TOP_LEVEL;
+ break;
+ case WCD9XXX_ANALOG_I2C_SLAVE_ADDR:
+ *wcd9xx_index = WCD9XXX_I2C_ANALOG;
+ break;
+ case WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR:
+ *wcd9xx_index = WCD9XXX_I2C_DIGITAL_1;
+ break;
+ case WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR:
+ *wcd9xx_index = WCD9XXX_I2C_DIGITAL_2;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct wcd9xxx *wcd9xxx;
- struct wcd9xxx_pdata *pdata;
+ struct wcd9xxx *wcd9xxx = NULL;
+ struct wcd9xxx_pdata *pdata = NULL;
int val = 0;
int ret = 0;
int i2c_mode = 0;
- static int device_id;
+ int wcd9xx_index = 0;
struct device *dev;
- pr_info("%s\n", __func__);
+ pr_debug("%s: interface status %d\n", __func__, wcd9xxx_intf);
if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
dev_dbg(&client->dev, "%s:Codec is detected in slimbus mode\n",
- __func__);
+ __func__);
return -ENODEV;
- }
- if (device_id > 0) {
- wcd9xxx_modules[device_id++].client = client;
- dev_dbg(&client->dev, "%s:probe for other slaves\n"
- "devices of codec\n", __func__);
+ } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
+ ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
+ if (ret != 0)
+ dev_err(&client->dev, "%s: I2C set codec I2C\n"
+ "client failed\n", __func__);
+ else {
+ dev_err(&client->dev, "%s:probe for other slaves\n"
+ "devices of codec I2C slave Addr = %x\n",
+ __func__, client->addr);
+ wcd9xxx_modules[wcd9xx_index].client = client;
+ }
return ret;
- }
- dev = &client->dev;
- if (client->dev.of_node) {
- dev_dbg(&client->dev, "%s:Platform data from device tree\n",
- __func__);
- pdata = wcd9xxx_populate_dt_pdata(&client->dev);
- client->dev.platform_data = pdata;
- } else {
- dev_dbg(&client->dev, "%s:Platform data from board file\n",
- __func__);
- pdata = client->dev.platform_data;
- }
- wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
- if (wcd9xxx == NULL) {
- pr_err("%s: error, allocation failed\n", __func__);
- ret = -ENOMEM;
- goto fail;
- }
+ } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_PROBING) {
+ dev = &client->dev;
+ if (client->dev.of_node) {
+ dev_dbg(&client->dev, "%s:Platform data\n"
+ "from device tree\n", __func__);
+ pdata = wcd9xxx_populate_dt_pdata(&client->dev);
+ client->dev.platform_data = pdata;
+ } else {
+ dev_dbg(&client->dev, "%s:Platform data from\n"
+ "board file\n", __func__);
+ pdata = client->dev.platform_data;
+ }
+ wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
+ if (wcd9xxx == NULL) {
+ pr_err("%s: error, allocation failed\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
+ }
- if (!pdata) {
- dev_dbg(&client->dev, "no platform data?\n");
- ret = -EINVAL;
- goto fail;
- }
- if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
- dev_dbg(&client->dev, "can't talk I2C?\n");
- ret = -EIO;
- goto fail;
- }
- dev_set_drvdata(&client->dev, wcd9xxx);
- wcd9xxx->dev = &client->dev;
- wcd9xxx->reset_gpio = pdata->reset_gpio;
- ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
- if (ret) {
- pr_err("%s: Fail to enable Codec supplies\n", __func__);
- goto err_codec;
- }
+ if (!pdata) {
+ dev_dbg(&client->dev, "no platform data?\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+ if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_I2C) == 0) {
+ dev_dbg(&client->dev, "can't talk I2C?\n");
+ ret = -EIO;
+ goto fail;
+ }
+ dev_set_drvdata(&client->dev, wcd9xxx);
+ wcd9xxx->dev = &client->dev;
+ wcd9xxx->reset_gpio = pdata->reset_gpio;
+ if (client->dev.of_node)
+ wcd9xxx->mclk_rate = pdata->mclk_rate;
+ ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
+ if (ret) {
+ pr_err("%s: Fail to enable Codec supplies\n",
+ __func__);
+ goto err_codec;
+ }
- usleep_range(5, 5);
- ret = wcd9xxx_reset(wcd9xxx);
- if (ret) {
- pr_err("%s: Resetting Codec failed\n", __func__);
+ usleep_range(5, 5);
+ ret = wcd9xxx_reset(wcd9xxx);
+ if (ret) {
+ pr_err("%s: Resetting Codec failed\n", __func__);
goto err_supplies;
- }
- wcd9xxx_modules[device_id++].client = client;
+ }
- wcd9xxx->read_dev = wcd9xxx_i2c_read;
- wcd9xxx->write_dev = wcd9xxx_i2c_write;
- if (!wcd9xxx->dev->of_node) {
- wcd9xxx->irq = pdata->irq;
- wcd9xxx->irq_base = pdata->irq_base;
- }
+ ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
+ if (ret != 0) {
+ pr_err("%s:Set codec I2C client failed\n", __func__);
+ goto err_supplies;
+ }
- ret = wcd9xxx_device_init(wcd9xxx);
- if (ret) {
- pr_err("%s: error, initializing device failed\n", __func__);
- goto err_device_init;
- }
+ wcd9xxx_modules[wcd9xx_index].client = client;
+ wcd9xxx->read_dev = wcd9xxx_i2c_read;
+ wcd9xxx->write_dev = wcd9xxx_i2c_write;
+ if (!wcd9xxx->dev->of_node) {
+ wcd9xxx->irq = pdata->irq;
+ wcd9xxx->irq_base = pdata->irq_base;
+ }
- if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
- i2c_mode = TABLA_I2C_MODE;
- else if (wcd9xxx->idbyte[0] == 0x0)
- i2c_mode = SITAR_I2C_MODE;
+ ret = wcd9xxx_device_init(wcd9xxx);
+ if (ret) {
+ pr_err("%s: error, initializing device failed\n",
+ __func__);
+ goto err_device_init;
+ }
- ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
+ if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
+ i2c_mode = TABLA_I2C_MODE;
+ else if (wcd9xxx->idbyte[0] == 0x0)
+ i2c_mode = SITAR_I2C_MODE;
- if ((ret < 0) || (val != i2c_mode))
- pr_err("failed to read the wcd9xxx status ret = %d\n", ret);
+ ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
+
+ if ((ret < 0) || (val != i2c_mode))
+ pr_err("failed to read the wcd9xxx status ret = %d\n",
+ ret);
wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
- return ret;
+ return ret;
+ } else
+ pr_err("%s: I2C probe in wrong state\n", __func__);
+
+
err_device_init:
wcd9xxx_free_reset(wcd9xxx);
err_supplies:
@@ -1087,6 +1142,7 @@
int ret, i;
char **codec_supplies;
u32 num_of_supplies = 0;
+ u32 mclk_rate = 0;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
@@ -1130,6 +1186,19 @@
goto err;
}
dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
+ ret = of_property_read_u32(dev->of_node,
+ "qcom,cdc-mclk-clk-rate",
+ &mclk_rate);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in\n"
+ "node %s failed",
+ "qcom,cdc-mclk-clk-rate",
+ dev->of_node->full_name);
+ devm_kfree(dev, pdata);
+ ret = -EINVAL;
+ goto err;
+ }
+ pdata->mclk_rate = mclk_rate;
return pdata;
err:
devm_kfree(dev, pdata);
@@ -1162,6 +1231,11 @@
struct wcd9xxx_pdata *pdata;
int ret = 0;
+ if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
+ dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
+ __func__);
+ return -ENODEV;
+ }
if (slim->dev.of_node) {
dev_info(&slim->dev, "Platform data from device tree\n");
pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
@@ -1201,6 +1275,7 @@
slim_set_clientdata(slim, wcd9xxx);
wcd9xxx->reset_gpio = pdata->reset_gpio;
wcd9xxx->dev = &slim->dev;
+ wcd9xxx->mclk_rate = pdata->mclk_rate;
ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
if (ret)
@@ -1477,11 +1552,6 @@
.suspend = wcd9xxx_slim_suspend,
};
-#define WCD9XXX_I2C_TOP_LEVEL 0
-#define WCD9XXX_I2C_ANALOG 1
-#define WCD9XXX_I2C_DIGITAL_1 2
-#define WCD9XXX_I2C_DIGITAL_2 3
-
static struct i2c_device_id wcd9xxx_id_table[] = {
{"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
{"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
@@ -1528,6 +1598,8 @@
{
int ret1, ret2, ret3, ret4, ret5, ret6, ret7;
+ wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_PROBING;
+
ret1 = slim_driver_register(&tabla_slim_driver);
if (ret1 != 0)
pr_err("Failed to register tabla SB driver: %d\n", ret1);
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 8f97531..6b067e7 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -398,8 +398,8 @@
pr_err("%s: src pipe connection failure\n", __func__);
return ret;
}
+ connection->src_enabled = 1;
}
- connection->src_enabled = 1;
if (dst_pipe_idx) {
/* open Peripheral -> USB pipe */
@@ -409,8 +409,8 @@
pr_err("%s: dst pipe connection failure\n", __func__);
return ret;
}
+ connection->dst_enabled = 1;
}
- connection->dst_enabled = 1;
return 0;
}
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 05b47cc..a8d52b5 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1800,7 +1800,7 @@
pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
if (fcc_uah - unusable_charge_uah <= 0) {
- pr_warn("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
+ pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
fcc_uah, unusable_charge_uah);
soc = 0;
} else {
@@ -1843,13 +1843,13 @@
soc = 100;
if (soc < 0) {
- pr_err("bad rem_usb_chg = %d rem_chg %d,"
+ pr_debug("bad rem_usb_chg = %d rem_chg %d,"
"cc_uah %d, unusb_chg %d\n",
remaining_usable_charge_uah,
remaining_charge_uah,
cc_uah, unusable_charge_uah);
- pr_err("for bad rem_usb_chg last_ocv_uv = %d"
+ pr_debug("for bad rem_usb_chg last_ocv_uv = %d"
"chargecycles = %d, batt_temp = %d"
"fcc = %d soc =%d\n",
chip->last_ocv_uv, chargecycles, batt_temp,
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index a51f877..87e41e6 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -312,6 +312,17 @@
static struct pm8921_chg_chip *the_chip;
+static int pm_chg_write(struct pm8921_chg_chip *chip, u16 addr, u8 reg)
+{
+ int rc;
+
+ rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
+ if (rc)
+ pr_err("pm_chg_write failed: addr=%03X, rc=%d\n", addr, rc);
+
+ return rc;
+}
+
static int pm_chg_masked_write(struct pm8921_chg_chip *chip, u16 addr,
u8 mask, u8 val)
{
@@ -325,9 +336,9 @@
}
reg &= ~mask;
reg |= val & mask;
- rc = pm8xxx_writeb(chip->dev->parent, addr, reg);
+ rc = pm_chg_write(chip, addr, reg);
if (rc) {
- pr_err("pm8xxx_writeb failed: addr=%03X, rc=%d\n", addr, rc);
+ pr_err("pm_chg_write failed: addr=%03X, rc=%d\n", addr, rc);
return rc;
}
return 0;
@@ -364,14 +375,14 @@
int err, ret = 0;
temp = CAPTURE_FSM_STATE_CMD;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return err;
}
temp = READ_BANK_7;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return err;
@@ -386,7 +397,7 @@
ret = temp & 0xF;
temp = READ_BANK_4;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return err;
@@ -409,7 +420,7 @@
int err;
temp = READ_BANK_6;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return err;
@@ -491,7 +502,7 @@
}
pr_debug("voltage=%d setting %02x\n", voltage, temp);
- return pm8xxx_writeb(chip->dev->parent, CHG_VDD_MAX, temp);
+ return pm_chg_write(chip, CHG_VDD_MAX, temp);
}
static int pm_chg_vddmax_get(struct pm8921_chg_chip *chip, int *voltage)
@@ -789,15 +800,18 @@
{1600, 0xF},
};
-#define REG_SBI_CONFIG 0x04F
-#define PAGE3_ENABLE_MASK 0x6
-#define USB_OVP_TRIM_MASK 0x3F
-#define USB_OVP_TRIM_MIN 0x00
+#define REG_SBI_CONFIG 0x04F
+#define PAGE3_ENABLE_MASK 0x6
+#define USB_OVP_TRIM_MASK 0x3F
+#define USB_OVP_TRIM_PM8917_MASK 0x7F
+#define USB_OVP_TRIM_MIN 0x00
#define REG_USB_OVP_TRIM_ORIG_LSB 0x10A
#define REG_USB_OVP_TRIM_ORIG_MSB 0x09C
+#define REG_USB_OVP_TRIM_PM8917 0x2B5
+#define REG_USB_OVP_TRIM_PM8917_BIT BIT(0)
static int pm_chg_usb_trim(struct pm8921_chg_chip *chip, int index)
{
- u8 temp, sbi_config, msb, lsb;
+ u8 temp, sbi_config, msb, lsb, mask;
s8 trim;
int rc = 0;
static u8 usb_trim_reg_orig = 0xFF;
@@ -824,6 +838,19 @@
msb = msb >> 5;
lsb = lsb >> 5;
usb_trim_reg_orig = msb << 3 | lsb;
+
+ if (pm8xxx_get_version(chip->dev->parent)
+ == PM8XXX_VERSION_8917) {
+ rc = pm8xxx_readb(chip->dev->parent,
+ REG_USB_OVP_TRIM_PM8917, &msb);
+ if (rc) {
+ pr_err("error = %d reading config reg\n", rc);
+ return rc;
+ }
+
+ msb = msb & REG_USB_OVP_TRIM_PM8917_BIT;
+ usb_trim_reg_orig |= msb << 6;
+ }
}
/* use the original trim value */
@@ -843,19 +870,24 @@
}
temp = sbi_config | PAGE3_ENABLE_MASK;
- rc = pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, temp);
+ rc = pm_chg_write(chip, REG_SBI_CONFIG, temp);
if (rc) {
pr_err("error = %d writing sbi config reg\n", rc);
return rc;
}
- rc = pm_chg_masked_write(chip, USB_OVP_TRIM, USB_OVP_TRIM_MASK, trim);
+ mask = USB_OVP_TRIM_MASK;
+
+ if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
+ mask = USB_OVP_TRIM_PM8917_MASK;
+
+ rc = pm_chg_masked_write(chip, USB_OVP_TRIM, mask, trim);
if (rc) {
pr_err("error = %d writing USB_OVP_TRIM\n", rc);
return rc;
}
- rc = pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, sbi_config);
+ rc = pm_chg_write(chip, REG_SBI_CONFIG, sbi_config);
if (rc) {
pr_err("error = %d writing sbi config reg\n", rc);
return rc;
@@ -1343,7 +1375,7 @@
return 0;
/* enable usbin valid comparator and remove force usb ovp fet off */
- rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, 0xB2);
+ rc = pm_chg_write(chip, USB_OVP_TEST, 0xB2);
if (rc < 0) {
pr_err("Failed to write 0xB2 to USB_OVP_TEST rc = %d\n", rc);
return rc;
@@ -1362,7 +1394,7 @@
return 0;
/* disable usbin valid comparator and force usb ovp fet off */
- rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, 0xB3);
+ rc = pm_chg_write(chip, USB_OVP_TEST, 0xB3);
if (rc < 0) {
pr_err("Failed to write 0xB3 to USB_OVP_TEST rc = %d\n", rc);
return rc;
@@ -1945,7 +1977,7 @@
if (disable) {
pr_warn("Disabling input current limit!\n");
- return pm8xxx_writeb(the_chip->dev->parent,
+ return pm_chg_write(the_chip,
CHG_BUCK_CTRL_TEST3, 0xF2);
}
return 0;
@@ -2319,7 +2351,7 @@
u8 temp;
int rc;
- rc = pm8xxx_writeb(chip->dev->parent, ovptestreg, 0x30);
+ rc = pm_chg_write(chip, ovptestreg, 0x30);
if (rc) {
pr_err("Failed to write 0x30 to OVP_TEST rc = %d\n", rc);
return;
@@ -2331,7 +2363,7 @@
}
/* set ovp fet disable bit and the write bit */
temp |= 0x81;
- rc = pm8xxx_writeb(chip->dev->parent, ovptestreg, temp);
+ rc = pm_chg_write(chip, ovptestreg, temp);
if (rc) {
pr_err("Failed to write 0x%x OVP_TEST rc=%d\n", temp, rc);
return;
@@ -2398,7 +2430,7 @@
u8 temp;
int rc;
- rc = pm8xxx_writeb(chip->dev->parent, ovptestreg, 0x30);
+ rc = pm_chg_write(chip, ovptestreg, 0x30);
if (rc) {
pr_err("Failed to write 0x30 to OVP_TEST rc = %d\n", rc);
return;
@@ -2411,7 +2443,7 @@
/* unset ovp fet disable bit and set the write bit */
temp &= 0xFE;
temp |= 0x80;
- rc = pm8xxx_writeb(chip->dev->parent, ovptestreg, temp);
+ rc = pm_chg_write(chip, ovptestreg, temp);
if (rc) {
pr_err("Failed to write 0x%x to OVP_TEST rc = %d\n",
temp, rc);
@@ -2716,7 +2748,7 @@
u8 temp;
int rc;
- rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x40);
+ rc = pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0x40);
if (rc) {
pr_err("Failed to write 0x70 to CTRL_TEST3 rc = %d\n", rc);
return;
@@ -2732,7 +2764,7 @@
temp |= (u8)pon_time_ns;
/* write enable bank 4 */
temp |= 0x80;
- rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
+ rc = pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, temp);
if (rc) {
pr_err("Failed to write 0x%x to CTRL_TEST3 rc=%d\n", temp, rc);
return;
@@ -3434,7 +3466,7 @@
if (flag)
val |= 0x01;
- rc = pm8xxx_writeb(chip->dev->parent, COMPARATOR_OVERRIDE, val);
+ rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
if (rc < 0)
pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
@@ -3452,7 +3484,7 @@
if (flag)
val |= 0x01;
- rc = pm8xxx_writeb(chip->dev->parent, COMPARATOR_OVERRIDE, val);
+ rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
if (rc < 0)
pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
@@ -3467,7 +3499,7 @@
u8 val;
val = COMP_OVERRIDE_HOT_BANK << 2;
- rc = pm8xxx_writeb(chip->dev->parent, COMPARATOR_OVERRIDE, val);
+ rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
if (rc < 0) {
pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
goto cold_init;
@@ -3487,7 +3519,7 @@
cold_init:
val = COMP_OVERRIDE_COLD_BANK << 2;
- rc = pm8xxx_writeb(chip->dev->parent, COMPARATOR_OVERRIDE, val);
+ rc = pm_chg_write(chip, COMPARATOR_OVERRIDE, val);
if (rc < 0) {
pr_err("Could not write 0x%x to override rc = %d\n", val, rc);
return;
@@ -3941,28 +3973,28 @@
u8 temp;
temp = 0xD1;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return;
}
temp = 0xD3;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return;
}
temp = 0xD1;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return;
}
temp = 0xD5;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return;
@@ -3971,14 +4003,14 @@
udelay(183);
temp = 0xD1;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return;
}
temp = 0xD0;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return;
@@ -3986,14 +4018,14 @@
udelay(32);
temp = 0xD1;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return;
}
temp = 0xD3;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return;
@@ -4006,14 +4038,14 @@
u8 temp;
temp = 0xD1;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return;
}
temp = 0xD0;
- err = pm8xxx_writeb(chip->dev->parent, CHG_TEST, temp);
+ err = pm_chg_write(chip, CHG_TEST, temp);
if (err) {
pr_err("Error %d writing %d to addr %d\n", err, temp, CHG_TEST);
return;
@@ -4180,10 +4212,10 @@
}
/* switch to a 3.2Mhz for the buck */
if (pm8xxx_get_revision(chip->dev->parent) >= PM8XXX_REVISION_8038_1p0)
- rc = pm8xxx_writeb(chip->dev->parent,
+ rc = pm_chg_write(chip,
CHG_BUCK_CLOCK_CTRL_8038, 0x15);
else
- rc = pm8xxx_writeb(chip->dev->parent,
+ rc = pm_chg_write(chip,
CHG_BUCK_CLOCK_CTRL, 0x15);
if (rc) {
@@ -4256,10 +4288,10 @@
}
/* Check if die 3.0.1 is present */
if (subrev == 0x1)
- pm8xxx_writeb(chip->dev->parent,
+ pm_chg_write(chip,
CHG_BUCK_CTRL_TEST3, 0xA4);
else
- pm8xxx_writeb(chip->dev->parent,
+ pm_chg_write(chip,
CHG_BUCK_CTRL_TEST3, 0xAC);
}
@@ -4276,10 +4308,10 @@
}
}
- pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xD9);
+ pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0xD9);
/* Disable EOC FSM processing */
- pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x91);
+ pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0x91);
rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
VREF_BATT_THERM_FORCE_ON);
@@ -4360,9 +4392,9 @@
u8 temp;
temp = (u8) val;
- ret = pm8xxx_writeb(the_chip->dev->parent, addr, temp);
+ ret = pm_chg_write(the_chip, addr, temp);
if (ret) {
- pr_err("pm8xxx_writeb to %x value =%d errored = %d\n",
+ pr_err("pm_chg_write to %x value =%d errored = %d\n",
addr, temp, ret);
return -EAGAIN;
}
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 0a072b1..81ffa3a 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -73,6 +73,8 @@
#define IAVG_STORAGE_REG 0xB1
#define SOC_STORAGE_REG 0xB2
#define BMS1_BMS_DATA_REG_3 0xB3
+/* IADC Channel Select */
+#define IADC1_BMS_ADC_CH_SEL_CTL 0x48
/* Configuration for saving of shutdown soc/iavg */
#define IGNORE_SOC_TEMP_DECIDEG 50
@@ -105,6 +107,7 @@
struct power_supply *batt_psy;
struct spmi_device *spmi;
u16 base;
+ u16 iadc_base;
u8 revision1;
u8 revision2;
@@ -134,6 +137,8 @@
struct mutex last_ocv_uv_mutex;
struct mutex soc_invalidation_mutex;
+ bool use_external_rsense;
+
unsigned int start_percent;
unsigned int end_percent;
bool ignore_shutdown_soc;
@@ -1067,11 +1072,8 @@
return 0;
}
-static int get_simultaneous_batt_v_and_i(
- struct qpnp_bms_chip *chip,
- int *ibat_ua, int *vbat_uv)
+static bool is_batfet_open(struct qpnp_bms_chip *chip)
{
- int rc;
union power_supply_propval ret = {0,};
if (chip->batt_psy == NULL)
@@ -1080,12 +1082,20 @@
/* if battery has been registered, use the status property */
chip->batt_psy->get_property(chip->batt_psy,
POWER_SUPPLY_PROP_STATUS, &ret);
- } else {
- /* default to using separate vbat/ibat if unregistered */
- ret.intval = POWER_SUPPLY_STATUS_FULL;
+ return ret.intval == POWER_SUPPLY_STATUS_FULL;
}
- if (ret.intval == POWER_SUPPLY_STATUS_FULL) {
+ /* Default to true if the battery power supply is not registered. */
+ pr_debug("battery power supply is not registered\n");
+ return true;
+}
+
+static int get_simultaneous_batt_v_and_i(struct qpnp_bms_chip *chip,
+ int *ibat_ua, int *vbat_uv)
+{
+ int rc;
+
+ if (is_batfet_open(chip)) {
pr_debug("batfet is open using separate vbat and ibat meas\n");
rc = get_battery_voltage(vbat_uv);
if (rc < 0) {
@@ -1197,7 +1207,7 @@
(s64)params->fcc_uah - params->uuc_uah);
soc_est = bound_soc(soc_est);
- if (ibat_ua < 0) {
+ if (ibat_ua < 0 && !is_batfet_open(chip)) {
soc = charging_adjustments(chip, params, soc, vbat_uv, ibat_ua,
batt_temp);
goto out;
@@ -1335,7 +1345,7 @@
pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
if (params.fcc_uah - params.uuc_uah <= 0) {
- pr_warn("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
+ pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
params.fcc_uah,
params.uuc_uah);
soc = 0;
@@ -1369,12 +1379,12 @@
soc = 100;
if (soc < 0) {
- pr_err("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
+ pr_debug("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
remaining_usable_charge_uah,
params.ocv_charge_uah,
params.cc_uah, params.uuc_uah);
- pr_err("for bad rem_usb_chg last_ocv_uv = %d batt_temp = %d fcc = %d soc =%d\n",
+ pr_debug("for bad rem_usb_chg last_ocv_uv = %d batt_temp = %d fcc = %d soc =%d\n",
chip->last_ocv_uv, batt_temp,
params.fcc_uah, soc);
soc = 0;
@@ -1659,7 +1669,8 @@
}
/* last_soc < soc ... scale and catch up */
- if (chip->last_soc != -EINVAL && chip->last_soc < soc && soc != 100)
+ if (chip->last_soc != -EINVAL && chip->last_soc < soc
+ && soc != 100 && chip->catch_up_time_us != 0)
soc = scale_soc_while_chg(chip, delta_time_us,
soc, chip->last_soc);
@@ -1976,11 +1987,104 @@
chip->first_time_calc_uuc = 1;
}
-static int __devinit
-qpnp_bms_probe(struct spmi_device *spmi)
+#define REG_OFFSET_PERP_TYPE 0x04
+#define REG_OFFSET_PERP_SUBTYPE 0x05
+#define BMS_BMS_TYPE 0xD
+#define BMS_BMS_SUBTYPE 0x1
+#define BMS_IADC_TYPE 0x8
+#define BMS_IADC_SUBTYPE 0x3
+
+static int register_spmi(struct qpnp_bms_chip *chip, struct spmi_device *spmi)
+{
+ struct spmi_resource *spmi_resource;
+ struct resource *resource;
+ int rc;
+ u8 type, subtype;
+
+ chip->dev = &(spmi->dev);
+ chip->spmi = spmi;
+
+ spmi_for_each_container_dev(spmi_resource, spmi) {
+ if (!spmi_resource) {
+ pr_err("qpnp_bms: spmi resource absent\n");
+ return -ENXIO;
+ }
+
+ resource = spmi_get_resource(spmi, spmi_resource,
+ IORESOURCE_MEM, 0);
+ if (!(resource && resource->start)) {
+ pr_err("node %s IO resource absent!\n",
+ spmi->dev.of_node->full_name);
+ return -ENXIO;
+ }
+
+ rc = qpnp_read_wrapper(chip, &type,
+ resource->start + REG_OFFSET_PERP_TYPE, 1);
+ if (rc) {
+ pr_err("Peripheral type read failed rc=%d\n", rc);
+ return rc;
+ }
+ rc = qpnp_read_wrapper(chip, &subtype,
+ resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
+ if (rc) {
+ pr_err("Peripheral subtype read failed rc=%d\n", rc);
+ return rc;
+ }
+
+ if (type == BMS_BMS_TYPE && subtype == BMS_BMS_SUBTYPE) {
+ chip->base = resource->start;
+ } else if (type == BMS_IADC_TYPE
+ && subtype == BMS_IADC_SUBTYPE) {
+ chip->iadc_base = resource->start;
+ } else {
+ pr_err("Invalid peripheral start=0x%x type=0x%x, subtype=0x%x\n",
+ resource->start, type, subtype);
+ }
+ }
+
+ if (chip->base == 0) {
+ dev_err(&spmi->dev, "BMS peripheral was not registered\n");
+ return -EINVAL;
+ }
+ if (chip->iadc_base == 0) {
+ dev_err(&spmi->dev, "BMS_IADC peripheral was not registered\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define ADC_CH_SEL_MASK 0x7
+static int read_iadc_channel_select(struct qpnp_bms_chip *chip)
+{
+ u8 iadc_channel_select;
+ int rc;
+
+ rc = qpnp_read_wrapper(chip, &iadc_channel_select,
+ chip->iadc_base + IADC1_BMS_ADC_CH_SEL_CTL, 1);
+ if (rc) {
+ pr_err("Error reading bms_iadc channel register %d\n", rc);
+ return rc;
+ }
+
+ iadc_channel_select &= ADC_CH_SEL_MASK;
+ if (iadc_channel_select == INTERNAL_RSENSE) {
+ pr_debug("Internal rsense used\n");
+ chip->use_external_rsense = false;
+ } else if (iadc_channel_select == EXTERNAL_RSENSE) {
+ pr_debug("External rsense used\n");
+ chip->use_external_rsense = true;
+ } else {
+ pr_err("IADC1_BMS_IADC configured incorrectly. Selected channel = %d\n",
+ iadc_channel_select);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
{
struct qpnp_bms_chip *chip;
- struct resource *bms_resource;
int rc, vbatt;
chip = kzalloc(sizeof *chip, GFP_KERNEL);
@@ -1990,19 +2094,23 @@
return -ENOMEM;
}
- chip->dev = &(spmi->dev);
- chip->spmi = spmi;
-
- mutex_init(&chip->bms_output_lock);
- mutex_init(&chip->last_ocv_uv_mutex);
- mutex_init(&chip->soc_invalidation_mutex);
-
- bms_resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
- if (!bms_resource) {
- dev_err(&spmi->dev, "Unable to get BMS base address\n");
- return -ENXIO;
+ rc = qpnp_vadc_is_ready();
+ if (rc) {
+ pr_info("vadc not ready: %d, deferring probe\n", rc);
+ goto error_read;
}
- chip->base = bms_resource->start;
+
+ rc = qpnp_iadc_is_ready();
+ if (rc) {
+ pr_info("iadc not ready: %d, deferring probe\n", rc);
+ goto error_read;
+ }
+
+ rc = register_spmi(chip, spmi);
+ if (rc) {
+ pr_err("error registering spmi resource %d\n", rc);
+ goto error_resource;
+ }
rc = qpnp_read_wrapper(chip, &chip->revision1,
chip->base + BMS1_REVISION1, 1);
@@ -2019,21 +2127,9 @@
}
pr_debug("BMS version: %hhu.%hhu\n", chip->revision2, chip->revision1);
- rc = qpnp_vadc_is_ready();
+ rc = read_iadc_channel_select(chip);
if (rc) {
- pr_info("vadc not ready: %d, deferring probe\n", rc);
- goto error_read;
- }
-
- rc = qpnp_iadc_is_ready();
- if (rc) {
- pr_info("iadc not ready: %d, deferring probe\n", rc);
- goto error_read;
- }
-
- rc = set_battery_data(chip);
- if (rc) {
- pr_err("Bad battery data %d\n", rc);
+ pr_err("Unable to get iadc selected channel = %d\n", rc);
goto error_read;
}
@@ -2043,8 +2139,18 @@
goto error_read;
}
+ rc = set_battery_data(chip);
+ if (rc) {
+ pr_err("Bad battery data %d\n", rc);
+ goto error_read;
+ }
+
bms_initialize_constants(chip);
+ mutex_init(&chip->bms_output_lock);
+ mutex_init(&chip->last_ocv_uv_mutex);
+ mutex_init(&chip->soc_invalidation_mutex);
+
INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
calculate_soc_work);
@@ -2086,6 +2192,7 @@
unregister_dc:
power_supply_unregister(&chip->bms_psy);
dev_set_drvdata(&spmi->dev, NULL);
+error_resource:
error_read:
kfree(chip);
return rc;
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index e756a0d..289293a 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -78,7 +78,7 @@
* the recovery of the remote processor.
*/
static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev,
- unsigned long iova, int flags)
+ unsigned long iova, int flags, void *token)
{
dev_err(dev, "iommu fault: da 0x%lx flags 0x%x\n", iova, flags);
@@ -117,7 +117,7 @@
return -ENOMEM;
}
- iommu_set_fault_handler(domain, rproc_iommu_fault);
+ iommu_set_fault_handler(domain, rproc_iommu_fault, rproc);
ret = iommu_attach_device(domain, dev);
if (ret) {
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index dba02f8..6135e71 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -127,13 +127,72 @@
}
}
+/**
+ * msm_spi_clk_max_rate: finds the nearest lower rate for a clk
+ * @clk the clock for which to find nearest lower rate
+ * @rate clock frequency in Hz
+ * @return nearest lower rate or negative error value
+ *
+ * Public clock API extends clk_round_rate which is a ceiling function. This
+ * function is a floor function implemented as a binary search using the
+ * ceiling function.
+ */
+static long msm_spi_clk_max_rate(struct clk *clk, unsigned long rate)
+{
+ long lowest_available, nearest_low, step_size, cur;
+ long step_direction = -1;
+ long guess = rate;
+ int max_steps = 10;
+
+ cur = clk_round_rate(clk, rate);
+ if (cur == rate)
+ return rate;
+
+ /* if we got here then: cur > rate */
+ lowest_available = clk_round_rate(clk, 0);
+ if (lowest_available > rate)
+ return -EINVAL;
+
+ step_size = (rate - lowest_available) >> 1;
+ nearest_low = lowest_available;
+
+ while (max_steps-- && step_size) {
+ guess += step_size * step_direction;
+
+ cur = clk_round_rate(clk, guess);
+
+ if ((cur < rate) && (cur > nearest_low))
+ nearest_low = cur;
+
+ /*
+ * if we stepped too far, then start stepping in the other
+ * direction with half the step size
+ */
+ if (((cur > rate) && (step_direction > 0))
+ || ((cur < rate) && (step_direction < 0))) {
+ step_direction = -step_direction;
+ step_size >>= 1;
+ }
+ }
+ return nearest_low;
+}
+
static void msm_spi_clock_set(struct msm_spi *dd, int speed)
{
+ long rate;
int rc;
- rc = clk_set_rate(dd->clk, speed);
+ rate = msm_spi_clk_max_rate(dd->clk, speed);
+ if (rate < 0) {
+ dev_err(dd->dev,
+ "%s: no match found for requested clock frequency:%d",
+ __func__, speed);
+ return;
+ }
+
+ rc = clk_set_rate(dd->clk, rate);
if (!rc)
- dd->clock_speed = speed;
+ dd->clock_speed = rate;
}
static int msm_spi_calculate_size(int *fifo_size,
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index 85240ef..65b4890 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -216,7 +216,7 @@
.bcdMbbVersion = cpu_to_le16(0x0100),
.wMaxControlMessage = cpu_to_le16(0x1000),
- .bNumberFilters = 0x10,
+ .bNumberFilters = 0x20,
.bMaxFilterSize = 0x80,
.wMaxSegmentSize = cpu_to_le16(0xfe0),
.bmNetworkCapabilities = 0x20,
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 79aac27..32fc79e 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -50,9 +50,6 @@
struct list_head cpkt_resp_q;
atomic_t notify_count;
unsigned long cpkts_len;
-
- /* IPA / RmNet Bridge support*/
- struct usb_bam_connect_ipa_params ipa_params;
};
#define NR_RMNET_PORTS 3
@@ -433,18 +430,9 @@
switch (dxport) {
case USB_GADGET_XPORT_BAM:
case USB_GADGET_XPORT_BAM2BAM:
- ret = gbam_connect(&dev->port, port_num,
- dxport, port_num, NULL);
- if (ret) {
- pr_err("%s: gbam_connect failed: err:%d\n",
- __func__, ret);
- gsmd_ctrl_disconnect(&dev->port, port_num);
- return ret;
- }
- break;
case USB_GADGET_XPORT_BAM2BAM_IPA:
ret = gbam_connect(&dev->port, port_num,
- dxport, port_num, &(dev->ipa_params));
+ dxport, port_num);
if (ret) {
pr_err("%s: gbam_connect failed: err:%d\n",
__func__, ret);
@@ -514,11 +502,8 @@
switch (dxport) {
case USB_GADGET_XPORT_BAM:
case USB_GADGET_XPORT_BAM2BAM:
- gbam_disconnect(&dev->port, port_num, dxport, NULL);
- break;
case USB_GADGET_XPORT_BAM2BAM_IPA:
- gbam_disconnect(&dev->port, port_num, dxport,
- &(dev->ipa_params));
+ gbam_disconnect(&dev->port, port_num, dxport);
break;
case USB_GADGET_XPORT_HSIC:
ghsic_data_disconnect(&dev->port, port_num);
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 02f044e..288611d 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -840,7 +840,6 @@
rndis_deregister(rndis->config);
rndis_exit();
- rndis_string_defs[0].id = 0;
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 7f3713f..aa93a7d 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -102,7 +102,7 @@
u32 dst_pipe_idx;
u8 connection_idx;
enum transport_type trans;
- struct usb_bam_connect_ipa_params *ipa_params;
+ struct usb_bam_connect_ipa_params ipa_params;
/* stats */
unsigned int pending_with_bam;
@@ -649,7 +649,7 @@
int ret;
if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
- ret = usb_bam_disconnect_ipa(d->connection_idx, d->ipa_params);
+ ret = usb_bam_disconnect_ipa(d->connection_idx, &d->ipa_params);
if (ret)
pr_err("%s: usb_bam_disconnect_ipa failed: err:%d\n",
__func__, ret);
@@ -706,29 +706,29 @@
return;
}
} else if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
- d->ipa_params->client = IPA_CLIENT_USB_CONS;
- d->ipa_params->dir = PEER_PERIPHERAL_TO_USB;
- ret = usb_bam_connect_ipa(d->ipa_params);
+ d->ipa_params.client = IPA_CLIENT_USB_CONS;
+ d->ipa_params.dir = PEER_PERIPHERAL_TO_USB;
+ ret = usb_bam_connect_ipa(&d->ipa_params);
if (ret) {
pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
__func__, ret);
return;
}
- d->ipa_params->client = IPA_CLIENT_USB_PROD;
- d->ipa_params->dir = USB_TO_PEER_PERIPHERAL;
+ d->ipa_params.client = IPA_CLIENT_USB_PROD;
+ d->ipa_params.dir = USB_TO_PEER_PERIPHERAL;
/* Currently only DMA mode is supported */
- d->ipa_params->ipa_ep_cfg.mode.mode = IPA_DMA;
- d->ipa_params->ipa_ep_cfg.mode.dst =
+ d->ipa_params.ipa_ep_cfg.mode.mode = IPA_DMA;
+ d->ipa_params.ipa_ep_cfg.mode.dst =
IPA_CLIENT_A2_TETHERED_CONS;
- ret = usb_bam_connect_ipa(d->ipa_params);
+ ret = usb_bam_connect_ipa(&d->ipa_params);
if (ret) {
pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
__func__, ret);
return;
}
- rmnet_bridge_connect(d->ipa_params->prod_clnt_hdl,
- d->ipa_params->cons_clnt_hdl, 0);
+ rmnet_bridge_connect(d->ipa_params.prod_clnt_hdl,
+ d->ipa_params.cons_clnt_hdl, 0);
}
d->rx_req = usb_ep_alloc_request(port->port_usb->out, GFP_KERNEL);
@@ -1037,8 +1037,7 @@
static void gam_debugfs_init(void) { }
#endif
-void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans,
- struct usb_bam_connect_ipa_params *ipa_params)
+void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans)
{
struct gbam_port *port;
unsigned long flags;
@@ -1096,8 +1095,7 @@
}
int gbam_connect(struct grmnet *gr, u8 port_num,
- enum transport_type trans, u8 connection_idx,
- struct usb_bam_connect_ipa_params *ipa_params)
+ enum transport_type trans, u8 connection_idx)
{
struct gbam_port *port;
struct bam_ch_info *d;
@@ -1166,11 +1164,10 @@
port->gr = gr;
d->connection_idx = connection_idx;
} else if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
- d->ipa_params = ipa_params;
port->gr = gr;
- d->ipa_params->src_pipe = &(d->src_pipe_idx);
- d->ipa_params->dst_pipe = &(d->dst_pipe_idx);
- d->ipa_params->idx = connection_idx;
+ d->ipa_params.src_pipe = &(d->src_pipe_idx);
+ d->ipa_params.dst_pipe = &(d->dst_pipe_idx);
+ d->ipa_params.idx = connection_idx;
}
d->trans = trans;
diff --git a/drivers/usb/gadget/u_rmnet.h b/drivers/usb/gadget/u_rmnet.h
index a3d42fa..0f7c4fb 100644
--- a/drivers/usb/gadget/u_rmnet.h
+++ b/drivers/usb/gadget/u_rmnet.h
@@ -48,10 +48,8 @@
int gbam_setup(unsigned int no_bam_port, unsigned int no_bam2bam_port);
int gbam_connect(struct grmnet *gr, u8 port_num,
- enum transport_type trans, u8 connection_idx,
- struct usb_bam_connect_ipa_params *ipa_params);
-void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans,
- struct usb_bam_connect_ipa_params *ipa_params);
+ enum transport_type trans, u8 connection_idx);
+void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans);
void gbam_suspend(struct grmnet *gr, u8 port_num, enum transport_type trans);
void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans);
int gsmd_ctrl_connect(struct grmnet *gr, int port_num);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index 8db38d6..50750e1 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -16,7 +16,7 @@
#include "mdss_hdmi_edid.h"
#define DBC_START_OFFSET 4
-#define HDMI_VSDB_3D_DATA_OFFSET(vsd) \
+#define HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd) \
(!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13))
struct hdmi_edid_sink_data {
@@ -180,6 +180,10 @@
{HDMI_VFRMT_1920x1080i120_16_9, 1920, 1080, true, 2200, 280, 1125,
22, 67500, 120000, 148500, 120000, false},
+ /* All 2560 H Active */
+ {HDMI_VFRMT_2560x1600p60_16_9, 2560, 1600, false, 2720, 160, 1646,
+ 46, 98700, 60000, 268500, 60000, false},
+
/* All 2880 H Active */
{HDMI_VFRMT_2880x576i50_4_3, 2880, 576, true, 3456, 576, 625, 24,
15625, 50000, 54000, 50000, true},
@@ -437,7 +441,7 @@
u8 block_len = in_buf[offset] & 0x1F;
if ((in_buf[offset] >> 5) == type) {
*len = block_len;
- DEV_DBG("%s: EDID: block=%d found @ %d w/ length=%d\n",
+ DEV_DBG("%s: EDID: block=%d found @ 0x%x w/ len=%d\n",
__func__, type, offset, block_len);
return in_buf + offset;
@@ -533,8 +537,8 @@
return;
}
- offset = HDMI_VSDB_3D_DATA_OFFSET(vsd);
- DEV_DBG("%s: EDID: 3D present @ %d = %02x\n", __func__,
+ offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
+ DEV_DBG("%s: EDID: 3D present @ 0x%x = %02x\n", __func__,
offset, vsd[offset]);
if (vsd[offset] >> 7) { /* 3D format indication present */
@@ -835,7 +839,7 @@
3, &len) : NULL;
int i;
- offset = HDMI_VSDB_3D_DATA_OFFSET(vsd);
+ offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
present_multi_3d = (vsd[offset] & 0x60) >> 5;
offset += 1;
@@ -897,17 +901,16 @@
i = 0;
while (hdmi_3d_len > 0) {
- DEV_DBG("%s: EDID[3D]: 3D_Structure_%d @ %d: %02x\n", __func__,
- i + 1, offset, vsd[offset]);
+ DEV_DBG("%s: EDID: 3D_Structure_%d @ 0x%x: %02x\n",
+ __func__, i + 1, offset, vsd[offset]);
if ((vsd[offset] >> 4) >=
sink_data->disp_multi_3d_mode_list_cnt) {
if ((vsd[offset] & 0x0F) >= 8) {
offset += 1;
hdmi_3d_len -= 1;
- DEV_DBG("%s:EDID[3D]:3D_Detail_%d @ %d: %02x\n",
- __func__, i + 1, offset,
- vsd[offset]);
+ DEV_DBG("%s:EDID:3D_Detail_%d @ 0x%x: %02x\n",
+ __func__, i + 1, offset, vsd[offset]);
}
i += 1;
offset += 1;
@@ -941,7 +944,7 @@
if ((vsd[offset] & 0x0F) >= 8) {
offset += 1;
hdmi_3d_len -= 1;
- DEV_DBG("%s: EDID[3D]: 3D_Detail_%d @ %d: %02x\n",
+ DEV_DBG("%s: EDID[3D]: 3D_Detail_%d @ 0x%x: %02x\n",
__func__, i + 1, offset,
vsd[offset]);
}
@@ -951,6 +954,49 @@
}
} /* hdmi_edid_get_display_vsd_3d_mode */
+static void hdmi_edid_get_extended_video_formats(
+ struct hdmi_edid_ctrl *edid_ctrl, const u8 *in_buf)
+{
+ u8 db_len, offset, i;
+ u8 hdmi_vic_len;
+ u32 video_format;
+ const u8 *vsd = NULL;
+
+ if (!edid_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &db_len);
+
+ if (vsd == NULL || db_len < 9) {
+ DEV_DBG("%s: blk-id 3 not found or not long enough\n",
+ __func__);
+ return;
+ }
+
+ /* check if HDMI_Video_present flag is set or not */
+ if (!(vsd[8] & BIT(5))) {
+ DEV_DBG("%s: extended vfmts are not supported by the sink.\n",
+ __func__);
+ return;
+ }
+
+ offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
+
+ hdmi_vic_len = vsd[offset + 1] >> 5;
+ if (hdmi_vic_len) {
+ DEV_DBG("%s: EDID: EVFRMT @ 0x%x of block 3, len = %02x\n",
+ __func__, offset, hdmi_vic_len);
+
+ for (i = 0; i < hdmi_vic_len; i++) {
+ video_format = HDMI_VFRMT_END + vsd[offset + 2 + i];
+ hdmi_edid_add_sink_video_format(&edid_ctrl->sink_data,
+ video_format);
+ }
+ }
+} /* hdmi_edid_get_extended_video_formats */
+
static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl,
const u8 *data_buf, u32 num_of_cea_blocks)
{
@@ -1113,6 +1159,8 @@
}
}
+ hdmi_edid_get_extended_video_formats(edid_ctrl, data_buf+0x80);
+
/* mandaroty 3d format */
if (edid_ctrl->present_3d) {
if (has60hz_mode) {
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 37bbbdf..9235856 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -32,7 +32,7 @@
#define DRV_NAME "hdmi-tx"
#define COMPATIBLE_NAME "qcom,hdmi-tx"
-#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_1920x1080p60_16_9;
+#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_1920x1080p60_16_9
/* HDMI PHY/PLL bit field macros */
#define SW_RESET BIT(2)
@@ -91,35 +91,46 @@
}
} /* hdmi_pm_name */
-static u8 hdmi_tx_avi_iframe_lut[][16] = {
-/* 480p60 480i60 576p50 576i50 720p60 720p50 1080p60 1080i60 1080p50
- 1080i50 1080p24 1080p30 1080p25 640x480p 480p60_16_9 576p50_4_3 */
- {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, /*00*/
- {0x18, 0x18, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x18, 0x28, 0x18}, /*01*/
- {0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x04, 0x04, 0x04, 0x04, 0x88, 0x00, 0x04}, /*02*/
- {0x02, 0x06, 0x11, 0x15, 0x04, 0x13, 0x10, 0x05, 0x1F,
- 0x14, 0x20, 0x22, 0x21, 0x01, 0x03, 0x11}, /*03*/
- {0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*04*/
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*05*/
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*06*/
- {0xE1, 0xE1, 0x41, 0x41, 0xD1, 0xd1, 0x39, 0x39, 0x39,
- 0x39, 0x39, 0x39, 0x39, 0xe1, 0xE1, 0x41}, /*07*/
- {0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04,
- 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x02}, /*08*/
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*09*/
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*10*/
- {0xD1, 0xD1, 0xD1, 0xD1, 0x01, 0x01, 0x81, 0x81, 0x81,
- 0x81, 0x81, 0x81, 0x81, 0x81, 0xD1, 0xD1}, /*11*/
- {0x02, 0x02, 0x02, 0x02, 0x05, 0x05, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x02, 0x02, 0x02} /*12*/
+static u8 hdmi_tx_avi_iframe_lut[][20] = {
+ {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10}, /*00*/
+ {0x18, 0x18, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0x28, 0x28, 0x18, 0x28, 0x18, 0x28, 0x28,
+ 0x28, 0x28}, /*01*/
+ {0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x88, 0x00, 0x04, 0x04, 0x04,
+ 0x04, 0x04}, /*02*/
+ {0x02, 0x06, 0x11, 0x15, 0x04, 0x13, 0x10, 0x05, 0x1F,
+ 0x14, 0x20, 0x22, 0x21, 0x01, 0x03, 0x11, 0x00, 0x00,
+ 0x00, 0x00}, /*03*/
+ {0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00}, /*04*/
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00}, /*05*/
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00}, /*06*/
+ {0xE1, 0xE1, 0x41, 0x41, 0xD1, 0xd1, 0x39, 0x39, 0x39,
+ 0x39, 0x39, 0x39, 0x39, 0xe1, 0xE1, 0x41, 0x71, 0x71,
+ 0x71, 0x71}, /*07*/
+ {0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x02, 0x08, 0x08,
+ 0x08, 0x08}, /*08*/
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00}, /*09*/
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00}, /*10*/
+ {0xD1, 0xD1, 0xD1, 0xD1, 0x01, 0x01, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0xD1, 0xD1, 0x01, 0x01,
+ 0x01, 0x01}, /*11*/
+ {0x02, 0x02, 0x02, 0x02, 0x05, 0x05, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x02, 0x02, 0x02, 0x0F, 0x0F,
+ 0x0F, 0x10} /*12*/
};
/* Audio constants lookup table for hdmi_tx_audio_acr_setup */
@@ -141,6 +152,10 @@
{148500, {{4096, 148500}, {6272, 165000}, {6144, 148500},
{12544, 165000}, {12288, 148500}, {25088, 165000},
{24576, 148500} } },
+ /* 297.000MHz */
+ {297000, {{3072, 222750}, {4704, 247500}, {5120, 247500},
+ {9408, 247500}, {10240, 247500}, {18816, 247500},
+ {20480, 247500} } },
};
const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
@@ -482,9 +497,11 @@
} /* hdmi_tx_init_panel_info */
/* Table indicating the video format supported by the HDMI TX Core */
-/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
+/* Valid pclk rates (Mhz): 25.2, 27, 27.03, 74.25, 148.5, 268.5, 297 */
static void hdmi_tx_setup_video_mode_lut(void)
{
+ hdmi_init_supported_video_timings();
+
hdmi_set_supported_mode(HDMI_VFRMT_640x480p60_4_3);
hdmi_set_supported_mode(HDMI_VFRMT_720x480p60_4_3);
hdmi_set_supported_mode(HDMI_VFRMT_720x480p60_16_9);
@@ -502,6 +519,11 @@
hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p50_16_9);
hdmi_set_supported_mode(HDMI_VFRMT_1920x1080i60_16_9);
hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p60_16_9);
+ hdmi_set_supported_mode(HDMI_VFRMT_2560x1600p60_16_9);
+ hdmi_set_supported_mode(HDMI_VFRMT_3840x2160p30_16_9);
+ hdmi_set_supported_mode(HDMI_VFRMT_3840x2160p25_16_9);
+ hdmi_set_supported_mode(HDMI_VFRMT_3840x2160p24_16_9);
+ hdmi_set_supported_mode(HDMI_VFRMT_4096x2160p24_16_9);
} /* hdmi_tx_setup_video_mode_lut */
static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl)
@@ -636,7 +658,7 @@
return 0;
} /* hdmi_tx_set_video_fmt */
-static void hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
+static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
int video_format)
{
u32 total_v = 0;
@@ -652,47 +674,53 @@
if (timing == NULL) {
DEV_ERR("%s: video format not supported: %d\n", __func__,
video_format);
- return;
+ return -EPERM;
}
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
- return;
+ return -EINVAL;
}
io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
if (!io->base) {
DEV_ERR("%s: Core io is not initialized\n", __func__);
- return;
+ return -EPERM;
}
total_h = timing->active_h + timing->front_porch_h +
timing->back_porch_h + timing->pulse_width_h - 1;
total_v = timing->active_v + timing->front_porch_v +
timing->back_porch_v + timing->pulse_width_v - 1;
- DSS_REG_W(io, HDMI_TOTAL,
- ((total_v << 16) & 0x0FFF0000) |
- ((total_h << 0) & 0x00000FFF));
+ if (((total_v << 16) & 0xE0000000) || (total_h & 0xFFFFE000)) {
+ DEV_ERR("%s: total v=%d or h=%d is larger than supported\n",
+ __func__, total_v, total_h);
+ return -EPERM;
+ }
+ DSS_REG_W(io, HDMI_TOTAL, (total_v << 16) | (total_h << 0));
start_h = timing->back_porch_h + timing->pulse_width_h;
end_h = (total_h + 1) - timing->front_porch_h;
- DSS_REG_W(io, HDMI_ACTIVE_H,
- ((end_h << 16) & 0x0FFF0000) |
- ((start_h << 0) & 0x00000FFF));
+ if (((end_h << 16) & 0xE0000000) || (start_h & 0xFFFFE000)) {
+ DEV_ERR("%s: end_h=%d or start_h=%d is larger than supported\n",
+ __func__, end_h, start_h);
+ return -EPERM;
+ }
+ DSS_REG_W(io, HDMI_ACTIVE_H, (end_h << 16) | (start_h << 0));
start_v = timing->back_porch_v + timing->pulse_width_v - 1;
end_v = total_v - timing->front_porch_v;
- DSS_REG_W(io, HDMI_ACTIVE_V,
- ((end_v << 16) & 0x0FFF0000) |
- ((start_v << 0) & 0x00000FFF));
+ if (((end_v << 16) & 0xE0000000) || (start_v & 0xFFFFE000)) {
+ DEV_ERR("%s: end_v=%d or start_v=%d is larger than supported\n",
+ __func__, end_v, start_v);
+ return -EPERM;
+ }
+ DSS_REG_W(io, HDMI_ACTIVE_V, (end_v << 16) | (start_v << 0));
if (timing->interlaced) {
- DSS_REG_W(io, HDMI_V_TOTAL_F2,
- ((total_v + 1) << 0) & 0x00000FFF);
-
+ DSS_REG_W(io, HDMI_V_TOTAL_F2, (total_v + 1) << 0);
DSS_REG_W(io, HDMI_ACTIVE_V_F2,
- (((start_v + 1) << 0) & 0x00000FFF) |
- (((end_v + 1) << 16) & 0x0FFF0000));
+ ((end_v + 1) << 16) | ((start_v + 1) << 0));
} else {
DSS_REG_W(io, HDMI_V_TOTAL_F2, 0);
DSS_REG_W(io, HDMI_ACTIVE_V_F2, 0);
@@ -702,6 +730,8 @@
((timing->interlaced << 31) & 0x80000000) |
((timing->active_low_h << 29) & 0x20000000) |
((timing->active_low_v << 28) & 0x10000000));
+
+ return 0;
} /* hdmi_tx_video_setup */
static void hdmi_tx_set_avi_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl)
@@ -772,6 +802,18 @@
case HDMI_VFRMT_720x576p50_4_3:
mode = 15;
break;
+ case HDMI_VFRMT_3840x2160p30_16_9:
+ mode = 16;
+ break;
+ case HDMI_VFRMT_3840x2160p25_16_9:
+ mode = 17;
+ break;
+ case HDMI_VFRMT_3840x2160p24_16_9:
+ mode = 18;
+ break;
+ case HDMI_VFRMT_4096x2160p24_16_9:
+ mode = 19;
+ break;
default:
DEV_INFO("%s: mode %d not supported\n", __func__,
hdmi_ctrl->video_resolution);
@@ -846,12 +888,87 @@
regVal = regVal << 8 | avi_iframe[14];
DSS_REG_W(io, HDMI_AVI_INFO3, regVal);
- /* 0x3 for AVI InfFrame enable (every frame) */
+ /* AVI InfFrame enable (every frame) */
DSS_REG_W(io, HDMI_INFOFRAME_CTRL0,
- DSS_REG_R(io, HDMI_INFOFRAME_CTRL0) |
- 0x00000003L);
+ DSS_REG_R(io, HDMI_INFOFRAME_CTRL0) | BIT(1) | BIT(0));
} /* hdmi_tx_set_avi_infoframe */
+/* todo: add 3D support */
+static void hdmi_tx_set_vendor_specific_infoframe(
+ struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ int i;
+ u8 vs_iframe[9]; /* two header + length + 6 data */
+ u32 sum, reg_val;
+ u32 hdmi_vic, hdmi_video_format;
+ struct dss_io_data *io = NULL;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: Core io is not initialized\n", __func__);
+ return;
+ }
+
+ /* HDMI Spec 1.4a Table 8-10 */
+ vs_iframe[0] = 0x81; /* type */
+ vs_iframe[1] = 0x1; /* version */
+ vs_iframe[2] = 0x8; /* length */
+
+ vs_iframe[3] = 0x0; /* PB0: checksum */
+
+ /* PB1..PB3: 24 Bit IEEE Registration Code 00_0C_03 */
+ vs_iframe[4] = 0x03;
+ vs_iframe[5] = 0x0C;
+ vs_iframe[6] = 0x00;
+
+ hdmi_video_format = 0x1;
+ switch (hdmi_ctrl->video_resolution) {
+ case HDMI_VFRMT_3840x2160p30_16_9:
+ hdmi_vic = 0x1;
+ break;
+ case HDMI_VFRMT_3840x2160p25_16_9:
+ hdmi_vic = 0x2;
+ break;
+ case HDMI_VFRMT_3840x2160p24_16_9:
+ hdmi_vic = 0x3;
+ break;
+ case HDMI_VFRMT_4096x2160p24_16_9:
+ hdmi_vic = 0x4;
+ break;
+ default:
+ hdmi_video_format = 0x0;
+ hdmi_vic = 0x0;
+ }
+
+ /* PB4: HDMI Video Format[7:5], Reserved[4:0] */
+ vs_iframe[7] = (hdmi_video_format << 5) & 0xE0;
+
+ /* PB5: HDMI_VIC or 3D_Structure[7:4], Reserved[3:0] */
+ vs_iframe[8] = hdmi_vic;
+
+ /* compute checksum */
+ sum = 0;
+ for (i = 0; i < 9; i++)
+ sum += vs_iframe[i];
+
+ sum &= 0xFF;
+ sum = 256 - sum;
+ vs_iframe[3] = (u8)sum;
+
+ reg_val = (hdmi_vic << 16) | (vs_iframe[3] << 8) |
+ (hdmi_video_format << 5) | vs_iframe[2];
+ DSS_REG_W(io, HDMI_VENSPEC_INFO0, reg_val);
+
+ /* vendor specific info-frame enable (every frame) */
+ DSS_REG_W(io, HDMI_INFOFRAME_CTRL0,
+ DSS_REG_R(io, HDMI_INFOFRAME_CTRL0) | BIT(13) | BIT(12));
+} /* hdmi_tx_set_vendor_specific_infoframe */
+
static void hdmi_tx_set_spd_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl)
{
u32 packet_header = 0;
@@ -1610,7 +1727,13 @@
hdmi_tx_set_mode(hdmi_ctrl, true);
- hdmi_tx_video_setup(hdmi_ctrl, hdmi_ctrl->video_resolution);
+ rc = hdmi_tx_video_setup(hdmi_ctrl, hdmi_ctrl->video_resolution);
+ if (rc) {
+ DEV_ERR("%s: hdmi_tx_video_setup failed. rc=%d\n",
+ __func__, rc);
+ hdmi_tx_set_mode(hdmi_ctrl, false);
+ return rc;
+ }
if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
rc = hdmi_tx_audio_setup(hdmi_ctrl);
@@ -1624,11 +1747,11 @@
switch_set_state(&hdmi_ctrl->audio_sdev, 1);
DEV_INFO("%s: hdmi_audio state switch to %d\n", __func__,
hdmi_ctrl->audio_sdev.state);
- }
- hdmi_tx_set_avi_infoframe(hdmi_ctrl);
- /* todo: CONFIG_FB_MSM_HDMI_3D */
- hdmi_tx_set_spd_infoframe(hdmi_ctrl);
+ hdmi_tx_set_avi_infoframe(hdmi_ctrl);
+ hdmi_tx_set_vendor_specific_infoframe(hdmi_ctrl);
+ hdmi_tx_set_spd_infoframe(hdmi_ctrl);
+ }
/* todo: HDCP/CEC */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index a3d76be..ad63605 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -16,73 +16,24 @@
#include "mdss_hdmi_util.h"
static struct hdmi_disp_mode_timing_type
- hdmi_supported_video_mode_lut[HDMI_VFRMT_MAX] = {
- HDMI_SETTINGS_640x480p60_4_3,
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p60_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p60_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1280x720p60_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080i60_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i60_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i60_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x240p60_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x240p60_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x480i60_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x480i60_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x240p60_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x240p60_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480p60_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480p60_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080p60_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p50_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1280x720p50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080i50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i50_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x288p50_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x288p50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x576i50_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x576i50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x288p50_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x288p50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576p50_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576p50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080p50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080p24_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080p25_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080p30_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x480p60_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x480p60_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x576p50_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_2880x576p50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1250i50_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080i100_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1280x720p100_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p100_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p100_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i100_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i100_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1920x1080i120_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1280x720p120_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p120_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p120_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i120_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i120_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p200_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x576p200_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i200_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x576i200_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p240_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_720x480p240_16_9),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i240_4_3),
- VFRMT_NOT_SUPPORTED(HDMI_VFRMT_1440x480i240_16_9),
-}; /* hdmi_supported_video_mode_lut */
+ hdmi_supported_video_mode_lut[HDMI_VFRMT_MAX];
#define HDMI_SETUP_LUT(MODE) do { \
struct hdmi_disp_mode_timing_type mode = HDMI_SETTINGS_##MODE; \
hdmi_supported_video_mode_lut[mode.video_format] = mode; \
} while (0)
+void hdmi_init_supported_video_timings(void)
+{
+ int i;
+
+ for (i = 0; i < HDMI_VFRMT_MAX; i++) {
+ struct hdmi_disp_mode_timing_type mode = VFRMT_NOT_SUPPORTED(i);
+
+ hdmi_supported_video_mode_lut[i] = mode;
+ }
+} /* hdmi_init_supported_video_timings */
+
const struct hdmi_disp_mode_timing_type *hdmi_get_supported_mode(u32 mode)
{
const struct hdmi_disp_mode_timing_type *ret = NULL;
@@ -203,6 +154,21 @@
case HDMI_VFRMT_1920x1080p60_16_9:
HDMI_SETUP_LUT(1920x1080p60_16_9);
break;
+ case HDMI_VFRMT_2560x1600p60_16_9:
+ HDMI_SETUP_LUT(2560x1600p60_16_9);
+ break;
+ case HDMI_VFRMT_3840x2160p30_16_9:
+ HDMI_SETUP_LUT(3840x2160p30_16_9);
+ break;
+ case HDMI_VFRMT_3840x2160p25_16_9:
+ HDMI_SETUP_LUT(3840x2160p25_16_9);
+ break;
+ case HDMI_VFRMT_3840x2160p24_16_9:
+ HDMI_SETUP_LUT(3840x2160p24_16_9);
+ break;
+ case HDMI_VFRMT_4096x2160p24_16_9:
+ HDMI_SETUP_LUT(4096x2160p24_16_9);
+ break;
default:
DEV_ERR("%s: unsupported mode=%d\n", __func__, mode);
}
@@ -270,6 +236,11 @@
case HDMI_VFRMT_720x480p240_16_9: return " 720x 480 p240 16/9";
case HDMI_VFRMT_1440x480i240_4_3: return "1440x 480 i240 4/3";
case HDMI_VFRMT_1440x480i240_16_9: return "1440x 480 i240 16/9";
+ case HDMI_VFRMT_2560x1600p60_16_9: return "2560x1600 p60 16/9";
+ case HDMI_VFRMT_3840x2160p30_16_9: return "3840x2160 p30 16/9";
+ case HDMI_VFRMT_3840x2160p25_16_9: return "3840x2160 p25 16/9";
+ case HDMI_VFRMT_3840x2160p24_16_9: return "3840x2160 p24 16/9";
+ case HDMI_VFRMT_4096x2160p24_16_9: return "4096x2160 p24 16/9";
default: return "???";
}
} /* hdmi_get_video_fmt_2string */
@@ -550,8 +521,8 @@
*/
DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_SETUP, 0xFF000000);
- /* Enable reference timer to 27 micro-seconds */
- DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_REF, (1 << 16) | (27 << 0));
+ /* Enable reference timer to 19 micro-seconds */
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_REF, (1 << 16) | (19 << 0));
} /* hdmi_ddc_config */
int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.h b/drivers/video/msm/mdss/mdss_hdmi_util.h
index c970ebe..cd7b7dd 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.h
@@ -216,7 +216,7 @@
#define QFPROM_RAW_FEAT_CONFIG_ROW0_LSB (0x000000F8)
#define QFPROM_RAW_FEAT_CONFIG_ROW0_MSB (0x000000FC)
-/* all video formats defined by EIA CEA 861D */
+/* all video formats defined by EIA CEA-861-E */
#define HDMI_VFRMT_640x480p60_4_3 0
#define HDMI_VFRMT_720x480p60_4_3 1
#define HDMI_VFRMT_720x480p60_16_9 2
@@ -292,7 +292,18 @@
#define HDMI_VFRMT_1440x480i240_4_3 HDMI_VFRMT_720x480i240_4_3
#define HDMI_VFRMT_720x480i240_16_9 58
#define HDMI_VFRMT_1440x480i240_16_9 HDMI_VFRMT_720x480i240_16_9
-#define HDMI_VFRMT_MAX 59
+/* Video Identification Codes from 65-127 are reserved for the future */
+#define HDMI_VFRMT_END 127
+/* extended video formats */
+#define HDMI_VFRMT_3840x2160p30_16_9 (HDMI_VFRMT_END + 1)
+#define HDMI_VFRMT_3840x2160p25_16_9 (HDMI_VFRMT_END + 2)
+#define HDMI_VFRMT_3840x2160p24_16_9 (HDMI_VFRMT_END + 3)
+#define HDMI_VFRMT_4096x2160p24_16_9 (HDMI_VFRMT_END + 4)
+#define HDMI_EVFRMT_END HDMI_VFRMT_4096x2160p24_16_9
+/* DVI only resolutions */
+#define HDMI_VFRMT_2560x1600p60_16_9 (HDMI_EVFRMT_END + 1)
+#define DVI_VFRMT_END HDMI_VFRMT_2560x1600p60_16_9
+#define HDMI_VFRMT_MAX (DVI_VFRMT_END + 1)
#define HDMI_VFRMT_FORCE_32BIT 0x7FFFFFFF
#define VFRMT_NOT_SUPPORTED(VFRMT) \
@@ -349,6 +360,21 @@
#define HDMI_SETTINGS_1920x1080p30_16_9 \
{HDMI_VFRMT_1920x1080p30_16_9, 1920, 88, 44, 148, false, \
1080, 4, 5, 36, false, 74250, 30000, false, true}
+#define HDMI_SETTINGS_2560x1600p60_16_9 \
+ {HDMI_VFRMT_2560x1600p60_16_9, 2560, 48, 32, 80, false, \
+ 1600, 3, 6, 37, false, 268500, 60000, false, true}
+#define HDMI_SETTINGS_3840x2160p30_16_9 \
+ {HDMI_VFRMT_3840x2160p30_16_9, 3840, 176, 88, 296, false, \
+ 2160, 8, 10, 72, false, 297000, 30000, false, true}
+#define HDMI_SETTINGS_3840x2160p25_16_9 \
+ {HDMI_VFRMT_3840x2160p25_16_9, 3840, 1056, 88, 296, false, \
+ 2160, 8, 10, 72, false, 297000, 25000, false, true}
+#define HDMI_SETTINGS_3840x2160p24_16_9 \
+ {HDMI_VFRMT_3840x2160p24_16_9, 3840, 1276, 88, 296, false, \
+ 2160, 8, 10, 72, false, 297000, 24000, false, true}
+#define HDMI_SETTINGS_4096x2160p24_16_9 \
+ {HDMI_VFRMT_4096x2160p24_16_9, 4096, 1020, 88, 296, false, \
+ 2160, 8, 10, 72, false, 297000, 24000, false, true}
#define TOP_AND_BOTTOM 0x10
#define FRAME_PACKING 0x20
@@ -397,6 +423,8 @@
int retry;
};
+/* video timing related utility routines */
+void hdmi_init_supported_video_timings(void);
int hdmi_get_video_id_code(struct hdmi_disp_mode_timing_type *timing_in);
const struct hdmi_disp_mode_timing_type *hdmi_get_supported_mode(u32 mode);
void hdmi_set_supported_mode(u32 mode);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index b59d193..7ca06ff 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -666,7 +666,7 @@
}
static int mdss_iommu_fault_handler(struct iommu_domain *domain,
- struct device *dev, unsigned long iova, int flags)
+ struct device *dev, unsigned long iova, int flags, void *token)
{
pr_err("MDP IOMMU page fault: iova 0x%lx\n", iova);
return 0;
@@ -758,7 +758,7 @@
iomap->domain_idx);
return -EINVAL;
}
- iommu_set_fault_handler(domain, mdss_iommu_fault_handler);
+ iommu_set_fault_handler(domain, mdss_iommu_fault_handler, NULL);
iomap->ctx = msm_iommu_get_ctx(iomap->ctx_name);
if (!iomap->ctx) {
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 95b15d6..d4fa3aa 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -22,12 +22,14 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/scatterlist.h>
+#include <linux/err.h>
#define IOMMU_READ (1)
#define IOMMU_WRITE (2)
#define IOMMU_CACHE (4) /* DMA cache coherency */
struct iommu_ops;
+struct iommu_group;
struct bus_type;
struct device;
struct iommu_domain;
@@ -37,12 +39,13 @@
#define IOMMU_FAULT_WRITE 0x1
typedef int (*iommu_fault_handler_t)(struct iommu_domain *,
- struct device *, unsigned long, int);
+ struct device *, unsigned long, int, void *);
struct iommu_domain {
struct iommu_ops *ops;
void *priv;
iommu_fault_handler_t handler;
+ void *handler_token;
};
#define IOMMU_CAP_CACHE_COHERENCY 0x1
@@ -61,6 +64,8 @@
* @iova_to_phys: translate iova to physical address
* @domain_has_cap: domain capabilities query
* @commit: commit iommu domain
+ * @add_device: add device to iommu grouping
+ * @remove_device: remove device from iommu grouping
* @pgsize_bitmap: bitmap of supported page sizes
*/
struct iommu_ops {
@@ -81,10 +86,18 @@
int (*domain_has_cap)(struct iommu_domain *domain,
unsigned long cap);
phys_addr_t (*get_pt_base_addr)(struct iommu_domain *domain);
- int (*device_group)(struct device *dev, unsigned int *groupid);
+ int (*add_device)(struct device *dev);
+ void (*remove_device)(struct device *dev);
unsigned long pgsize_bitmap;
};
+#define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1 /* Device added */
+#define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */
+#define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */
+#define IOMMU_GROUP_NOTIFY_BOUND_DRIVER 4 /* Post Driver bind */
+#define IOMMU_GROUP_NOTIFY_UNBIND_DRIVER 5 /* Pre Driver unbind */
+#define IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER 6 /* Post Driver unbind */
+
extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops);
extern bool iommu_present(struct bus_type *bus);
extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus, int flags);
@@ -107,8 +120,30 @@
unsigned long cap);
extern phys_addr_t iommu_get_pt_base_addr(struct iommu_domain *domain);
extern void iommu_set_fault_handler(struct iommu_domain *domain,
- iommu_fault_handler_t handler);
-extern int iommu_device_group(struct device *dev, unsigned int *groupid);
+ iommu_fault_handler_t handler, void *token);
+
+extern int iommu_attach_group(struct iommu_domain *domain,
+ struct iommu_group *group);
+extern void iommu_detach_group(struct iommu_domain *domain,
+ struct iommu_group *group);
+extern struct iommu_group *iommu_group_alloc(void);
+extern void *iommu_group_get_iommudata(struct iommu_group *group);
+extern void iommu_group_set_iommudata(struct iommu_group *group,
+ void *iommu_data,
+ void (*release)(void *iommu_data));
+extern int iommu_group_set_name(struct iommu_group *group, const char *name);
+extern int iommu_group_add_device(struct iommu_group *group,
+ struct device *dev);
+extern void iommu_group_remove_device(struct device *dev);
+extern int iommu_group_for_each_dev(struct iommu_group *group, void *data,
+ int (*fn)(struct device *, void *));
+extern struct iommu_group *iommu_group_get(struct device *dev);
+extern void iommu_group_put(struct iommu_group *group);
+extern int iommu_group_register_notifier(struct iommu_group *group,
+ struct notifier_block *nb);
+extern int iommu_group_unregister_notifier(struct iommu_group *group,
+ struct notifier_block *nb);
+extern int iommu_group_id(struct iommu_group *group);
/**
* report_iommu_fault() - report about an IOMMU fault to the IOMMU framework
@@ -144,7 +179,8 @@
* invoke it.
*/
if (domain->handler)
- ret = domain->handler(domain, dev, iova, flags);
+ ret = domain->handler(domain, dev, iova, flags,
+ domain->handler_token);
return ret;
}
@@ -152,6 +188,7 @@
#else /* CONFIG_IOMMU_API */
struct iommu_ops {};
+struct iommu_group {};
static inline bool iommu_present(struct bus_type *bus)
{
@@ -221,15 +258,85 @@
}
static inline void iommu_set_fault_handler(struct iommu_domain *domain,
- iommu_fault_handler_t handler)
+ iommu_fault_handler_t handler, void *token)
{
}
-static inline int iommu_device_group(struct device *dev, unsigned int *groupid)
+static inline int iommu_attach_group(struct iommu_domain *domain,
+ struct iommu_group *group)
{
return -ENODEV;
}
+static inline void iommu_detach_group(struct iommu_domain *domain,
+ struct iommu_group *group)
+{
+}
+
+static inline struct iommu_group *iommu_group_alloc(void)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline void *iommu_group_get_iommudata(struct iommu_group *group)
+{
+ return NULL;
+}
+
+static inline void iommu_group_set_iommudata(struct iommu_group *group,
+ void *iommu_data,
+ void (*release)(void *iommu_data))
+{
+}
+
+static inline int iommu_group_set_name(struct iommu_group *group,
+ const char *name)
+{
+ return -ENODEV;
+}
+
+static inline int iommu_group_add_device(struct iommu_group *group,
+ struct device *dev)
+{
+ return -ENODEV;
+}
+
+static inline void iommu_group_remove_device(struct device *dev)
+{
+}
+
+static inline int iommu_group_for_each_dev(struct iommu_group *group,
+ void *data,
+ int (*fn)(struct device *, void *))
+{
+ return -ENODEV;
+}
+
+static inline struct iommu_group *iommu_group_get(struct device *dev)
+{
+ return NULL;
+}
+
+static inline void iommu_group_put(struct iommu_group *group)
+{
+}
+
+static inline int iommu_group_register_notifier(struct iommu_group *group,
+ struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+
+static inline int iommu_group_unregister_notifier(struct iommu_group *group,
+ struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int iommu_group_id(struct iommu_group *group)
+{
+ return -ENODEV;
+}
#endif /* CONFIG_IOMMU_API */
#endif /* __LINUX_IOMMU_H */
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 4e9e1ce..2874a3b 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -22,10 +22,6 @@
#define WCD9XXX_NUM_IRQ_REGS 4
#define WCD9XXX_SLIM_NUM_PORT_REG 3
-
-#define WCD9XXX_INTERFACE_TYPE_SLIMBUS 0x00
-#define WCD9XXX_INTERFACE_TYPE_I2C 0x01
-
#define TABLA_VERSION_1_0 0
#define TABLA_VERSION_1_1 1
#define TABLA_VERSION_2_0 2
@@ -135,6 +131,12 @@
wait_queue_head_t dai_wait;
};
+enum wcd9xxx_intf_status {
+ WCD9XXX_INTERFACE_TYPE_PROBING,
+ WCD9XXX_INTERFACE_TYPE_SLIMBUS,
+ WCD9XXX_INTERFACE_TYPE_I2C,
+};
+
#define WCD9XXX_CH(xport, xshift) \
{.port = xport, .shift = xshift}
@@ -177,6 +179,7 @@
u32 num_tx_port;
struct wcd9xxx_ch *rx_chs;
struct wcd9xxx_ch *tx_chs;
+ u32 mclk_rate;
};
int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
@@ -192,7 +195,7 @@
int wcd9xxx_irq_init(struct wcd9xxx *wcd9xxx);
void wcd9xxx_irq_exit(struct wcd9xxx *wcd9xxx);
int wcd9xxx_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
-int wcd9xxx_get_intf_type(void);
+enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void);
bool wcd9xxx_lock_sleep(struct wcd9xxx *wcd9xxx);
void wcd9xxx_unlock_sleep(struct wcd9xxx *wcd9xxx);
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index a7ca417..bfd95a6 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -154,6 +154,7 @@
struct wcd9xxx_micbias_setting micbias;
struct wcd9xxx_ocp_setting ocp;
struct wcd9xxx_regulator regulator[MAX_REGULATOR];
+ u32 mclk_rate;
};
#endif
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index f8a3a10..7bdd3f2 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -62,9 +62,11 @@
};
#ifdef CONFIG_CMA
+bool is_cma_pageblock(struct page *page);
# define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
# define cma_wmark_pages(zone) zone->min_cma_pages
#else
+# define is_cma_pageblock(page) false
# define is_migrate_cma(migratetype) false
# define cma_wmark_pages(zone) 0
#endif
diff --git a/include/media/msm_media_info.h b/include/media/msm_media_info.h
index 13ce043..ab76d79 100644
--- a/include/media/msm_media_info.h
+++ b/include/media/msm_media_info.h
@@ -97,7 +97,7 @@
uv_sclines = VENUS_UV_SCANLINES(color_fmt, height);
switch (color_fmt) {
case COLOR_FMT_NV12:
- uv_alignment = 0;
+ uv_alignment = 4096;
y_plane = y_stride * y_sclines;
uv_plane = uv_stride * uv_sclines + uv_alignment;
size = y_plane + uv_plane;
diff --git a/include/media/vcap_fmt.h b/include/media/vcap_fmt.h
index 369cf45..2787e8d 100644
--- a/include/media/vcap_fmt.h
+++ b/include/media/vcap_fmt.h
@@ -47,6 +47,11 @@
HAL_VCAP_RGB,
};
+enum nr_threshold_mode {
+ NR_THRESHOLD_STATIC = 0,
+ NR_THRESHOLD_DYNAMIC,
+};
+
enum nr_mode {
NR_DISABLE = 0,
NR_AUTO,
@@ -73,6 +78,7 @@
};
struct nr_param {
+ enum nr_threshold_mode threshold;
enum nr_mode mode;
enum nr_decay_ratio decay_ratio;
uint8_t window;
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 9201a0a..3abe85d 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -1884,6 +1884,67 @@
/* For 32 bit alignment. */
} __packed;
+
+/* This param id is used to configure the Pseudoport interface */
+
+#define AFE_PARAM_ID_PSEUDO_PORT_CONFIG 0x00010219
+
+/* Version information used to handle future additions to the configuration
+ * interface (for backward compatibility).
+ */
+#define AFE_API_VERSION_PSEUDO_PORT_CONFIG 0x1
+
+/* Enumeration for setting the timing_mode parameter to faster than real
+ * time.
+ */
+#define AFE_PSEUDOPORT_TIMING_MODE_FTRT 0x0
+
+/* Enumeration for setting the timing_mode parameter to real time using
+ * timers.
+ */
+#define AFE_PSEUDOPORT_TIMING_MODE_TIMER 0x1
+
+/* Payload of the AFE_PARAM_ID_PSEUDO_PORT_CONFIG parameter used by
+ AFE_MODULE_AUDIO_DEV_INTERFACE.
+*/
+struct afe_param_id_pseudo_port_cfg {
+ u32 pseud_port_cfg_minor_version;
+ /*
+ * Minor version used for tracking the version of the pseudoport
+ * configuration interface.
+ */
+
+ u16 bit_width;
+ /* Bit width of the sample at values 16, 24 */
+
+ u16 num_channels;
+ /* Number of channels at values 1 to 8 */
+
+ u16 data_format;
+ /* Non-linear data format supported by the pseudoport (for future use).
+ * At values #AFE_LINEAR_PCM_DATA
+ */
+
+ u16 timing_mode;
+ /* Indicates whether the pseudoport synchronizes to the clock or
+ * operates faster than real time.
+ * at values
+ * - #AFE_PSEUDOPORT_TIMING_MODE_FTRT
+ * - #AFE_PSEUDOPORT_TIMING_MODE_TIMER @tablebulletend
+ */
+
+ u32 sample_rate;
+ /* Sample rate at which the pseudoport will run.
+ * at values
+ * - #AFE_PORT_SAMPLE_RATE_8K
+ * - #AFE_PORT_SAMPLE_RATE_32K
+ * - #AFE_PORT_SAMPLE_RATE_48K
+ * - #AFE_PORT_SAMPLE_RATE_96K
+ * - #AFE_PORT_SAMPLE_RATE_192K @tablebulletend
+ */
+} __packed;
+
+
union afe_port_config {
struct afe_param_id_pcm_cfg pcm;
struct afe_param_id_i2s_cfg i2s;
@@ -1891,6 +1952,7 @@
struct afe_param_id_slimbus_cfg slim_sch;
struct afe_param_id_rt_proxy_port_cfg rtproxy;
struct afe_param_id_internal_bt_fm_cfg int_bt_fm;
+ struct afe_param_id_pseudo_port_cfg pseudo_port;
} __packed;
struct afe_audioif_config_command_no_payload {
diff --git a/mm/filemap.c b/mm/filemap.c
index 79c4b2b..8ed5c5c 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2343,9 +2343,17 @@
if (page)
goto found;
+retry:
page = __page_cache_alloc(gfp_mask & ~gfp_notmask);
if (!page)
return NULL;
+
+ if (is_cma_pageblock(page)) {
+ __free_page(page);
+ gfp_notmask |= __GFP_MOVABLE;
+ goto retry;
+ }
+
status = add_to_page_cache_lru(page, mapping, index,
GFP_KERNEL & ~gfp_notmask);
if (unlikely(status)) {
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 92dd060..c642286 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -758,6 +758,11 @@
}
#ifdef CONFIG_CMA
+bool is_cma_pageblock(struct page *page)
+{
+ return get_pageblock_migratetype(page) == MIGRATE_CMA;
+}
+
/* Free whole pageblock and set it's migration type to MIGRATE_CMA. */
void __init init_cma_reserved_pageblock(struct page *page)
{
@@ -5422,7 +5427,7 @@
pfn &= (PAGES_PER_SECTION-1);
return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
#else
- pfn = pfn - zone->zone_start_pfn;
+ pfn = pfn - round_down(zone->zone_start_pfn, pageblock_nr_pages);
return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
#endif /* CONFIG_SPARSEMEM */
}
@@ -5701,7 +5706,7 @@
ret = migrate_pages(&cc.migratepages,
__alloc_contig_migrate_alloc,
- 0, false, true);
+ 0, false, MIGRATE_SYNC);
}
putback_lru_pages(&cc.migratepages);
diff --git a/sound/soc/codecs/msm_stub.c b/sound/soc/codecs/msm_stub.c
index 7e603b4..0143e51 100644
--- a/sound/soc/codecs/msm_stub.c
+++ b/sound/soc/codecs/msm_stub.c
@@ -34,7 +34,7 @@
.capture = { /* Support maximum range */
.stream_name = "Record",
.channels_min = 1,
- .channels_max = 4,
+ .channels_max = 8,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 6aa5bbb..76623b1 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -54,7 +54,8 @@
#define TAIKO_SLIM_IRQ_OVERFLOW (1 << 0)
#define TAIKO_SLIM_IRQ_UNDERFLOW (1 << 1)
#define TAIKO_SLIM_IRQ_PORT_CLOSED (1 << 2)
-
+#define TAIKO_MCLK_CLK_12P288MHZ 12288000
+#define TAIKO_MCLK_CLK_9P6HZ 9600000
enum {
AIF1_PB = 0,
AIF1_CAP,
@@ -3120,11 +3121,7 @@
static int taiko_set_dai_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir)
{
- struct snd_soc_codec *codec = dai->codec;
- if (freq == TAIKO_MCLK_CLK_12P288MHZ)
- snd_soc_write(codec, TAIKO_A_CHIP_CTL, 0x04);
- else if (freq == TAIKO_MCLK_CLK_9P6HZ)
- snd_soc_write(codec, TAIKO_A_CHIP_CTL, 0x0A);
+ pr_debug("%s\n", __func__);
return 0;
}
@@ -4810,6 +4807,11 @@
taiko->aux_l_gain = 0x1F;
taiko->aux_r_gain = 0x1F;
taiko_update_reg_defaults(codec);
+ pr_debug("%s: MCLK Rate = %x\n", __func__, wcd9xxx->mclk_rate);
+ if (wcd9xxx->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ)
+ snd_soc_write(codec, TAIKO_A_CHIP_CTL, 0x04);
+ else if (wcd9xxx->mclk_rate == TAIKO_MCLK_CLK_9P6HZ)
+ snd_soc_write(codec, TAIKO_A_CHIP_CTL, 0x0A);
taiko_codec_init_reg(codec);
ret = taiko_handle_pdata(taiko);
if (IS_ERR_VALUE(ret)) {
diff --git a/sound/soc/msm/mdm9625.c b/sound/soc/msm/mdm9625.c
index b1822f6..4c7b69d 100644
--- a/sound/soc/msm/mdm9625.c
+++ b/sound/soc/msm/mdm9625.c
@@ -68,7 +68,6 @@
unsigned gpio_no;
char *gpio_name;
};
-static bool cdc_mclk_init;
static struct mutex cdc_mclk_mutex;
static int mdm9625_mi2s_rx_ch = 1;
static int mdm9625_mi2s_tx_ch = 1;
@@ -292,25 +291,6 @@
return ret;
}
-static int set_codec_mclk(struct snd_soc_pcm_runtime *rtd)
-{
- int ret = 0;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_card *card = rtd->card;
- struct mdm9625_machine_data *pdata = snd_soc_card_get_drvdata(card);
-
- if (cdc_mclk_init == true)
- return 0;
- ret = snd_soc_dai_set_sysclk(codec_dai, TAIKO_MCLK_ID, pdata->mclk_freq,
- SND_SOC_CLOCK_IN);
- if (ret < 0) {
- pr_err("%s: Set codec sys clk failed %x", __func__, ret);
- return ret;
- }
- cdc_mclk_init = true;
- return 0;
-}
-
static int mdm9625_mi2s_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -320,7 +300,6 @@
SNDRV_PCM_HW_PARAM_CHANNELS);
rate->min = rate->max = 48000;
channels->min = channels->max = mdm9625_mi2s_rx_ch;
- set_codec_mclk(rtd);
return 0;
}
@@ -333,7 +312,6 @@
SNDRV_PCM_HW_PARAM_CHANNELS);
rate->min = rate->max = 48000;
channels->min = channels->max = mdm9625_mi2s_tx_ch;
- set_codec_mclk(rtd);
return 0;
}
@@ -713,7 +691,6 @@
mutex_init(&cdc_mclk_mutex);
gpio_enable = false;
- cdc_mclk_init = false;
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "No platform supplied from device tree\n");
return -EINVAL;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index f8185bb..cf1202e 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -1326,6 +1326,30 @@
.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
.ops = &msm8974_be_ops,
},
+ /* Incall Record Uplink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_TX,
+ .stream_name = "Voice Uplink Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.32772",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ },
+ /* Incall Record Downlink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_RX,
+ .stream_name = "Voice Downlink Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.32771",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ },
};
struct snd_soc_card snd_soc_card_msm8974 = {
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index a307bcc..2f4c256 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -432,12 +432,11 @@
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
switch (dai->id) {
case VOICE_PLAYBACK_TX:
- case VOICE_RECORD_TX:
- case VOICE_RECORD_RX:
rc = afe_start_pseudo_port(dai->id);
+ break;
default:
rc = afe_port_start(dai->id, &dai_data->port_config,
- dai_data->rate);
+ dai_data->rate);
}
if (IS_ERR_VALUE(rc))
@@ -606,6 +605,36 @@
return 0;
}
+static int msm_dai_q6_psuedo_port_hw_params(struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai, int stream)
+{
+ struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+
+ dai_data->channels = params_channels(params);
+ dai_data->rate = params_rate(params);
+
+ /* Q6 only supports 16 as now */
+ dai_data->port_config.pseudo_port.pseud_port_cfg_minor_version =
+ AFE_API_VERSION_PSEUDO_PORT_CONFIG;
+ dai_data->port_config.pseudo_port.num_channels =
+ params_channels(params);
+ dai_data->port_config.pseudo_port.bit_width = 16;
+ dai_data->port_config.pseudo_port.data_format = 0;
+ dai_data->port_config.pseudo_port.timing_mode =
+ AFE_PSEUDOPORT_TIMING_MODE_TIMER;
+ dai_data->port_config.pseudo_port.sample_rate = params_rate(params);
+
+ dev_dbg(dai->dev, "%s: bit_wd[%hu] num_channels [%hu] format[%hu]\n"
+ "timing Mode %hu sample_rate %d\n", __func__,
+ dai_data->port_config.pseudo_port.bit_width,
+ dai_data->port_config.pseudo_port.num_channels,
+ dai_data->port_config.pseudo_port.data_format,
+ dai_data->port_config.pseudo_port.timing_mode,
+ dai_data->port_config.pseudo_port.sample_rate);
+
+ return 0;
+}
+
/* Current implementation assumes hw_param is called once
* This may not be the case but what to do when ADM and AFE
* port are already opened and parameter changes
@@ -649,9 +678,12 @@
rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
break;
case VOICE_PLAYBACK_TX:
+ rc = 0;
+ break;
case VOICE_RECORD_RX:
case VOICE_RECORD_TX:
- rc = 0;
+ rc = msm_dai_q6_psuedo_port_hw_params(params,
+ dai, substream->stream);
break;
default:
dev_err(dai->dev, "invalid AFE port ID\n");
@@ -671,8 +703,6 @@
if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
switch (dai->id) {
case VOICE_PLAYBACK_TX:
- case VOICE_RECORD_TX:
- case VOICE_RECORD_RX:
pr_debug("%s, stop pseudo port:%d\n",
__func__, dai->id);
rc = afe_stop_pseudo_port(dai->id);
@@ -832,8 +862,6 @@
if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
switch (dai->id) {
case VOICE_PLAYBACK_TX:
- case VOICE_RECORD_TX:
- case VOICE_RECORD_RX:
pr_debug("%s, stop pseudo port:%d\n",
__func__, dai->id);
rc = afe_stop_pseudo_port(dai->id);
@@ -872,7 +900,7 @@
SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 4,
+ .channels_max = 8,
.rate_min = 8000,
.rate_max = 48000,
},
@@ -969,6 +997,21 @@
.remove = msm_dai_q6_dai_remove,
};
+static struct snd_soc_dai_driver msm_dai_q6_incall_record_dai = {
+ .capture = {
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_ops,
+ .probe = msm_dai_q6_dai_probe,
+ .remove = msm_dai_q6_dai_remove,
+};
+
static int __devinit msm_auxpcm_dev_probe(struct platform_device *pdev)
{
int id;
@@ -1879,6 +1922,12 @@
case RT_PROXY_DAI_002_TX:
rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
break;
+ case VOICE_RECORD_RX:
+ case VOICE_RECORD_TX:
+ rc = snd_soc_register_dai(&pdev->dev,
+ &msm_dai_q6_incall_record_dai);
+ break;
+
default:
rc = -ENODEV;
break;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index 73a04c2..1aa12e3 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -33,8 +33,10 @@
#include <mach/msm_subsystem_map.h>
#include "msm-pcm-afe-v2.h"
-#define MIN_PERIOD_SIZE (128 * 2)
-#define MAX_PERIOD_SIZE (128 * 2 * 2 * 6)
+#define MIN_PERIOD_SIZE (128 * 2 * 8)
+#define MAX_PERIOD_SIZE (128 * 2 * 2 * 6 * 8)
+#define MAX_NUM_PERIODS 384
+#define MIN_NUM_PERIODS 32
static struct snd_pcm_hardware msm_afe_hardware = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -47,12 +49,12 @@
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 8,
.buffer_bytes_max = MAX_PERIOD_SIZE * 32,
.period_bytes_min = MIN_PERIOD_SIZE,
.period_bytes_max = MAX_PERIOD_SIZE,
- .periods_min = 32,
- .periods_max = 384,
+ .periods_min = MIN_NUM_PERIODS,
+ .periods_max = MAX_NUM_PERIODS,
.fifo_size = 0,
};
static enum hrtimer_restart afe_hrtimer_callback(struct hrtimer *hrt);
@@ -353,6 +355,17 @@
if (ret < 0)
pr_err("snd_pcm_hw_constraint_integer failed\n");
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ ret = snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ MAX_NUM_PERIODS * MIN_PERIOD_SIZE,
+ MIN_NUM_PERIODS * MAX_PERIOD_SIZE);
+ if (ret < 0) {
+ pr_err("constraint for buffer bytes min max ret = %d\n",
+ ret);
+ }
+ }
+
return 0;
}
@@ -497,8 +510,8 @@
dir = OUT;
rc = q6afe_audio_client_buf_alloc_contiguous(dir,
prtd->audio_client,
- runtime->hw.period_bytes_min,
- runtime->hw.periods_max);
+ (params_buffer_bytes(params) / params_periods(params)),
+ params_periods(params));
if (rc < 0) {
pr_err("Audio Start: Buffer Allocation failed rc = %d\n", rc);
mutex_unlock(&prtd->lock);
@@ -517,14 +530,14 @@
dma_buf->private_data = NULL;
dma_buf->area = buf[0].data;
dma_buf->addr = buf[0].phys;
- dma_buf->bytes = runtime->hw.buffer_bytes_max;
+ dma_buf->bytes = params_buffer_bytes(params);
if (!dma_buf->area) {
pr_err("%s:MSM AFE physical memory allocation failed\n",
__func__);
mutex_unlock(&prtd->lock);
return -ENOMEM;
}
- memset(dma_buf->area, 0, runtime->hw.buffer_bytes_max);
+ memset(dma_buf->area, 0, params_buffer_bytes(params));
prtd->dma_addr = (u32) dma_buf->addr;
mutex_unlock(&prtd->lock);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 17c18dd..fbdbbf6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -2059,6 +2059,8 @@
{"BE_OUT", NULL, "SLIMBUS_3_RX"},
{"BE_OUT", NULL, "AUX_PCM_RX"},
{"AUX_PCM_TX", NULL, "BE_IN"},
+ {"INCALL_RECORD_TX", NULL, "BE_IN"},
+ {"INCALL_RECORD_RX", NULL, "BE_IN"},
};
static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index fb6b56e..9387d21 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -227,6 +227,10 @@
case SLIMBUS_1_TX:
ret_size = SIZEOF_CFG_CMD(afe_param_id_slimbus_cfg);
break;
+ case VOICE_RECORD_RX:
+ case VOICE_RECORD_TX:
+ ret_size = SIZEOF_CFG_CMD(afe_param_id_pseudo_port_cfg);
+ break;
case RT_PROXY_PORT_001_RX:
case RT_PROXY_PORT_001_TX:
ret_size = SIZEOF_CFG_CMD(afe_param_id_rt_proxy_port_cfg);
@@ -410,6 +414,10 @@
case HDMI_RX:
cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
break;
+ case VOICE_RECORD_RX:
+ case VOICE_RECORD_TX:
+ cfg_type = AFE_PARAM_ID_PSEUDO_PORT_CONFIG;
+ break;
case SLIMBUS_0_RX:
case SLIMBUS_0_TX:
case SLIMBUS_1_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 263f47f..349fcf2 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -2928,23 +2928,25 @@
cvs_start_record.hdr.src_port = v->session_id;
cvs_start_record.hdr.dest_port = cvs_handle;
cvs_start_record.hdr.token = 0;
- cvs_start_record.hdr.opcode = VSS_ISTREAM_CMD_START_RECORD;
+ cvs_start_record.hdr.opcode = VSS_IRECORD_CMD_START;
+ cvs_start_record.rec_mode.port_id =
+ VSS_IRECORD_PORT_ID_DEFAULT;
if (rec_mode == VOC_REC_UPLINK) {
cvs_start_record.rec_mode.rx_tap_point =
- VSS_TAP_POINT_NONE;
+ VSS_IRECORD_TAP_POINT_NONE;
cvs_start_record.rec_mode.tx_tap_point =
- VSS_TAP_POINT_STREAM_END;
+ VSS_IRECORD_TAP_POINT_STREAM_END;
} else if (rec_mode == VOC_REC_DOWNLINK) {
cvs_start_record.rec_mode.rx_tap_point =
- VSS_TAP_POINT_STREAM_END;
+ VSS_IRECORD_TAP_POINT_STREAM_END;
cvs_start_record.rec_mode.tx_tap_point =
- VSS_TAP_POINT_NONE;
+ VSS_IRECORD_TAP_POINT_NONE;
} else if (rec_mode == VOC_REC_BOTH) {
cvs_start_record.rec_mode.rx_tap_point =
- VSS_TAP_POINT_STREAM_END;
+ VSS_IRECORD_TAP_POINT_STREAM_END;
cvs_start_record.rec_mode.tx_tap_point =
- VSS_TAP_POINT_STREAM_END;
+ VSS_IRECORD_TAP_POINT_STREAM_END;
} else {
pr_err("%s: Invalid in-call rec_mode %d\n", __func__,
rec_mode);
@@ -3011,7 +3013,7 @@
cvs_stop_record.src_port = v->session_id;
cvs_stop_record.dest_port = cvs_handle;
cvs_stop_record.token = 0;
- cvs_stop_record.opcode = VSS_ISTREAM_CMD_STOP_RECORD;
+ cvs_stop_record.opcode = VSS_IRECORD_CMD_STOP;
v->cvs_state = CMD_STATUS_FAIL;
@@ -4166,8 +4168,8 @@
case VSS_ICOMMON_CMD_SET_UI_PROPERTY:
case VSS_ISTREAM_CMD_START_PLAYBACK:
case VSS_ISTREAM_CMD_STOP_PLAYBACK:
- case VSS_ISTREAM_CMD_START_RECORD:
- case VSS_ISTREAM_CMD_STOP_RECORD:
+ case VSS_IRECORD_CMD_START:
+ case VSS_IRECORD_CMD_STOP:
case VSS_ISTREAM_CMD_SET_PACKET_EXCHANGE_MODE:
case VSS_ISTREAM_CMD_SET_OOB_PACKET_EXCHANGE_CONFIG:
pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 6fb4b04..d19697a 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -495,17 +495,26 @@
#define VSS_ISTREAM_CMD_STOP_PLAYBACK 0x00011239
/* Stop the in-call music delivery on the Tx voice path. */
-#define VSS_ISTREAM_CMD_START_RECORD 0x00011236
+#define VSS_IRECORD_CMD_START 0x000112BE
/* Start in-call conversation recording. */
-#define VSS_ISTREAM_CMD_STOP_RECORD 0x00011237
+#define VSS_IRECORD_CMD_STOP 0x00011237
/* Stop in-call conversation recording. */
-#define VSS_TAP_POINT_NONE 0x00010F78
+#define VSS_IRECORD_PORT_ID_DEFAULT 0x0000FFFF
+/* Default AFE port ID. */
+
+#define VSS_IRECORD_TAP_POINT_NONE 0x00010F78
/* Indicates no tapping for specified path. */
-#define VSS_TAP_POINT_STREAM_END 0x00010F79
+#define VSS_IRECORD_TAP_POINT_STREAM_END 0x00010F79
/* Indicates that specified path should be tapped at the end of the stream. */
+#define VSS_IRECORD_MODE_TX_RX_STEREO 0x00010F7A
+/* Select Tx on left channel and Rx on right channel. */
+
+#define VSS_IRECORD_MODE_TX_RX_MIXING 0x00010F7B
+/* Select mixed Tx and Rx paths. */
+
#define VSS_ISTREAM_EVT_NOT_READY 0x000110FD
#define VSS_ISTREAM_EVT_READY 0x000110FC
@@ -529,16 +538,30 @@
#define VSS_ISTREAM_CMD_SET_PACKET_EXCHANGE_MODE 0x0001136A
-struct vss_istream_cmd_start_record_t {
+struct vss_irecord_cmd_start_t {
uint32_t rx_tap_point;
/* Tap point to use on the Rx path. Supported values are:
- * VSS_TAP_POINT_NONE : Do not record Rx path.
- * VSS_TAP_POINT_STREAM_END : Rx tap point is at the end of the stream.
+ * VSS_IRECORD_TAP_POINT_NONE : Do not record Rx path.
+ * VSS_IRECORD_TAP_POINT_STREAM_END : Rx tap point is at the end of
+ * the stream.
*/
uint32_t tx_tap_point;
/* Tap point to use on the Tx path. Supported values are:
- * VSS_TAP_POINT_NONE : Do not record tx path.
- * VSS_TAP_POINT_STREAM_END : Tx tap point is at the end of the stream.
+ * VSS_IRECORD_TAP_POINT_NONE : Do not record tx path.
+ * VSS_IRECORD_TAP_POINT_STREAM_END : Tx tap point is at the end of
+ * the stream.
+ */
+ uint16_t port_id;
+ /* AFE Port ID to whcih the conversation recording stream needs to be
+ * sent. Set this to #VSS_IRECORD_PORT_ID_DEFAULT to use default AFE
+ * pseudo ports (0x8003 for Rx and 0x8004 for Tx).
+ */
+ uint32_t mode;
+ /* Recording Mode. The mode parameter value is ignored if the port_id
+ * is set to #VSS_IRECORD_PORT_ID_DEFAULT.
+ * The supported values:
+ * #VSS_IRECORD_MODE_TX_RX_STEREO
+ * #VSS_IRECORD_MODE_TX_RX_MIXING
*/
} __packed;
@@ -782,7 +805,7 @@
} __packed;
struct cvs_start_record_cmd {
struct apr_hdr hdr;
- struct vss_istream_cmd_start_record_t rec_mode;
+ struct vss_irecord_cmd_start_t rec_mode;
} __packed;
struct cvs_dec_buffer_ready_cmd {