Merge "ASoC: 8930: add multi channel support for hdmi" into msm-3.4
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
index 35385d3..4129f7f 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
@@ -18,7 +18,11 @@
- qcom,vdd-mem-upper-bound: The upper bound value of mem voltage in uV
- qcom,vdd-mem-lower-bound: The lower bound value of mem voltage in uV
- qcom,vdd-dig-upper-bound: The upper bound value of dig voltage in uV
+ or an RBCPR (Rapid Bridge Core Power Reduction)
+ corner voltage.
- qcom,vdd-dig-lower-bound: The lower bound value of dig voltage in uV
+ or an RBCPR (Rapid Bridge Core Power Reduction)
+ corner voltage.
- qcom,latency-us: The latency in handling the interrupt if this level was
chosen, in uSec
- qcom,ss-power: The steady state power expelled when the processor is in this
@@ -37,8 +41,8 @@
qcom,l2 = <3>; /* ACTIVE */
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
- qcom,vdd-dig-lower-bound = <950000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
qcom,latency-us = <100>;
qcom,ss-power = <650>;
qcom,energy-overhead = <801>;
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
index 9ff43a1..b16d40f 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
@@ -13,19 +13,20 @@
- compatible: "qcom,lpm-resources"
- reg: The numeric level id
-- qcom,name: The name of the low power resource.
-- qcom,type: The string represeting the type of resource used
- like smps or pxo.
+- qcom,name: The name of the low power resource represented
+ as a string.
+- qcom,type: The type of resource used like smps or pxo
+ represented as a hex value.
- qcom,id: The id representing a device within a resource type.
- qcom,key: The key is the specific attribute of the resource being
- monitored.
+ monitored represented as a hex value.
Example:
qcom,lpm-resources@0 {
reg = <0x0>;
qcom,name = "vdd-dig";
- qcom,type = "smpb\0";
+ qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
- qcom,key = "uv\0\0";
+ qcom,key = <0x6e726f63>; /* "corn" */
};
diff --git a/Documentation/devicetree/bindings/cache/msm_cache_erp.txt b/Documentation/devicetree/bindings/cache/msm_cache_erp.txt
new file mode 100644
index 0000000..400b299
--- /dev/null
+++ b/Documentation/devicetree/bindings/cache/msm_cache_erp.txt
@@ -0,0 +1,16 @@
+* Qualcomm Krait L1 / L2 cache error reporting driver
+
+Required properties:
+- compatible: Should be "qcom,cache_erp"
+- interrupts: Should contain the L1/CPU error interrupt number and
+ the L2 cache interrupt number
+- interrupt-names: Should contain the interrupt names "l1_irq" and
+ "l2_irq"
+
+Example:
+ qcom,cache_erp {
+ compatible = "qcom,cache_erp";
+ interrupts = <1 9 0>, <0 2 0>;
+ interrupt-names = "l1_irq", "l2_irq";
+ };
+
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index 11af7a9..dbbe46d 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -5,11 +5,20 @@
- "qcom,msm-vidc"
- reg : offset and length of the register set for the device.
- interrupts : should contain the vidc interrupt.
+- vidc-cp-map : start and size of device virtual address range for secure buffers.
+ Video hardware uses this address range to identify if the buffers are secure
+ or non-secure.
+- vidc-ns-map : start and size of device virtual address range for non-secure buffers.
+ Video hardware uses this address range to identify if the buffers are secure
+ or non-secure.
Example:
+
qcom,vidc@fdc00000 {
compatible = "qcom,msm-vidc";
reg = <0xfdc00000 0xff000>;
interrupts = <0 44 0>;
+ vidc-cp-map = <0x1000000 0x40000000>;
+ vidc-ns-map = <0x40000000 0x40000000>;
};
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index 35ac0ec..a8de90f 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -35,6 +35,15 @@
- qcom,sdcc-<supply>-current_level - specifies load levels for supply in lpm or
high power mode (hpm). Should be specified in pairs (lpm, hpm), units uA.
+ - gpios - specifies gpios assigned for sdcc slot.
+ - qcom,sdcc-gpio-names - a list of strings that map in order to the list of gpios
+ A slot has either gpios or dedicated tlmm pins as represented below.
+ - qcom,sdcc-pad-pull-on - Active pull configuration for sdc tlmm pins
+ - qcom,sdcc-pad-pull-off - Suspend pull configuration for sdc tlmm pins.
+ - qcom,sdcc-pad-drv-on - Active drive strength configuration for sdc tlmm pins.
+ - qcom,sdcc-pad-drv-off - Suspend drive strength configuration for sdc tlmm pins.
+ Tlmm pins are specified as <clk cmd data>
+
Example:
qcom,sdcc@f9600000 {
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index b6086e7..16a5c77 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -18,6 +18,12 @@
- compatible : "qcom,msm-pcm-lpa"
+* msm-compr-dsp
+
+Required properties:
+
+ - compatible : "qcom,msm-compr-dsp"
+
* msm-voip-dsp
Required properties:
@@ -95,6 +101,10 @@
compatible = "qcom,msm-pcm-lpa";
};
+ qcom,msm-compr-dsp {
+ compatible = "qcom,msm-compr-dsp";
+ };
+
qcom,msm-voip-dsp {
compatible = "qcom,msm-voip-dsp";
};
@@ -119,12 +129,12 @@
qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>;
qcom,msm-auxpcm-rx {
- qcom,msm-auxpcm-dev-id = <4106>;
+ qcom,msm-auxpcm-dev-id = <4106>;
compatible = "qcom,msm-auxpcm-dev";
};
qcom,msm-auxpcm-tx {
- qcom,msm-auxpcm-dev-id = <4107>;
+ qcom,msm-auxpcm-dev-id = <4107>;
compatible = "qcom,msm-auxpcm-dev";
};
};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index f462a1e..6737e89 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -315,6 +315,23 @@
status = "disabled";
};
};
+
+ qcom,pm8941_rtc {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-rtc";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ qcom,qpnp-rtc-write = <0>;
+ qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+ qcom,pm8941_rtc_rw@6000 {
+ reg = <0x6000 0x100>;
+ };
+ qcom,pm8941_rtc_alarm@6100 {
+ reg = <0x6100 0x100>;
+ interrupts = <0x0 0x61 0x1>;
+ };
+ };
};
qcom,pm8941@1 {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 8426b52..edb86be 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -46,6 +46,8 @@
compatible = "qcom,msm-vidc";
reg = <0xfdc00000 0xff000>;
interrupts = <0 44 0>;
+ vidc-cp-map = <0x1000000 0x40000000>;
+ vidc-ns-map = <0x40000000 0x40000000>;
};
serial@f991f000 {
@@ -74,7 +76,7 @@
};
qcom,sdcc@f9824000 {
- cell-index = <1>;
+ cell-index = <1>; /* SDC1 eMMC slot */
compatible = "qcom,msm-sdcc";
reg = <0xf9824000 0x1000>;
interrupts = <0 123 0>;
@@ -88,6 +90,11 @@
qcom,sdcc-vdd-io-voltage_level = <1800000 1800000>;
qcom,sdcc-vdd-io-current_level = <250 154000>;
+ qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+ qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
qcom,sdcc-sup-voltages = <2950 2950>;
qcom,sdcc-bus-width = <8>;
@@ -96,7 +103,7 @@
};
qcom,sdcc@f98a4000 {
- cell-index = <2>;
+ cell-index = <2>; /* SDC2 SD card slot */
compatible = "qcom,msm-sdcc";
reg = <0xf98a4000 0x1000>;
interrupts = <0 125 0>;
@@ -111,6 +118,11 @@
qcom,sdcc-vdd-io-voltage_level = <1800000 2950000>;
qcom,sdcc-vdd-io-current_level = <6 22000>;
+ qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+ qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+ qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
qcom,sdcc-sup-voltages = <2950 2950>;
qcom,sdcc-bus-width = <4>;
@@ -120,11 +132,19 @@
};
qcom,sdcc@f9864000 {
- cell-index = <3>;
+ cell-index = <3>; /* SDC3 SDIO slot */
compatible = "qcom,msm-sdcc";
reg = <0xf9864000 0x1000>;
interrupts = <0 127 0>;
+ gpios = <&msmgpio 40 0>, /* CLK */
+ <&msmgpio 39 0>, /* CMD */
+ <&msmgpio 38 0>, /* DATA0 */
+ <&msmgpio 37 0>, /* DATA1 */
+ <&msmgpio 36 0>, /* DATA2 */
+ <&msmgpio 35 0>; /* DATA3 */
+ qcom,sdcc-gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>;
qcom,sdcc-sup-voltages = <1800 1800>;
qcom,sdcc-bus-width = <4>;
@@ -133,11 +153,19 @@
};
qcom,sdcc@f98e4000 {
- cell-index = <4>;
+ cell-index = <4>; /* SDC4 SDIO slot */
compatible = "qcom,msm-sdcc";
reg = <0xf98e4000 0x1000>;
interrupts = <0 129 0>;
+ gpios = <&msmgpio 93 0>, /* CLK */
+ <&msmgpio 91 0>, /* CMD */
+ <&msmgpio 96 0>, /* DATA0 */
+ <&msmgpio 95 0>, /* DATA1 */
+ <&msmgpio 94 0>, /* DATA2 */
+ <&msmgpio 92 0>; /* DATA3 */
+ qcom,sdcc-gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>;
qcom,sdcc-sup-voltages = <1800 1800>;
qcom,sdcc-bus-width = <4>;
@@ -350,6 +378,10 @@
compatible = "qcom,msm-pcm-lpa";
};
+ qcom,msm-compr-dsp {
+ compatible = "qcom,msm-compr-dsp";
+ };
+
qcom,msm-voip-dsp {
compatible = "qcom,msm-voip-dsp";
};
@@ -447,7 +479,7 @@
partition@E0000 {
reg = <0x120000 0x20000>;
- qcom,ocmem-part-name = "blast";
+ qcom,ocmem-part-name = "other_os";
qcom,ocmem-part-min = <0x20000>;
};
diff --git a/arch/arm/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974_pm.dtsi
index 6f12e31c..aab2722 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974_pm.dtsi
@@ -140,25 +140,25 @@
qcom,lpm-resources@0 {
reg = <0x0>;
qcom,name = "vdd-dig";
- qcom,type = "smpb\0";
+ qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
- qcom,key = "uv\0\0";
+ qcom,key = <0x6e726f63>; /* "corn" */
};
qcom,lpm-resources@1 {
reg = <0x1>;
qcom,name = "vdd-mem";
- qcom,type = "smpb\0";
+ qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x01>;
- qcom,key = "uv\0\0";
+ qcom,key = <0x7675>; /* "uv" */
};
qcom,lpm-resources@2 {
reg = <0x2>;
qcom,name = "pxo";
- qcom,type = "clk0\0";
+ qcom,type = <0x306b6c63>; /* "clk0" */
qcom,id = <0x00>;
- qcom,key = "Enab";
+ qcom,key = <0x62616e45>; /* "Enab" */
};
};
@@ -174,8 +174,8 @@
qcom,l2 = <3>; /* ACTIVE */
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
- qcom,vdd-dig-lower-bound = <950000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
qcom,latency-us = <100>;
qcom,ss-power = <650>;
qcom,energy-overhead = <801>;
@@ -189,8 +189,8 @@
qcom,l2 = <3>; /* ACTIVE */
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
- qcom,vdd-dig-lower-bound = <950000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
qcom,latency-us = <2000>;
qcom,ss-power = <200>;
qcom,energy-overhead = <576000>;
@@ -204,8 +204,8 @@
qcom,l2 = <1>; /* GDHS */
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
- qcom,vdd-dig-lower-bound = <950000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
qcom,latency-us = <8500>;
qcom,ss-power = <51>;
qcom,energy-overhead = <1122000>;
@@ -219,8 +219,8 @@
qcom,l2 = <0>; /* OFF */
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
- qcom,vdd-dig-lower-bound = <950000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
qcom,latency-us = <9000>;
qcom,ss-power = <51>;
qcom,energy-overhead = <1130300>;
@@ -234,8 +234,8 @@
qcom,l2 = <0>; /* OFF */
qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
- qcom,vdd-dig-upper-bound = <950000>; /* ACTIVE */
- qcom,vdd-dig-lower-bound = <750000>; /* RETENTION HIGH */
+ qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
+ qcom,vdd-dig-lower-bound = <2>; /* RETENTION HIGH */
qcom,latency-us = <10000>;
qcom,ss-power = <51>;
qcom,energy-overhead = <1130300>;
@@ -249,8 +249,8 @@
qcom,l2 = <1>; /* GDHS */
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
- qcom,vdd-dig-lower-bound = <950000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
qcom,latency-us = <12000>;
qcom,ss-power = <14>;
qcom,energy-overhead = <2205900>;
@@ -264,8 +264,8 @@
qcom,l2 = <0>; /* OFF */
qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
- qcom,vdd-dig-lower-bound = <950000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
qcom,latency-us = <18000>;
qcom,ss-power = <12>;
qcom,energy-overhead = <2364250>;
@@ -279,8 +279,8 @@
qcom,l2 = <0>; /* OFF */
qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
- qcom,vdd-dig-upper-bound = <950000>; /* ACTIVE */
- qcom,vdd-dig-lower-bound = <750000>; /* RETIONTION HIGH */
+ qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
+ qcom,vdd-dig-lower-bound = <2>; /* RETIONTION HIGH */
qcom,latency-us = <23500>;
qcom,ss-power = <10>;
qcom,energy-overhead = <2667000>;
@@ -294,8 +294,8 @@
qcom,l2 = <0>; /* OFF */
qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
- qcom,vdd-dig-upper-bound = <750000>; /* RETENTION HIGH */
- qcom,vdd-dig-lower-bound = <500000>; /* RETENTION LOW */
+ qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
+ qcom,vdd-dig-lower-bound = <0>; /* RETENTION LOW */
qcom,latency-us = <29700>;
qcom,ss-power = <5>;
qcom,energy-overhead = <2867000>;
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 88c4862..bbd6c63 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -47,6 +47,8 @@
#include <asm/hardware/gic.h>
#include <asm/system.h>
+#include <mach/socinfo.h>
+
union gic_base {
void __iomem *common_base;
void __percpu __iomem **percpu_base;
@@ -56,6 +58,7 @@
unsigned int irq_offset;
union gic_base dist_base;
union gic_base cpu_base;
+ bool need_access_lock;
#ifdef CONFIG_CPU_PM
u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
@@ -207,14 +210,8 @@
{
unsigned int i;
void __iomem *base = gic_data_dist_base(gic);
-#ifdef CONFIG_ARCH_MSM8625
- unsigned long flags;
-#endif
for (i = 0; i * 32 < gic->max_irq; i++) {
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_lock_irqsave(&irq_controller_lock, flags);
-#endif
gic->enabled_irqs[i]
= readl_relaxed(base + GIC_DIST_ENABLE_SET + i * 4);
/* disable all of them */
@@ -222,9 +219,6 @@
/* enable the wakeup set */
writel_relaxed(gic->wakeup_irqs[i],
base + GIC_DIST_ENABLE_SET + i * 4);
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
-#endif
}
mb();
return 0;
@@ -305,18 +299,19 @@
static void gic_eoi_irq(struct irq_data *d)
{
+ struct gic_chip_data *gic = irq_data_get_irq_chip_data(d);
+
if (gic_arch_extn.irq_eoi) {
raw_spin_lock(&irq_controller_lock);
gic_arch_extn.irq_eoi(d);
raw_spin_unlock(&irq_controller_lock);
}
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_lock(&irq_controller_lock);
-#endif
+
+ if (gic->need_access_lock)
+ raw_spin_lock(&irq_controller_lock);
writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_unlock(&irq_controller_lock);
-#endif
+ if (gic->need_access_lock)
+ raw_spin_unlock(&irq_controller_lock);
}
static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -435,13 +430,11 @@
void __iomem *cpu_base = gic_data_cpu_base(gic);
do {
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_lock(&irq_controller_lock);
-#endif
+ if (gic->need_access_lock)
+ raw_spin_lock(&irq_controller_lock);
irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_unlock(&irq_controller_lock);
-#endif
+ if (gic->need_access_lock)
+ raw_spin_unlock(&irq_controller_lock);
irqnr = irqstat & ~0x1c00;
if (likely(irqnr > 15 && irqnr < 1021)) {
@@ -450,13 +443,11 @@
continue;
}
if (irqnr < 16) {
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_lock(&irq_controller_lock);
-#endif
+ if (gic->need_access_lock)
+ raw_spin_lock(&irq_controller_lock);
writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_unlock(&irq_controller_lock);
-#endif
+ if (gic->need_access_lock)
+ raw_spin_unlock(&irq_controller_lock);
#ifdef CONFIG_SMP
handle_IPI(irqnr, regs);
#endif
@@ -583,9 +574,8 @@
* Deal with the banked PPI and SGI interrupts - disable all
* PPI interrupts, ensure all SGI interrupts are enabled.
*/
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_lock(&irq_controller_lock);
-#endif
+ if (gic->need_access_lock)
+ raw_spin_lock(&irq_controller_lock);
writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
@@ -605,9 +595,8 @@
writel_relaxed(0xF, base + GIC_CPU_CTRL);
else
writel_relaxed(1, base + GIC_CPU_CTRL);
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_unlock(&irq_controller_lock);
-#endif
+ if (gic->need_access_lock)
+ raw_spin_unlock(&irq_controller_lock);
mb();
}
@@ -883,6 +872,10 @@
BUG_ON(gic_nr >= MAX_GIC_NR);
gic = &gic_data[gic_nr];
+ if (cpu_is_msm8625() &&
+ (SOCINFO_VERSION_MAJOR(socinfo_get_version()) <= 1))
+ gic->need_access_lock = true;
+
#ifdef CONFIG_GIC_NON_BANKED
if (percpu_offset) { /* Frankein-GIC without banked registers... */
unsigned int cpu;
@@ -967,9 +960,8 @@
int cpu;
unsigned long sgir;
unsigned long map = 0;
-#ifdef CONFIG_ARCH_MSM8625
- unsigned long flags;
-#endif
+ unsigned long flags = 0;
+ struct gic_chip_data *gic = &gic_data[0];
/* Convert our logical CPU mask into a physical one. */
for_each_cpu(cpu, mask)
@@ -985,16 +977,12 @@
*/
dsb();
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_lock_irqsave(&irq_controller_lock, flags);
-#endif
+ if (gic->need_access_lock)
+ raw_spin_lock_irqsave(&irq_controller_lock, flags);
/* this always happens on GIC0 */
-
- writel_relaxed(sgir,
- gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
-#ifdef CONFIG_ARCH_MSM8625
- raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
-#endif
+ writel_relaxed(sgir, gic_data_dist_base(gic) + GIC_DIST_SOFTINT);
+ if (gic->need_access_lock)
+ raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
mb();
}
#endif
@@ -1151,7 +1139,7 @@
}
#endif
-void msm_gic_save(bool modem_wake, int from_idle)
+void msm_gic_save(void)
{
unsigned int i;
struct gic_chip_data *gic = &gic_data[0];
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 5078148..ad12bcd 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -60,7 +60,7 @@
}
void gic_set_irq_secure(unsigned int irq);
-void msm_gic_save(bool modem_wake, int from_idle);
+void msm_gic_save(void);
void msm_gic_restore(void);
void core1_gic_configure_and_raise(void);
#endif
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h
index 582c9b3..94aa75e 100644
--- a/arch/arm/include/asm/spinlock.h
+++ b/arch/arm/include/asm/spinlock.h
@@ -7,6 +7,8 @@
#include <asm/processor.h>
+extern int msm_krait_need_wfe_fixup;
+
/*
* sev and wfe are ARMv6K extensions. Uniprocessor ARMv6 may not have the K
* extensions, so when running on UP, we have to patch these instructions away.
@@ -21,25 +23,42 @@
#ifdef CONFIG_THUMB2_KERNEL
#define SEV ALT_SMP("sev.w", "nop.w")
/*
- * For Thumb-2, special care is needed to ensure that the conditional WFE
- * instruction really does assemble to exactly 4 bytes (as required by
- * the SMP_ON_UP fixup code). By itself "wfene" might cause the
- * assembler to insert a extra (16-bit) IT instruction, depending on the
- * presence or absence of neighbouring conditional instructions.
- *
- * To avoid this unpredictableness, an approprite IT is inserted explicitly:
- * the assembler won't change IT instructions which are explicitly present
- * in the input.
+ * Both instructions given to the ALT_SMP macro need to be the same size, to
+ * allow the SMP_ON_UP fixups to function correctly. Hence the explicit encoding
+ * specifications.
*/
-#define WFE(cond) ALT_SMP( \
- "it " cond "\n\t" \
- "wfe" cond ".n", \
- \
+#define WFE() ALT_SMP( \
+ "wfe.w", \
"nop.w" \
)
#else
#define SEV ALT_SMP("sev", "nop")
-#define WFE(cond) ALT_SMP("wfe" cond, "nop")
+#define WFE() ALT_SMP("wfe", "nop")
+#endif
+
+/*
+ * The fixup involves disabling interrupts during execution of the WFE
+ * instruction. This could potentially lead to deadlock if a thread is trying
+ * to acquire a spinlock which is being released from an interrupt context.
+ */
+#ifdef CONFIG_MSM_KRAIT_WFE_FIXUP
+#define WFE_SAFE(fixup, tmp) \
+" mrs " tmp ", cpsr\n" \
+" cmp " fixup ", #0\n" \
+" wfeeq\n" \
+" beq 10f\n" \
+" cpsid if\n" \
+" mrc p15, 7, " fixup ", c15, c0, 5\n" \
+" bic " fixup ", " fixup ", #0x10000\n" \
+" mcr p15, 7, " fixup ", c15, c0, 5\n" \
+" isb\n" \
+" wfe\n" \
+" orr " fixup ", " fixup ", #0x10000\n" \
+" mcr p15, 7, " fixup ", c15, c0, 5\n" \
+" isb\n" \
+"10: msr cpsr_cf, " tmp "\n"
+#else
+#define WFE_SAFE(fixup, tmp) " wfe\n"
#endif
static inline void dsb_sev(void)
@@ -79,17 +98,19 @@
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
- unsigned long tmp;
+ unsigned long tmp, fixup = msm_krait_need_wfe_fixup;
__asm__ __volatile__(
-"1: ldrex %0, [%1]\n"
-" teq %0, #0\n"
- WFE("ne")
-" strexeq %0, %2, [%1]\n"
-" teqeq %0, #0\n"
+"1: ldrex %[tmp], [%[lock]]\n"
+" teq %[tmp], #0\n"
+" beq 2f\n"
+ WFE_SAFE("%[fixup]", "%[tmp]")
+"2:\n"
+" strexeq %[tmp], %[bit0], [%[lock]]\n"
+" teqeq %[tmp], #0\n"
" bne 1b"
- : "=&r" (tmp)
- : "r" (&lock->lock), "r" (1)
+ : [tmp] "=&r" (tmp), [fixup] "+r" (fixup)
+ : [lock] "r" (&lock->lock), [bit0] "r" (1)
: "cc");
smp_mb();
@@ -155,6 +176,7 @@
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
unsigned long tmp, ticket, next_ticket;
+ unsigned long fixup = msm_krait_need_wfe_fixup;
/* Grab the next ticket and wait for it to be "served" */
__asm__ __volatile__(
@@ -166,12 +188,15 @@
" uxth %[ticket], %[ticket]\n"
"2:\n"
#ifdef CONFIG_CPU_32v6K
-" wfene\n"
+" beq 3f\n"
+ WFE_SAFE("%[fixup]", "%[tmp]")
+"3:\n"
#endif
" ldr %[tmp], [%[lockaddr]]\n"
" cmp %[ticket], %[tmp], lsr #16\n"
" bne 2b"
- : [ticket]"=&r" (ticket), [tmp]"=&r" (tmp), [next_ticket]"=&r" (next_ticket)
+ : [ticket]"=&r" (ticket), [tmp]"=&r" (tmp),
+ [next_ticket]"=&r" (next_ticket), [fixup]"+r" (fixup)
: [lockaddr]"r" (&lock->lock), [val1]"r" (1)
: "cc");
smp_mb();
@@ -220,13 +245,16 @@
static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
{
- unsigned long ticket;
+ unsigned long ticket, tmp, fixup = msm_krait_need_wfe_fixup;
/* Wait for now_serving == next_ticket */
__asm__ __volatile__(
#ifdef CONFIG_CPU_32v6K
" cmpne %[lockaddr], %[lockaddr]\n"
-"1: wfene\n"
+"1:\n"
+" beq 2f\n"
+ WFE_SAFE("%[fixup]", "%[tmp]")
+"2:\n"
#else
"1:\n"
#endif
@@ -235,7 +263,8 @@
" uxth %[ticket], %[ticket]\n"
" cmp %[ticket], #0\n"
" bne 1b"
- : [ticket]"=&r" (ticket)
+ : [ticket]"=&r" (ticket), [tmp]"=&r" (tmp),
+ [fixup]"+r" (fixup)
: [lockaddr]"r" (&lock->lock)
: "cc");
}
@@ -263,17 +292,19 @@
static inline void arch_write_lock(arch_rwlock_t *rw)
{
- unsigned long tmp;
+ unsigned long tmp, fixup = msm_krait_need_wfe_fixup;
__asm__ __volatile__(
-"1: ldrex %0, [%1]\n"
-" teq %0, #0\n"
- WFE("ne")
-" strexeq %0, %2, [%1]\n"
-" teq %0, #0\n"
+"1: ldrex %[tmp], [%[lock]]\n"
+" teq %[tmp], #0\n"
+" beq 2f\n"
+ WFE_SAFE("%[fixup]", "%[tmp]")
+"2:\n"
+" strexeq %[tmp], %[bit31], [%[lock]]\n"
+" teq %[tmp], #0\n"
" bne 1b"
- : "=&r" (tmp)
- : "r" (&rw->lock), "r" (0x80000000)
+ : [tmp] "=&r" (tmp), [fixup] "+r" (fixup)
+ : [lock] "r" (&rw->lock), [bit31] "r" (0x80000000)
: "cc");
smp_mb();
@@ -329,17 +360,19 @@
*/
static inline void arch_read_lock(arch_rwlock_t *rw)
{
- unsigned long tmp, tmp2;
+ unsigned long tmp, tmp2, fixup = msm_krait_need_wfe_fixup;
__asm__ __volatile__(
-"1: ldrex %0, [%2]\n"
-" adds %0, %0, #1\n"
-" strexpl %1, %0, [%2]\n"
- WFE("mi")
-" rsbpls %0, %1, #0\n"
+"1: ldrex %[tmp], [%[lock]]\n"
+" adds %[tmp], %[tmp], #1\n"
+" strexpl %[tmp2], %[tmp], [%[lock]]\n"
+" bpl 2f\n"
+ WFE_SAFE("%[fixup]", "%[tmp]")
+"2:\n"
+" rsbpls %[tmp], %[tmp2], #0\n"
" bmi 1b"
- : "=&r" (tmp), "=&r" (tmp2)
- : "r" (&rw->lock)
+ : [tmp] "=&r" (tmp), [tmp2] "=&r" (tmp2), [fixup] "+r" (fixup)
+ : [lock] "r" (&rw->lock)
: "cc");
smp_mb();
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index a8f2858..7d767c3 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -185,6 +185,7 @@
INIT_SETUP(16)
INIT_CALLS
CON_INITCALL
+ COMPAT_EXPORTS
SECURITY_INITCALL
INIT_RAM_FS
}
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index c23bc10..5e7965e 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -172,6 +172,7 @@
select HOLES_IN_ZONE if SPARSEMEM
select MSM_RUN_QUEUE_STATS
select ARM_HAS_SG_CHAIN
+ select MSM_KRAIT_WFE_FIXUP
config ARCH_MSM8930
bool "MSM8930"
@@ -203,6 +204,7 @@
select MSM_PM8X60 if PM
select HOLES_IN_ZONE if SPARSEMEM
select ARM_HAS_SG_CHAIN
+ select MSM_KRAIT_WFE_FIXUP
config ARCH_APQ8064
bool "APQ8064"
@@ -229,6 +231,7 @@
select MIGHT_HAVE_PCI
select ARCH_SUPPORTS_MSI
select ARM_HAS_SG_CHAIN
+ select MSM_KRAIT_WFE_FIXUP
config ARCH_MSM8974
bool "MSM8974"
@@ -370,6 +373,9 @@
select MSM_SMP
bool
+config MSM_KRAIT_WFE_FIXUP
+ bool
+
config ARCH_MSM_CORTEX_A5
bool
select HAVE_HW_BRKPT_RESERVED_RW_ACCESS
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 5cd93dc..4c020e3 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -23,6 +23,7 @@
endif
obj-y += acpuclock.o
+obj-$(CONFIG_ARCH_MSM_KRAIT) += acpuclock-krait.o
obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7627.o clock-pll.o
obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
@@ -269,6 +270,7 @@
obj-$(CONFIG_ARCH_MSM8960) += saw-regulator.o
obj-$(CONFIG_ARCH_MSM8960) += devices-8960.o
obj-$(CONFIG_ARCH_APQ8064) += devices-8960.o devices-8064.o
+obj-$(CONFIG_ARCH_APQ8064) += acpuclock-8064.o
board-8960-all-objs += board-8960.o board-8960-camera.o board-8960-display.o board-8960-pmic.o board-8960-storage.o board-8960-gpiomux.o
board-8930-all-objs += board-8930.o board-8930-camera.o board-8930-display.o board-8930-pmic.o board-8930-storage.o board-8930-gpiomux.o devices-8930.o board-8930-gpu.o
board-8064-all-objs += board-8064.o board-8064-pmic.o board-8064-storage.o board-8064-gpiomux.o board-8064-camera.o board-8064-display.o board-8064-gpu.o
@@ -291,11 +293,11 @@
obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
obj-$(CONFIG_ARCH_MSM8974) += board-8974.o board-dt.o board-8974-regulator.o board-8974-gpiomux.o
-obj-$(CONFIG_ARCH_MSM8974) += acpuclock-krait.o acpuclock-8974.o
+obj-$(CONFIG_ARCH_MSM8974) += acpuclock-8974.o
obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o
obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
-obj-$(CONFIG_ARCH_MSM8930) += acpuclock-krait.o acpuclock-8930.o acpuclock-8627.o
+obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
@@ -337,7 +339,7 @@
obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
endif
obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o ocmem_notifier.o
-obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o
+obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o ocmem_rdm.o
obj-$(CONFIG_ARCH_MSM7X27) += gpiomux-7x27.o gpiomux-v1.o gpiomux.o
obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
new file mode 100644
index 0000000..d46d268
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2011-2012, Code Aurora Forum. 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/module.h>
+#include <linux/platform_device.h>
+#include <mach/rpm-regulator.h>
+#include <mach/msm_bus_board.h>
+#include <mach/msm_bus.h>
+
+#include "acpuclock.h"
+#include "acpuclock-krait.h"
+
+static struct hfpll_data hfpll_data __initdata = {
+ .mode_offset = 0x00,
+ .l_offset = 0x08,
+ .m_offset = 0x0C,
+ .n_offset = 0x10,
+ .config_offset = 0x04,
+ .config_val = 0x7845C665,
+ .has_droop_ctl = true,
+ .droop_offset = 0x14,
+ .droop_val = 0x0108C000,
+ .low_vdd_l_max = 40,
+ .vdd[HFPLL_VDD_NONE] = 0,
+ .vdd[HFPLL_VDD_LOW] = 945000,
+ .vdd[HFPLL_VDD_NOM] = 1050000,
+};
+
+static struct scalable scalable[] __initdata = {
+ [CPU0] = {
+ .hfpll_phys_base = 0x00903200,
+ .aux_clk_sel_phys = 0x02088014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x4501,
+ .vreg[VREG_CORE] = { "krait0", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait0_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait0_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 },
+ },
+ [CPU1] = {
+ .hfpll_phys_base = 0x00903240,
+ .aux_clk_sel_phys = 0x02098014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x5501,
+ .vreg[VREG_CORE] = { "krait1", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 },
+ },
+ [CPU2] = {
+ .hfpll_phys_base = 0x00903280,
+ .aux_clk_sel_phys = 0x020A8014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x6501,
+ .vreg[VREG_CORE] = { "krait2", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait2_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait2_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait2_hfpll", 1800000 },
+ },
+ [CPU3] = {
+ .hfpll_phys_base = 0x009032C0,
+ .aux_clk_sel_phys = 0x020B8014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x7501,
+ .vreg[VREG_CORE] = { "krait3", 1300000, 1740000 },
+ .vreg[VREG_MEM] = { "krait3_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait3_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait3_hfpll", 1800000 },
+ },
+ [L2] = {
+ .hfpll_phys_base = 0x00903300,
+ .aux_clk_sel_phys = 0x02011028,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x0500,
+ .vreg[VREG_HFPLL_A] = { "l2_hfpll", 1800000 },
+ },
+};
+
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
+ [0] = BW_MBPS(640), /* At least 80 MHz on bus. */
+ [1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
+ [2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
+ [3] = BW_MBPS(2128), /* At least 266 MHz on bus. */
+ [4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
+ [5] = BW_MBPS(4264), /* At least 533 MHz on bus. */
+};
+
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
+ .usecase = bw_level_tbl,
+ .num_usecases = ARRAY_SIZE(bw_level_tbl),
+ .active_only = 1,
+ .name = "acpuclk-8064",
+};
+
+static struct l2_level l2_freq_tbl[] __initdata __initdata = {
+ [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
+ [1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
+ [2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
+ [3] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 2 },
+ [4] = { { 540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 2 },
+ [5] = { { 594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
+ [6] = { { 648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 4 },
+ [7] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 4 },
+ [8] = { { 756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 4 },
+ [9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 4 },
+ [10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 4 },
+ [11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 5 },
+ [12] = { { 972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 5 },
+ [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 5 },
+ [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 5 },
+ [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 5 },
+};
+
+static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 975000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 975000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 1000000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 1000000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 1025000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1075000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1075000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1100000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1125000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1125000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1175000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1175000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1200000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1200000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1225000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1225000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1237500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1237500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1250000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 925000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 925000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 950000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 950000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 975000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 975000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1025000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1025000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1050000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1050000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1075000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1075000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1125000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1125000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1150000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1150000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1175000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1175000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1187500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1187500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 850000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 850000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 875000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 875000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 900000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 900000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 925000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 925000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 975000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 975000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1000000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1000000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1025000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1025000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1075000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1075000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1100000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1100000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1125000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1125000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1137500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1137500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1150000 },
+ { 0, { 0 } }
+};
+
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+ [PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow) },
+ [PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom) },
+ [PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
+ /* TODO: update the faster table when data is available */
+ [PVS_FASTER] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
+};
+
+static struct acpuclk_krait_params acpuclk_8064_params __initdata = {
+ .scalable = scalable,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
+ .l2_freq_tbl = l2_freq_tbl,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
+ .qfprom_phys_base = 0x00700000,
+};
+
+static int __init acpuclk_8064_probe(struct platform_device *pdev)
+{
+ return acpuclk_krait_init(&pdev->dev, &acpuclk_8064_params);
+}
+
+static struct platform_driver acpuclk_8064_driver = {
+ .driver = {
+ .name = "acpuclk-8064",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init acpuclk_8064_init(void)
+{
+ return platform_driver_probe(&acpuclk_8064_driver,
+ acpuclk_8064_probe);
+}
+device_initcall(acpuclk_8064_init);
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
index 45f2096..8060803 100644
--- a/arch/arm/mach-msm/acpuclock-8627.c
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -27,7 +27,7 @@
#define LVL_NOM RPM_VREG_CORNER_NOMINAL
#define LVL_HIGH RPM_VREG_CORNER_HIGH
-static struct hfpll_data hfpll_data = {
+static struct hfpll_data hfpll_data __initdata = {
.mode_offset = 0x00,
.l_offset = 0x08,
.m_offset = 0x0C,
@@ -43,10 +43,9 @@
.vdd[HFPLL_VDD_NOM] = LVL_NOM,
};
-static struct scalable scalable[] = {
+static struct scalable scalable[] __initdata = {
[CPU0] = {
.hfpll_phys_base = 0x00903200,
- .hfpll_data = &hfpll_data,
.aux_clk_sel_phys = 0x02088014,
.aux_clk_sel = 3,
.l2cpmr_iaddr = 0x4501,
@@ -57,7 +56,6 @@
},
[CPU1] = {
.hfpll_phys_base = 0x00903300,
- .hfpll_data = &hfpll_data,
.aux_clk_sel_phys = 0x02098014,
.aux_clk_sel = 3,
.l2cpmr_iaddr = 0x5501,
@@ -68,7 +66,6 @@
},
[L2] = {
.hfpll_phys_base = 0x00903400,
- .hfpll_data = &hfpll_data,
.aux_clk_sel_phys = 0x02011028,
.aux_clk_sel = 3,
.l2cpmr_iaddr = 0x0500,
@@ -76,7 +73,7 @@
},
};
-static struct msm_bus_paths bw_level_tbl[] = {
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
[0] = BW_MBPS(640), /* At least 80 MHz on bus. */
[1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
[2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
@@ -84,7 +81,7 @@
[4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
};
-static struct msm_bus_scale_pdata bus_scale_data = {
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
.usecase = bw_level_tbl,
.num_usecases = ARRAY_SIZE(bw_level_tbl),
.active_only = 1,
@@ -92,8 +89,7 @@
};
/* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
-#define L2(x) (&l2_freq_tbl[(x)])
-static struct l2_level l2_freq_tbl[] = {
+static struct l2_level l2_freq_tbl[] __initdata = {
[0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, LVL_NOM, 1050000, 0 },
[1] = { { 384000, PLL_8, 0, 2, 0x00 }, LVL_NOM, 1050000, 1 },
[2] = { { 432000, HFPLL, 2, 0, 0x20 }, LVL_NOM, 1050000, 1 },
@@ -110,7 +106,7 @@
};
/* TODO: Update core voltages when data is available. */
-static struct acpu_level acpu_freq_tbl[] = {
+static struct acpu_level acpu_freq_tbl[] __initdata = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
{ 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(5), 925000 },
@@ -127,14 +123,20 @@
{ 0, { 0 } }
};
-static struct acpuclk_krait_params acpuclk_8627_params = {
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+ [PVS_SLOW] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+ [PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+ [PVS_FAST] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+};
+
+static struct acpuclk_krait_params acpuclk_8627_params __initdata = {
.scalable = scalable,
- .pvs_acpu_freq_tbl[PVS_SLOW] = acpu_freq_tbl,
- .pvs_acpu_freq_tbl[PVS_NOMINAL] = acpu_freq_tbl,
- .pvs_acpu_freq_tbl[PVS_FAST] = acpu_freq_tbl,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
.l2_freq_tbl = l2_freq_tbl,
- .l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl),
- .bus_scale_data = &bus_scale_data,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
.qfprom_phys_base = 0x00700000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index d60b4eb..d04ce03 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -27,7 +27,7 @@
#define LVL_NOM RPM_VREG_CORNER_NOMINAL
#define LVL_HIGH RPM_VREG_CORNER_HIGH
-static struct hfpll_data hfpll_data = {
+static struct hfpll_data hfpll_data __initdata = {
.mode_offset = 0x00,
.l_offset = 0x08,
.m_offset = 0x0C,
@@ -43,10 +43,9 @@
.vdd[HFPLL_VDD_NOM] = LVL_NOM,
};
-static struct scalable scalable[] = {
+static struct scalable scalable[] __initdata = {
[CPU0] = {
.hfpll_phys_base = 0x00903200,
- .hfpll_data = &hfpll_data,
.aux_clk_sel_phys = 0x02088014,
.aux_clk_sel = 3,
.l2cpmr_iaddr = 0x4501,
@@ -57,7 +56,6 @@
},
[CPU1] = {
.hfpll_phys_base = 0x00903300,
- .hfpll_data = &hfpll_data,
.aux_clk_sel_phys = 0x02098014,
.aux_clk_sel = 3,
.l2cpmr_iaddr = 0x5501,
@@ -68,7 +66,6 @@
},
[L2] = {
.hfpll_phys_base = 0x00903400,
- .hfpll_data = &hfpll_data,
.aux_clk_sel_phys = 0x02011028,
.aux_clk_sel = 3,
.l2cpmr_iaddr = 0x0500,
@@ -76,7 +73,7 @@
},
};
-static struct msm_bus_paths bw_level_tbl[] = {
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
[0] = BW_MBPS(640), /* At least 80 MHz on bus. */
[1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
[2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
@@ -87,7 +84,7 @@
[7] = BW_MBPS(4264), /* At least 533 MHz on bus. */
};
-static struct msm_bus_scale_pdata bus_scale_data = {
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
.usecase = bw_level_tbl,
.num_usecases = ARRAY_SIZE(bw_level_tbl),
.active_only = 1,
@@ -95,8 +92,7 @@
};
/* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
-#define L2(x) (&l2_freq_tbl[(x)])
-static struct l2_level l2_freq_tbl[] = {
+static struct l2_level l2_freq_tbl[] __initdata = {
[0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, LVL_NOM, 1050000, 0 },
[1] = { { 384000, PLL_8, 0, 2, 0x00 }, LVL_NOM, 1050000, 1 },
[2] = { { 432000, HFPLL, 2, 0, 0x20 }, LVL_NOM, 1050000, 2 },
@@ -116,7 +112,7 @@
[16] = { { 1188000, HFPLL, 1, 0, 0x2C }, LVL_HIGH, 1150000, 7 },
};
-static struct acpu_level acpu_freq_tbl_slow[] = {
+static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
{ 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 975000 },
@@ -137,7 +133,7 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_freq_tbl_nom[] = {
+static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 925000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 925000 },
{ 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 950000 },
@@ -158,7 +154,7 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_freq_tbl_fast[] = {
+static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
{ 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 900000 },
@@ -179,14 +175,20 @@
{ 0, { 0 } }
};
-static struct acpuclk_krait_params acpuclk_8930_params = {
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+ [PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow) },
+ [PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom) },
+ [PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
+};
+
+static struct acpuclk_krait_params acpuclk_8930_params __initdata = {
.scalable = scalable,
- .pvs_acpu_freq_tbl[PVS_SLOW] = acpu_freq_tbl_slow,
- .pvs_acpu_freq_tbl[PVS_NOMINAL] = acpu_freq_tbl_nom,
- .pvs_acpu_freq_tbl[PVS_FAST] = acpu_freq_tbl_fast,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
.l2_freq_tbl = l2_freq_tbl,
- .l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl),
- .bus_scale_data = &bus_scale_data,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
.qfprom_phys_base = 0x00700000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 8947c9f..8623c2b 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/*
+ * Copyright (c) 2011-2012, Code Aurora Forum. 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
@@ -10,318 +11,66 @@
* GNU General Public License for more details.
*/
-#define pr_fmt(fmt) "%s: " fmt, __func__
-
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/regulator/consumer.h>
#include <linux/platform_device.h>
-
-#include <asm/mach-types.h>
-#include <asm/cpu.h>
-
-#include <mach/board.h>
-#include <mach/msm_iomap.h>
#include <mach/rpm-regulator.h>
-#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
-#include <mach/socinfo.h>
-#include <mach/msm-krait-l2-accessors.h>
-#include <mach/rpm-regulator.h>
+#include <mach/msm_bus.h>
#include "acpuclock.h"
-#include "pm.h"
+#include "acpuclock-krait.h"
-/*
- * Source IDs.
- * These must be negative to not overlap with the source IDs
- * used by the 8x60 local clock driver.
- */
-#define PLL_8 0
-#define HFPLL -1
-#define QSB -2
-
-/* Mux source selects. */
-#define PRI_SRC_SEL_SEC_SRC 0
-#define PRI_SRC_SEL_HFPLL 1
-#define PRI_SRC_SEL_HFPLL_DIV2 2
-#define SEC_SRC_SEL_QSB 0
-#define SEC_SRC_SEL_AUX 2
-
-/* HFPLL registers offsets. */
-#define HFPLL_MODE 0x00
-#define HFPLL_CONFIG_CTL 0x04
-#define HFPLL_L_VAL 0x08
-#define HFPLL_M_VAL 0x0C
-#define HFPLL_N_VAL 0x10
-#define HFPLL_DROOP_CTL 0x14
-
-/* CP15 L2 indirect addresses. */
-#define L2CPMR_IADDR 0x500
-#define L2CPUCPMR_IADDR 0x501
-
-#define STBY_KHZ 1
-
-#define HFPLL_LOW_VDD_PLL_L_MAX 0x28
-
-#define SECCLKAGD BIT(4)
-
-/* PTE EFUSE register. */
-#define QFPROM_PTE_EFUSE_ADDR (MSM_QFPROM_BASE + 0x00C0)
-
-/* Corner type vreg VDD values */
-#define LVL_NONE RPM_VREG_CORNER_NONE
-#define LVL_LOW RPM_VREG_CORNER_LOW
-#define LVL_NOM RPM_VREG_CORNER_NOMINAL
-#define LVL_HIGH RPM_VREG_CORNER_HIGH
-
-enum scalables {
- CPU0 = 0,
- CPU1,
- CPU2,
- CPU3,
- L2,
- NUM_SCALABLES
+static struct hfpll_data hfpll_data __initdata = {
+ .mode_offset = 0x00,
+ .l_offset = 0x08,
+ .m_offset = 0x0C,
+ .n_offset = 0x10,
+ .config_offset = 0x04,
+ .config_val = 0x7845C665,
+ .has_droop_ctl = true,
+ .droop_offset = 0x14,
+ .droop_val = 0x0108C000,
+ .low_vdd_l_max = 40,
+ .vdd[HFPLL_VDD_NONE] = 0,
+ .vdd[HFPLL_VDD_LOW] = 850000,
+ .vdd[HFPLL_VDD_NOM] = 1050000,
};
-enum vregs {
- VREG_CORE,
- VREG_MEM,
- VREG_DIG,
- VREG_HFPLL_A,
- VREG_HFPLL_B,
- NUM_VREG
-};
-
-enum hfpll_vdd_levels {
- HFPLL_VDD_NONE,
- HFPLL_VDD_LOW,
- HFPLL_VDD_NOM
-};
-
-enum pvs {
- PVS_SLOW,
- PVS_NOM,
- PVS_FAST,
- PVS_FASTER,
- NUM_PVS
-};
-
-struct vreg {
- const char name[15];
- const unsigned int max_vdd;
- const int rpm_vreg_voter;
- const int rpm_vreg_id;
- struct regulator *reg;
- unsigned int cur_vdd;
-};
-
-struct core_speed {
- unsigned int khz;
- int src;
- unsigned int pri_src_sel;
- unsigned int sec_src_sel;
- unsigned int pll_l_val;
-};
-
-struct l2_level {
- struct core_speed speed;
- unsigned int vdd_dig;
- unsigned int vdd_mem;
- unsigned int bw_level;
-};
-
-struct acpu_level {
- unsigned int use_for_scaling;
- struct core_speed speed;
- struct l2_level *l2_level;
- unsigned int vdd_core;
-};
-
-struct scalable {
- void * __iomem const hfpll_base;
- void * __iomem const aux_clk_sel;
- const uint32_t l2cpmr_iaddr;
- struct core_speed *current_speed;
- struct l2_level *l2_vote;
- struct vreg vreg[NUM_VREG];
- unsigned int *hfpll_vdd_tbl;
- bool regulators_initialized;
- bool clocks_initialized;
-};
-
-static unsigned int hfpll_vdd_tbl_8960[] = {
- [HFPLL_VDD_NONE] = 0,
- [HFPLL_VDD_LOW] = 850000,
- [HFPLL_VDD_NOM] = 1050000
-};
-
-static unsigned int hfpll_vdd_tbl_8064[] = {
- [HFPLL_VDD_NONE] = 0,
- [HFPLL_VDD_LOW] = 945000,
- [HFPLL_VDD_NOM] = 1050000
-};
-
-static struct scalable scalable_8960[] = {
+static struct scalable scalable[] __initdata = {
[CPU0] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x200,
- .aux_clk_sel = MSM_ACC0_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait0", 1300000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", 1150000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_A] = { "hfpll0_s8", 2100000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_S8 },
- .vreg[VREG_HFPLL_B] = { "hfpll0_l23", 1800000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_L23 },
- },
+ .hfpll_phys_base = 0x00903200,
+ .aux_clk_sel_phys = 0x02088014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x4501,
+ .vreg[VREG_CORE] = { "krait0", 1300000, 3200000 },
+ .vreg[VREG_MEM] = { "krait0_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait0_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait0_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "krait0_l23", 1800000 },
+ },
[CPU1] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x300,
- .aux_clk_sel = MSM_ACC1_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait1", 1300000 },
- .vreg[VREG_MEM] = { "krait1_mem", 1150000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait1_dig", 1150000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_A] = { "hfpll1_s8", 2100000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_S8 },
- .vreg[VREG_HFPLL_B] = { "hfpll1_l23", 1800000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_L23 },
- },
+ .hfpll_phys_base = 0x00903300,
+ .aux_clk_sel_phys = 0x02098014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x5501,
+ .vreg[VREG_CORE] = { "krait1", 1300000, 3200000 },
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait1_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "krait1_l23", 1800000 },
+ },
[L2] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x400,
- .hfpll_vdd_tbl = hfpll_vdd_tbl_8960,
- .aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
- .l2cpmr_iaddr = L2CPMR_IADDR,
- .vreg[VREG_HFPLL_A] = { "hfpll_l2_s8", 2100000,
- RPM_VREG_VOTER6,
- RPM_VREG_ID_PM8921_S8 },
- .vreg[VREG_HFPLL_B] = { "hfpll_l2_l23", 1800000,
- RPM_VREG_VOTER6,
- RPM_VREG_ID_PM8921_L23 },
- },
+ .hfpll_phys_base = 0x00903400,
+ .aux_clk_sel_phys = 0x02011028,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x0500,
+ .vreg[VREG_HFPLL_A] = { "l2_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "l2_l23", 1800000 },
+ },
};
-static DEFINE_MUTEX(driver_lock);
-static DEFINE_SPINLOCK(l2_lock);
-
-static struct scalable scalable_8064[] = {
- [CPU0] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x200,
- .aux_clk_sel = MSM_ACC0_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait0", 1300000 },
- .vreg[VREG_MEM] = { "krait0_mem", 1150000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait0_dig", 1150000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
- RPM_VREG_VOTER1,
- RPM_VREG_ID_PM8921_LVS7 },
- },
- [CPU1] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x240,
- .aux_clk_sel = MSM_ACC1_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait1", 1300000 },
- .vreg[VREG_MEM] = { "krait1_mem", 1150000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait1_dig", 1150000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
- RPM_VREG_VOTER2,
- RPM_VREG_ID_PM8921_LVS7 },
- },
- [CPU2] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x280,
- .aux_clk_sel = MSM_ACC2_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait2", 1300000 },
- .vreg[VREG_MEM] = { "krait2_mem", 1150000,
- RPM_VREG_VOTER4,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait2_dig", 1150000,
- RPM_VREG_VOTER4,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll2", 1800000,
- RPM_VREG_VOTER4,
- RPM_VREG_ID_PM8921_LVS7 },
- },
- [CPU3] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x2C0,
- .aux_clk_sel = MSM_ACC3_BASE + 0x014,
- .l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait3", 1300000 },
- .vreg[VREG_MEM] = { "krait3_mem", 1150000,
- RPM_VREG_VOTER5,
- RPM_VREG_ID_PM8921_L24 },
- .vreg[VREG_DIG] = { "krait3_dig", 1150000,
- RPM_VREG_VOTER5,
- RPM_VREG_ID_PM8921_S3 },
- .vreg[VREG_HFPLL_B] = { "hfpll3", 1800000,
- RPM_VREG_VOTER5,
- RPM_VREG_ID_PM8921_LVS7 },
- },
- [L2] = {
- .hfpll_base = MSM_HFPLL_BASE + 0x300,
- .hfpll_vdd_tbl = hfpll_vdd_tbl_8064,
- .aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
- .l2cpmr_iaddr = L2CPMR_IADDR,
- .vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
- RPM_VREG_VOTER6,
- RPM_VREG_ID_PM8921_LVS7 },
- },
-};
-
-static struct l2_level *l2_freq_tbl;
-static struct acpu_level *acpu_freq_tbl;
-static int l2_freq_tbl_size;
-static struct scalable *scalable;
-#define SCALABLE_TO_CPU(sc) ((sc) - scalable)
-
-/* Instantaneous bandwidth requests in MB/s. */
-#define BW_MBPS(_bw) \
- { \
- .vectors = (struct msm_bus_vectors[]){ \
- {\
- .src = MSM_BUS_MASTER_AMPSS_M0, \
- .dst = MSM_BUS_SLAVE_EBI_CH0, \
- .ib = (_bw) * 1000000UL, \
- .ab = (_bw) * 100000UL, \
- }, \
- { \
- .src = MSM_BUS_MASTER_AMPSS_M1, \
- .dst = MSM_BUS_SLAVE_EBI_CH0, \
- .ib = (_bw) * 1000000UL, \
- .ab = (_bw) * 100000UL, \
- }, \
- }, \
- .num_paths = 2, \
- }
-static struct msm_bus_paths bw_level_tbl[] = {
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
[0] = BW_MBPS(640), /* At least 80 MHz on bus. */
[1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
[2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
@@ -329,70 +78,16 @@
[4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
[5] = BW_MBPS(3600), /* At least 450 MHz on bus. */
[6] = BW_MBPS(3936), /* At least 492 MHz on bus. */
- [7] = BW_MBPS(4264), /* At least 533 MHz on bus. */
};
-static struct msm_bus_scale_pdata bus_client_pdata = {
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
.usecase = bw_level_tbl,
.num_usecases = ARRAY_SIZE(bw_level_tbl),
.active_only = 1,
- .name = "acpuclock",
+ .name = "acpuclk-8960",
};
-static uint32_t bus_perf_client;
-
-/* TODO: Update vdd_dig and vdd_mem when voltage data is available. */
-#define L2(x) (&l2_freq_tbl_8960_kraitv1[(x)])
-static struct l2_level l2_freq_tbl_8960_kraitv1[] = {
- [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
- [1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
- [2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 1 },
- [3] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 1 },
- [4] = { { 540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 1 },
- [5] = { { 594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
- [6] = { { 648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 2 },
- [7] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 2 },
- [8] = { { 756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 2 },
- [9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 3 },
- [10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 3 },
- [11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
-};
-
-static struct acpu_level acpu_freq_tbl_8960_kraitv1_slow[] = {
- { 0, {STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 925000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 925000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 937500 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 962500 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 987500 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1000000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1062500 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1062500 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1087500 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8960_kraitv1_nom_fast[] = {
- { 0, {STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 862500 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 862500 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 862500 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 887500 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 900000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 925000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 925000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 937500 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 962500 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1012500 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1025000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1025000 },
- { 0, { 0 } }
-};
-
-#undef L2
-#define L2(x) (&l2_freq_tbl_8960_kraitv2[(x)])
-static struct l2_level l2_freq_tbl_8960_kraitv2[] = {
+static struct l2_level l2_freq_tbl[] __initdata = {
[0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
[1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
[2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
@@ -415,7 +110,7 @@
[19] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 6 },
};
-static struct acpu_level acpu_freq_tbl_8960_kraitv2_slow[] = {
+static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
{ 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 975000 },
@@ -442,7 +137,7 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_freq_tbl_8960_kraitv2_nom[] = {
+static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
{ 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 925000 },
@@ -469,7 +164,7 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_freq_tbl_8960_kraitv2_fast[] = {
+static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 850000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 850000 },
{ 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 875000 },
@@ -496,935 +191,26 @@
{ 0, { 0 } }
};
-/* TODO: Update vdd_dig and vdd_mem when voltage data is available. */
-#undef L2
-#define L2(x) (&l2_freq_tbl_8064[(x)])
-static struct l2_level l2_freq_tbl_8064[] = {
- [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
- [1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
- [2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
- [3] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 2 },
- [4] = { { 540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 2 },
- [5] = { { 594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
- [6] = { { 648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 4 },
- [7] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 4 },
- [8] = { { 756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 4 },
- [9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 4 },
- [10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 4 },
- [11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 7 },
- [12] = { { 972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 7 },
- [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 7 },
- [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 7 },
- [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 7 },
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+ [PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow) },
+ [PVS_NOMINAL] = { acpu_freq_tbl_nom, sizeof(acpu_freq_tbl_nom) },
+ [PVS_FAST] = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
};
-/* TODO: Update core voltages when data is available. */
-static struct acpu_level acpu_freq_tbl_8064_slow[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
- { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 975000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 975000 },
- { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 1000000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 1000000 },
- { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 1025000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 1025000 },
- { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1075000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1075000 },
- { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1100000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1100000 },
- { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1125000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1125000 },
- { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1175000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1175000 },
- { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1200000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1200000 },
- { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1225000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1225000 },
- { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1237500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1237500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1250000 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8064_nom[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
- { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 925000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 925000 },
- { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 950000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 950000 },
- { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 975000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 975000 },
- { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1025000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1025000 },
- { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1050000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1050000 },
- { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1075000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1075000 },
- { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1125000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1125000 },
- { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1150000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1150000 },
- { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1175000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1175000 },
- { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1187500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1187500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1200000 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8064_fast[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 850000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 850000 },
- { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 875000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 875000 },
- { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 900000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 900000 },
- { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 925000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 925000 },
- { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 975000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 975000 },
- { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1000000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1000000 },
- { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1025000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1025000 },
- { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1075000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1075000 },
- { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1100000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1100000 },
- { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1125000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1125000 },
- { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1137500 },
- { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1137500 },
- { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1150000 },
- { 0, { 0 } }
-};
-
-static struct acpu_level *acpu_freq_tbl_8960_v1[NUM_PVS] __initdata = {
- [PVS_SLOW] = acpu_freq_tbl_8960_kraitv1_slow,
- [PVS_NOM] = acpu_freq_tbl_8960_kraitv1_nom_fast,
- [PVS_FAST] = acpu_freq_tbl_8960_kraitv1_nom_fast,
-};
-
-static struct acpu_level *acpu_freq_tbl_8960_v2[NUM_PVS] __initdata = {
- [PVS_SLOW] = acpu_freq_tbl_8960_kraitv2_slow,
- [PVS_NOM] = acpu_freq_tbl_8960_kraitv2_nom,
- [PVS_FAST] = acpu_freq_tbl_8960_kraitv2_fast,
-};
-
-/* TODO: update the faster table when data is available */
-static struct acpu_level *acpu_freq_tbl_8064[NUM_PVS] __initdata = {
- [PVS_SLOW] = acpu_freq_tbl_8064_slow,
- [PVS_NOM] = acpu_freq_tbl_8064_nom,
- [PVS_FAST] = acpu_freq_tbl_8064_fast,
- [PVS_FASTER] = acpu_freq_tbl_8064_fast,
-};
-
-static struct acpu_level *max_acpu_level;
-
-static unsigned long acpuclk_8960_get_rate(int cpu)
-{
- return scalable[cpu].current_speed->khz;
-}
-
-/* Get the selected source on primary MUX. */
-static int get_pri_clk_src(struct scalable *sc)
-{
- uint32_t regval;
-
- regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- return regval & 0x3;
-}
-
-/* Set the selected source on primary MUX. */
-static void set_pri_clk_src(struct scalable *sc, uint32_t pri_src_sel)
-{
- uint32_t regval;
-
- regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- regval &= ~0x3;
- regval |= (pri_src_sel & 0x3);
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
- /* Wait for switch to complete. */
- mb();
- udelay(1);
-}
-
-/* Get the selected source on secondary MUX. */
-static int get_sec_clk_src(struct scalable *sc)
-{
- uint32_t regval;
-
- regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- return (regval >> 2) & 0x3;
-}
-
-/* Set the selected source on secondary MUX. */
-static void set_sec_clk_src(struct scalable *sc, uint32_t sec_src_sel)
-{
- uint32_t regval;
-
- /* Disable secondary source clock gating during switch. */
- regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- regval |= SECCLKAGD;
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
- /* Program the MUX. */
- regval &= ~(0x3 << 2);
- regval |= ((sec_src_sel & 0x3) << 2);
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
- /* Wait for switch to complete. */
- mb();
- udelay(1);
-
- /* Re-enable secondary source clock gating. */
- regval &= ~SECCLKAGD;
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-}
-
-/* Enable an already-configured HFPLL. */
-static void hfpll_enable(struct scalable *sc, bool skip_regulators)
-{
- int rc;
-
- if (!skip_regulators) {
- if (cpu_is_msm8960()) {
- rc = rpm_vreg_set_voltage(
- sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
- sc->vreg[VREG_HFPLL_A].rpm_vreg_voter,
- 2050000,
- sc->vreg[VREG_HFPLL_A].max_vdd, 0);
- if (rc)
- pr_err("%s regulator enable failed (%d)\n",
- sc->vreg[VREG_HFPLL_A].name, rc);
- }
- rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
- sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 1800000,
- sc->vreg[VREG_HFPLL_B].max_vdd, 0);
- if (rc)
- pr_err("%s regulator enable failed (%d)\n",
- sc->vreg[VREG_HFPLL_B].name, rc);
- }
- /* Disable PLL bypass mode. */
- writel_relaxed(0x2, sc->hfpll_base + HFPLL_MODE);
-
- /*
- * H/W requires a 5us delay between disabling the bypass and
- * de-asserting the reset. Delay 10us just to be safe.
- */
- mb();
- udelay(10);
-
- /* De-assert active-low PLL reset. */
- writel_relaxed(0x6, sc->hfpll_base + HFPLL_MODE);
-
- /* Wait for PLL to lock. */
- mb();
- udelay(60);
-
- /* Enable PLL output. */
- writel_relaxed(0x7, sc->hfpll_base + HFPLL_MODE);
-}
-
-/* Disable a HFPLL for power-savings or while its being reprogrammed. */
-static void hfpll_disable(struct scalable *sc, bool skip_regulators)
-{
- int rc;
-
- /*
- * Disable the PLL output, disable test mode, enable
- * the bypass mode, and assert the reset.
- */
- writel_relaxed(0, sc->hfpll_base + HFPLL_MODE);
-
- if (!skip_regulators) {
- rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
- sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 0,
- 0, 0);
- if (rc)
- pr_err("%s regulator enable failed (%d)\n",
- sc->vreg[VREG_HFPLL_B].name, rc);
-
- if (cpu_is_msm8960()) {
- rc = rpm_vreg_set_voltage(
- sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
- sc->vreg[VREG_HFPLL_A].rpm_vreg_voter,
- 0, 0, 0);
- if (rc)
- pr_err("%s regulator enable failed (%d)\n",
- sc->vreg[VREG_HFPLL_A].name, rc);
- }
- }
-}
-
-/* Program the HFPLL rate. Assumes HFPLL is already disabled. */
-static void hfpll_set_rate(struct scalable *sc, struct core_speed *tgt_s)
-{
- writel_relaxed(tgt_s->pll_l_val, sc->hfpll_base + HFPLL_L_VAL);
-}
-
-/* Return the L2 speed that should be applied. */
-static struct l2_level *compute_l2_level(struct scalable *sc,
- struct l2_level *vote_l)
-{
- struct l2_level *new_l;
- int cpu;
-
- /* Bounds check. */
- BUG_ON(vote_l >= (l2_freq_tbl + l2_freq_tbl_size));
-
- /* Find max L2 speed vote. */
- sc->l2_vote = vote_l;
- new_l = l2_freq_tbl;
- for_each_present_cpu(cpu)
- new_l = max(new_l, scalable[cpu].l2_vote);
-
- return new_l;
-}
-
-/* Update the bus bandwidth request. */
-static void set_bus_bw(unsigned int bw)
-{
- int ret;
-
- /* Bounds check. */
- if (bw >= ARRAY_SIZE(bw_level_tbl)) {
- pr_err("invalid bandwidth request (%d)\n", bw);
- return;
- }
-
- /* Update bandwidth if request has changed. This may sleep. */
- ret = msm_bus_scale_client_update_request(bus_perf_client, bw);
- if (ret)
- pr_err("bandwidth request failed (%d)\n", ret);
-}
-
-/* Set the CPU or L2 clock speed. */
-static void set_speed(struct scalable *sc, struct core_speed *tgt_s,
- enum setrate_reason reason)
-{
- struct core_speed *strt_s = sc->current_speed;
-
- if (tgt_s == strt_s)
- return;
-
- if (strt_s->src == HFPLL && tgt_s->src == HFPLL) {
- /*
- * Move to an always-on source running at a frequency that does
- * not require an elevated CPU voltage. PLL8 is used here.
- */
- set_sec_clk_src(sc, SEC_SRC_SEL_AUX);
- set_pri_clk_src(sc, PRI_SRC_SEL_SEC_SRC);
-
- /* Program CPU HFPLL. */
- hfpll_disable(sc, 1);
- hfpll_set_rate(sc, tgt_s);
- hfpll_enable(sc, 1);
-
- /* Move CPU to HFPLL source. */
- set_pri_clk_src(sc, tgt_s->pri_src_sel);
- } else if (strt_s->src == HFPLL && tgt_s->src != HFPLL) {
- /*
- * If responding to CPU_DEAD we must be running on another CPU.
- * Therefore, we can't access the downed CPU's clock MUX CP15
- * registers from here and can't change clock sources. If the
- * CPU is collapsed, however, it is still safe to turn off the
- * PLL without switching the MUX away from it.
- */
- if (reason != SETRATE_HOTPLUG || sc == &scalable[L2]) {
- set_sec_clk_src(sc, tgt_s->sec_src_sel);
- set_pri_clk_src(sc, tgt_s->pri_src_sel);
- hfpll_disable(sc, 0);
- } else if (reason == SETRATE_HOTPLUG
- && msm_pm_verify_cpu_pc(SCALABLE_TO_CPU(sc))) {
- hfpll_disable(sc, 0);
- }
- } else if (strt_s->src != HFPLL && tgt_s->src == HFPLL) {
- /*
- * If responding to CPU_UP_PREPARE, we can't change CP15
- * registers for the CPU that's coming up since we're not
- * running on that CPU. That's okay though, since the MUX
- * source was not changed on the way down, either.
- */
- if (reason != SETRATE_HOTPLUG || sc == &scalable[L2]) {
- hfpll_set_rate(sc, tgt_s);
- hfpll_enable(sc, 0);
- set_pri_clk_src(sc, tgt_s->pri_src_sel);
- } else if (reason == SETRATE_HOTPLUG
- && msm_pm_verify_cpu_pc(SCALABLE_TO_CPU(sc))) {
- /* PLL was disabled during hot-unplug. Re-enable it. */
- hfpll_set_rate(sc, tgt_s);
- hfpll_enable(sc, 0);
- }
- } else {
- if (reason != SETRATE_HOTPLUG || sc == &scalable[L2])
- set_sec_clk_src(sc, tgt_s->sec_src_sel);
- }
-
- sc->current_speed = tgt_s;
-}
-
-/* Apply any per-cpu voltage increases. */
-static int increase_vdd(int cpu, unsigned int vdd_core, unsigned int vdd_mem,
- unsigned int vdd_dig, enum setrate_reason reason)
-{
- struct scalable *sc = &scalable[cpu];
- int rc = 0;
-
- /*
- * Increase vdd_mem active-set before vdd_dig.
- * vdd_mem should be >= vdd_dig.
- */
- if (vdd_mem > sc->vreg[VREG_MEM].cur_vdd) {
- rc = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
- sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
- sc->vreg[VREG_MEM].max_vdd, 0);
- if (rc) {
- pr_err("%s increase failed (%d)\n",
- sc->vreg[VREG_MEM].name, rc);
- return rc;
- }
- sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
- }
-
- /* Increase vdd_dig active-set vote. */
- if (vdd_dig > sc->vreg[VREG_DIG].cur_vdd) {
- rc = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
- sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
- sc->vreg[VREG_DIG].max_vdd, 0);
- if (rc) {
- pr_err("%s increase failed (%d)\n",
- sc->vreg[VREG_DIG].name, rc);
- return rc;
- }
- sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
- }
-
- /*
- * Update per-CPU core voltage. Don't do this for the hotplug path for
- * which it should already be correct. Attempting to set it is bad
- * because we don't know what CPU we are running on at this point, but
- * the CPU regulator API requires we call it from the affected CPU.
- */
- if (vdd_core > sc->vreg[VREG_CORE].cur_vdd
- && reason != SETRATE_HOTPLUG) {
- rc = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
- sc->vreg[VREG_CORE].max_vdd);
- if (rc) {
- pr_err("%s increase failed (%d)\n",
- sc->vreg[VREG_CORE].name, rc);
- return rc;
- }
- sc->vreg[VREG_CORE].cur_vdd = vdd_core;
- }
-
- return rc;
-}
-
-/* Apply any per-cpu voltage decreases. */
-static void decrease_vdd(int cpu, unsigned int vdd_core, unsigned int vdd_mem,
- unsigned int vdd_dig, enum setrate_reason reason)
-{
- struct scalable *sc = &scalable[cpu];
- int ret;
-
- /*
- * Update per-CPU core voltage. This must be called on the CPU
- * that's being affected. Don't do this in the hotplug remove path,
- * where the rail is off and we're executing on the other CPU.
- */
- if (vdd_core < sc->vreg[VREG_CORE].cur_vdd
- && reason != SETRATE_HOTPLUG) {
- ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
- sc->vreg[VREG_CORE].max_vdd);
- if (ret) {
- pr_err("%s decrease failed (%d)\n",
- sc->vreg[VREG_CORE].name, ret);
- return;
- }
- sc->vreg[VREG_CORE].cur_vdd = vdd_core;
- }
-
- /* Decrease vdd_dig active-set vote. */
- if (vdd_dig < sc->vreg[VREG_DIG].cur_vdd) {
- ret = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
- sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
- sc->vreg[VREG_DIG].max_vdd, 0);
- if (ret) {
- pr_err("%s decrease failed (%d)\n",
- sc->vreg[VREG_DIG].name, ret);
- return;
- }
- sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
- }
-
- /*
- * Decrease vdd_mem active-set after vdd_dig.
- * vdd_mem should be >= vdd_dig.
- */
- if (vdd_mem < sc->vreg[VREG_MEM].cur_vdd) {
- ret = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
- sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
- sc->vreg[VREG_MEM].max_vdd, 0);
- if (ret) {
- pr_err("%s decrease failed (%d)\n",
- sc->vreg[VREG_MEM].name, ret);
- return;
- }
- sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
- }
-}
-
-static unsigned int calculate_vdd_mem(struct acpu_level *tgt)
-{
- return tgt->l2_level->vdd_mem;
-}
-
-static unsigned int calculate_vdd_dig(struct acpu_level *tgt)
-{
- unsigned int pll_vdd_dig;
-
- if (tgt->l2_level->speed.src != HFPLL)
- pll_vdd_dig = scalable[L2].hfpll_vdd_tbl[HFPLL_VDD_NONE];
- else if (tgt->l2_level->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
- pll_vdd_dig = scalable[L2].hfpll_vdd_tbl[HFPLL_VDD_NOM];
- else
- pll_vdd_dig = scalable[L2].hfpll_vdd_tbl[HFPLL_VDD_LOW];
-
- return max(tgt->l2_level->vdd_dig, pll_vdd_dig);
-}
-
-static unsigned int calculate_vdd_core(struct acpu_level *tgt)
-{
- return tgt->vdd_core;
-}
-
-/* Set the CPU's clock rate and adjust the L2 rate, if appropriate. */
-static int acpuclk_8960_set_rate(int cpu, unsigned long rate,
- enum setrate_reason reason)
-{
- struct core_speed *strt_acpu_s, *tgt_acpu_s;
- struct l2_level *tgt_l2_l;
- struct acpu_level *tgt;
- unsigned int vdd_mem, vdd_dig, vdd_core;
- unsigned long flags;
- int rc = 0;
-
- if (cpu > num_possible_cpus())
- return -EINVAL;
-
- if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
- mutex_lock(&driver_lock);
-
- strt_acpu_s = scalable[cpu].current_speed;
-
- /* Return early if rate didn't change. */
- if (rate == strt_acpu_s->khz)
- goto out;
-
- /* Find target frequency. */
- for (tgt = acpu_freq_tbl; tgt->speed.khz != 0; tgt++) {
- if (tgt->speed.khz == rate) {
- tgt_acpu_s = &tgt->speed;
- break;
- }
- }
- if (tgt->speed.khz == 0) {
- rc = -EINVAL;
- goto out;
- }
-
- /* Calculate voltage requirements for the current CPU. */
- vdd_mem = calculate_vdd_mem(tgt);
- vdd_dig = calculate_vdd_dig(tgt);
- vdd_core = calculate_vdd_core(tgt);
-
- /* Increase VDD levels if needed. */
- if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG) {
- rc = increase_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
- if (rc)
- goto out;
- }
-
- pr_debug("Switching from ACPU%d rate %u KHz -> %u KHz\n",
- cpu, strt_acpu_s->khz, tgt_acpu_s->khz);
-
- /* Set the CPU speed. */
- set_speed(&scalable[cpu], tgt_acpu_s, reason);
-
- /*
- * Update the L2 vote and apply the rate change. A spinlock is
- * necessary to ensure L2 rate is calulated and set atomically,
- * even if acpuclk_8960_set_rate() is called from an atomic context
- * and the driver_lock mutex is not acquired.
- */
- spin_lock_irqsave(&l2_lock, flags);
- tgt_l2_l = compute_l2_level(&scalable[cpu], tgt->l2_level);
- set_speed(&scalable[L2], &tgt_l2_l->speed, reason);
- spin_unlock_irqrestore(&l2_lock, flags);
-
- /* Nothing else to do for power collapse or SWFI. */
- if (reason == SETRATE_PC || reason == SETRATE_SWFI)
- goto out;
-
- /* Update bus bandwith request. */
- set_bus_bw(tgt_l2_l->bw_level);
-
- /* Drop VDD levels if we can. */
- decrease_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
-
- pr_debug("ACPU%d speed change complete\n", cpu);
-
-out:
- if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
- mutex_unlock(&driver_lock);
- return rc;
-}
-
-/* Initialize a HFPLL at a given rate and enable it. */
-static void __cpuinit hfpll_init(struct scalable *sc, struct core_speed *tgt_s)
-{
- pr_debug("Initializing HFPLL%d\n", sc - scalable);
-
- /* Disable the PLL for re-programming. */
- hfpll_disable(sc, 1);
-
- /* Configure PLL parameters for integer mode. */
- writel_relaxed(0x7845C665, sc->hfpll_base + HFPLL_CONFIG_CTL);
- writel_relaxed(0, sc->hfpll_base + HFPLL_M_VAL);
- writel_relaxed(1, sc->hfpll_base + HFPLL_N_VAL);
-
- /* Program droop controller. */
- writel_relaxed(0x0108C000, sc->hfpll_base + HFPLL_DROOP_CTL);
-
- /* Set an initial rate and enable the PLL. */
- hfpll_set_rate(sc, tgt_s);
- hfpll_enable(sc, 0);
-}
-
-/* Voltage regulator initialization. */
-static void __cpuinit regulator_init(int cpu, struct acpu_level *lvl)
-{
- int ret;
- struct scalable *sc = &scalable[cpu];
- unsigned int vdd_mem, vdd_dig, vdd_core;
-
- vdd_mem = calculate_vdd_mem(lvl);
- vdd_dig = calculate_vdd_dig(lvl);
-
- /* Set initial vdd_mem vote. */
- ret = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
- sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
- sc->vreg[VREG_MEM].max_vdd, 0);
- if (ret) {
- pr_err("%s initialization failed (%d)\n",
- sc->vreg[VREG_MEM].name, ret);
- BUG();
- }
- sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
-
- /* Set initial vdd_dig vote. */
- ret = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
- sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
- sc->vreg[VREG_DIG].max_vdd, 0);
- if (ret) {
- pr_err("%s initialization failed (%d)\n",
- sc->vreg[VREG_DIG].name, ret);
- BUG();
- }
- sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
-
- /* Setup Krait CPU regulators and initial core voltage. */
- sc->vreg[VREG_CORE].reg = regulator_get(NULL,
- sc->vreg[VREG_CORE].name);
- if (IS_ERR(sc->vreg[VREG_CORE].reg)) {
- pr_err("regulator_get(%s) failed (%ld)\n",
- sc->vreg[VREG_CORE].name,
- PTR_ERR(sc->vreg[VREG_CORE].reg));
- BUG();
- }
- vdd_core = calculate_vdd_core(lvl);
- ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
- sc->vreg[VREG_CORE].max_vdd);
- if (ret) {
- pr_err("%s initialization failed (%d)\n",
- sc->vreg[VREG_CORE].name, ret);
- BUG();
- }
- sc->vreg[VREG_CORE].cur_vdd = vdd_core;
- ret = regulator_enable(sc->vreg[VREG_CORE].reg);
- if (ret) {
- pr_err("regulator_enable(%s) failed (%d)\n",
- sc->vreg[VREG_CORE].name, ret);
- BUG();
- }
- sc->regulators_initialized = true;
-}
-
-/* Set initial rate for a given core. */
-static void __cpuinit init_clock_sources(struct scalable *sc,
- struct core_speed *tgt_s)
-{
- uint32_t regval;
-
- /* Select PLL8 as AUX source input to the secondary MUX. */
- writel_relaxed(0x3, sc->aux_clk_sel);
-
- /* Switch away from the HFPLL while it's re-initialized. */
- set_sec_clk_src(sc, SEC_SRC_SEL_AUX);
- set_pri_clk_src(sc, PRI_SRC_SEL_SEC_SRC);
- hfpll_init(sc, tgt_s);
-
- /* Set PRI_SRC_SEL_HFPLL_DIV2 divider to div-2. */
- regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- regval &= ~(0x3 << 6);
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
- /* Switch to the target clock source. */
- set_sec_clk_src(sc, tgt_s->sec_src_sel);
- set_pri_clk_src(sc, tgt_s->pri_src_sel);
- sc->current_speed = tgt_s;
-}
-
-static void __cpuinit per_cpu_init(void *data)
-{
- int cpu = smp_processor_id();
-
- init_clock_sources(&scalable[cpu], &max_acpu_level->speed);
- scalable[cpu].l2_vote = max_acpu_level->l2_level;
- scalable[cpu].clocks_initialized = true;
-}
-
-/* Register with bus driver. */
-static void __init bus_init(unsigned int init_bw)
-{
- int ret;
-
- bus_perf_client = msm_bus_scale_register_client(&bus_client_pdata);
- if (!bus_perf_client) {
- pr_err("unable to register bus client\n");
- BUG();
- }
-
- ret = msm_bus_scale_client_update_request(bus_perf_client, init_bw);
- if (ret)
- pr_err("initial bandwidth request failed (%d)\n", ret);
-}
-
-#ifdef CONFIG_CPU_FREQ_MSM
-static struct cpufreq_frequency_table freq_table[NR_CPUS][30];
-
-static void __init cpufreq_table_init(void)
-{
- int cpu;
-
- for_each_possible_cpu(cpu) {
- int i, freq_cnt = 0;
- /* Construct the freq_table tables from acpu_freq_tbl. */
- for (i = 0; acpu_freq_tbl[i].speed.khz != 0
- && freq_cnt < ARRAY_SIZE(*freq_table); i++) {
- if (acpu_freq_tbl[i].use_for_scaling) {
- freq_table[cpu][freq_cnt].index = freq_cnt;
- freq_table[cpu][freq_cnt].frequency
- = acpu_freq_tbl[i].speed.khz;
- freq_cnt++;
- }
- }
- /* freq_table not big enough to store all usable freqs. */
- BUG_ON(acpu_freq_tbl[i].speed.khz != 0);
-
- freq_table[cpu][freq_cnt].index = freq_cnt;
- freq_table[cpu][freq_cnt].frequency = CPUFREQ_TABLE_END;
-
- pr_info("CPU%d: %d scaling frequencies supported.\n",
- cpu, freq_cnt);
-
- /* Register table with CPUFreq. */
- cpufreq_frequency_table_get_attr(freq_table[cpu], cpu);
- }
-}
-#else
-static void __init cpufreq_table_init(void) {}
-#endif
-
-#define HOT_UNPLUG_KHZ STBY_KHZ
-static int __cpuinit acpuclock_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- static int prev_khz[NR_CPUS];
- static int prev_pri_src[NR_CPUS];
- static int prev_sec_src[NR_CPUS];
- int cpu = (int)hcpu;
-
- switch (action) {
- case CPU_DYING:
- case CPU_DYING_FROZEN:
- /*
- * On Krait v1 and 8064v1, the primary and secondary muxes must
- * be set to QSB before L2 power collapse and restored after.
- */
- if (cpu_is_krait_v1() || cpu_is_apq8064()) {
- prev_sec_src[cpu] = get_sec_clk_src(&scalable[cpu]);
- prev_pri_src[cpu] = get_pri_clk_src(&scalable[cpu]);
- set_sec_clk_src(&scalable[cpu], SEC_SRC_SEL_QSB);
- set_pri_clk_src(&scalable[cpu], PRI_SRC_SEL_SEC_SRC);
- }
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- prev_khz[cpu] = acpuclk_8960_get_rate(cpu);
- /* Fall through. */
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
- if (scalable[cpu].clocks_initialized)
- acpuclk_8960_set_rate(cpu, HOT_UNPLUG_KHZ,
- SETRATE_HOTPLUG);
- break;
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- if (scalable[cpu].clocks_initialized)
- acpuclk_8960_set_rate(cpu, prev_khz[cpu],
- SETRATE_HOTPLUG);
- if (!scalable[cpu].regulators_initialized)
- regulator_init(cpu, max_acpu_level);
- break;
- case CPU_STARTING:
- case CPU_STARTING_FROZEN:
- if (!scalable[cpu].clocks_initialized) {
- per_cpu_init(NULL);
- } else if (cpu_is_krait_v1() || cpu_is_apq8064()) {
- set_sec_clk_src(&scalable[cpu], prev_sec_src[cpu]);
- set_pri_clk_src(&scalable[cpu], prev_pri_src[cpu]);
- }
- break;
- default:
- break;
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block __cpuinitdata acpuclock_cpu_notifier = {
- .notifier_call = acpuclock_cpu_callback,
-};
-
-static const int krait_needs_vmin(void)
-{
- switch (read_cpuid_id()) {
- case 0x511F04D0:
- case 0x511F04D1:
- case 0x510F06F0:
- return 1;
- default:
- return 0;
- };
-}
-
-static void kraitv2_apply_vmin(struct acpu_level *tbl)
-{
- for (; tbl->speed.khz != 0; tbl++)
- if (tbl->vdd_core < 1150000)
- tbl->vdd_core = 1150000;
-}
-
-static enum pvs __init get_pvs(void)
-{
- uint32_t pte_efuse, pvs;
-
- pte_efuse = readl_relaxed(QFPROM_PTE_EFUSE_ADDR);
- pvs = (pte_efuse >> 10) & 0x7;
- if (pvs == 0x7)
- pvs = (pte_efuse >> 13) & 0x7;
-
- switch (pvs) {
- case 0x0:
- case 0x7:
- pr_info("ACPU PVS: Slow\n");
- return PVS_SLOW;
- case 0x1:
- pr_info("ACPU PVS: Nominal\n");
- return PVS_NOM;
- case 0x3:
- pr_info("ACPU PVS: Fast\n");
- return PVS_FAST;
- case 0x4:
- if (cpu_is_apq8064()) {
- pr_info("ACPU PVS: Faster\n");
- return PVS_FASTER;
- }
- default:
- pr_warn("ACPU PVS: Unknown. Defaulting to slow\n");
- return PVS_SLOW;
- }
-}
-
-static void __init select_freq_plan(void)
-{
- struct acpu_level *l;
-
- /* Select frequency tables. */
- if (cpu_is_msm8960()) {
- enum pvs pvs_id = get_pvs();
-
- scalable = scalable_8960;
- if (cpu_is_krait_v1()) {
- acpu_freq_tbl = acpu_freq_tbl_8960_v1[pvs_id];
- l2_freq_tbl = l2_freq_tbl_8960_kraitv1;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv1);
- } else {
- acpu_freq_tbl = acpu_freq_tbl_8960_v2[pvs_id];
- l2_freq_tbl = l2_freq_tbl_8960_kraitv2;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv2);
- }
- } else if (cpu_is_apq8064()) {
- enum pvs pvs_id = get_pvs();
-
- scalable = scalable_8064;
- acpu_freq_tbl = acpu_freq_tbl_8064[pvs_id];
- l2_freq_tbl = l2_freq_tbl_8064;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8064);
- } else {
- BUG();
- }
- BUG_ON(!acpu_freq_tbl);
- if (krait_needs_vmin())
- kraitv2_apply_vmin(acpu_freq_tbl);
-
- /* Find the max supported scaling frequency. */
- for (l = acpu_freq_tbl; l->speed.khz != 0; l++)
- if (l->use_for_scaling)
- max_acpu_level = l;
- BUG_ON(!max_acpu_level);
- pr_info("Max ACPU freq: %u KHz\n", max_acpu_level->speed.khz);
-}
-
-static struct acpuclk_data acpuclk_8960_data = {
- .set_rate = acpuclk_8960_set_rate,
- .get_rate = acpuclk_8960_get_rate,
- .power_collapse_khz = STBY_KHZ,
- .wait_for_irq_khz = STBY_KHZ,
+static struct acpuclk_krait_params acpuclk_8960_params __initdata = {
+ .scalable = scalable,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
+ .l2_freq_tbl = l2_freq_tbl,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
+ .qfprom_phys_base = 0x00700000,
};
static int __init acpuclk_8960_probe(struct platform_device *pdev)
{
- int cpu;
-
- select_freq_plan();
-
- for_each_online_cpu(cpu)
- regulator_init(cpu, max_acpu_level);
- bus_init(max_acpu_level->l2_level->bw_level);
-
- init_clock_sources(&scalable[L2], &max_acpu_level->l2_level->speed);
- on_each_cpu(per_cpu_init, NULL, true);
-
- cpufreq_table_init();
-
- acpuclk_register(&acpuclk_8960_data);
- register_hotcpu_notifier(&acpuclock_cpu_notifier);
-
- return 0;
+ return acpuclk_krait_init(&pdev->dev, &acpuclk_8960_params);
}
static struct platform_driver acpuclk_8960_driver = {
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 8cf9c2b..9ed038b 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -28,21 +28,7 @@
#define LVL_NOM RPM_REGULATOR_CORNER_NORMAL
#define LVL_HIGH RPM_REGULATOR_CORNER_SUPER_TURBO
-static struct hfpll_data hfpll_data_cpu = {
- .mode_offset = 0x00,
- .l_offset = 0x04,
- .m_offset = 0x08,
- .n_offset = 0x0C,
- .config_offset = 0x14,
- /* TODO: Verify magic number for 8974 when available. */
- .config_val = 0x7845C665,
- .low_vdd_l_max = 52,
- .vdd[HFPLL_VDD_NONE] = 0,
- .vdd[HFPLL_VDD_LOW] = 810000,
- .vdd[HFPLL_VDD_NOM] = 900000,
-};
-
-static struct hfpll_data hfpll_data_l2 = {
+static struct hfpll_data hfpll_data __initdata = {
.mode_offset = 0x00,
.l_offset = 0x04,
.m_offset = 0x08,
@@ -56,10 +42,9 @@
.vdd[HFPLL_VDD_NOM] = LVL_NOM,
};
-static struct scalable scalable[] = {
+static struct scalable scalable[] __initdata = {
[CPU0] = {
.hfpll_phys_base = 0xF908A000,
- .hfpll_data = &hfpll_data_cpu,
.l2cpmr_iaddr = 0x4501,
.vreg[VREG_CORE] = { "krait0", 1050000, 3200000 },
.vreg[VREG_MEM] = { "krait0_mem", 1050000 },
@@ -69,7 +54,6 @@
},
[CPU1] = {
.hfpll_phys_base = 0xF909A000,
- .hfpll_data = &hfpll_data_cpu,
.l2cpmr_iaddr = 0x5501,
.vreg[VREG_CORE] = { "krait1", 1050000, 3200000 },
.vreg[VREG_MEM] = { "krait1_mem", 1050000 },
@@ -79,7 +63,6 @@
},
[CPU2] = {
.hfpll_phys_base = 0xF90AA000,
- .hfpll_data = &hfpll_data_cpu,
.l2cpmr_iaddr = 0x6501,
.vreg[VREG_CORE] = { "krait2", 1050000, 3200000 },
.vreg[VREG_MEM] = { "krait2_mem", 1050000 },
@@ -89,7 +72,6 @@
},
[CPU3] = {
.hfpll_phys_base = 0xF90BA000,
- .hfpll_data = &hfpll_data_cpu,
.l2cpmr_iaddr = 0x7501,
.vreg[VREG_CORE] = { "krait3", 1050000, 3200000 },
.vreg[VREG_MEM] = { "krait3_mem", 1050000 },
@@ -99,14 +81,13 @@
},
[L2] = {
.hfpll_phys_base = 0xF9016000,
- .hfpll_data = &hfpll_data_l2,
.l2cpmr_iaddr = 0x0500,
.vreg[VREG_HFPLL_A] = { "l2_hfpll_a", 2150000 },
.vreg[VREG_HFPLL_B] = { "l2_hfpll_b", 1800000 },
},
};
-static struct msm_bus_paths bw_level_tbl[] = {
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
[0] = BW_MBPS(400), /* At least 50 MHz on bus. */
[1] = BW_MBPS(800), /* At least 100 MHz on bus. */
[2] = BW_MBPS(1334), /* At least 167 MHz on bus. */
@@ -114,15 +95,14 @@
[4] = BW_MBPS(3200), /* At least 333 MHz on bus. */
};
-static struct msm_bus_scale_pdata bus_scale_data = {
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
.usecase = bw_level_tbl,
.num_usecases = ARRAY_SIZE(bw_level_tbl),
.active_only = 1,
.name = "acpuclk-8974",
};
-#define L2(x) (&l2_freq_tbl[(x)])
-static struct l2_level l2_freq_tbl[] = {
+static struct l2_level l2_freq_tbl[] __initdata = {
[0] = { {STBY_KHZ, QSB, 0, 0, 0 }, LVL_LOW, 1050000, 0 },
[1] = { { 300000, PLL_0, 0, 2, 0 }, LVL_LOW, 1050000, 2 },
[2] = { { 384000, HFPLL, 2, 0, 40 }, LVL_NOM, 1050000, 2 },
@@ -137,7 +117,7 @@
[11] = { { 1036800, HFPLL, 1, 0, 54 }, LVL_NOM, 1050000, 4 },
};
-static struct acpu_level acpu_freq_tbl[] = {
+static struct acpu_level acpu_freq_tbl[] __initdata = {
{ 0, {STBY_KHZ, QSB, 0, 0, 0 }, L2(0), 1050000 },
{ 1, { 300000, PLL_0, 0, 2, 0 }, L2(1), 1050000 },
{ 1, { 384000, HFPLL, 2, 0, 40 }, L2(2), 1050000 },
@@ -153,14 +133,20 @@
{ 0, { 0 } }
};
-static struct acpuclk_krait_params acpuclk_8974_params = {
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+ [PVS_SLOW] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+ [PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+ [PVS_FAST] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+};
+
+static struct acpuclk_krait_params acpuclk_8974_params __initdata = {
.scalable = scalable,
- .pvs_acpu_freq_tbl[PVS_SLOW] = acpu_freq_tbl,
- .pvs_acpu_freq_tbl[PVS_NOMINAL] = acpu_freq_tbl,
- .pvs_acpu_freq_tbl[PVS_FAST] = acpu_freq_tbl,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
.l2_freq_tbl = l2_freq_tbl,
- .l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl),
- .bus_scale_data = &bus_scale_data,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
.qfprom_phys_base = 0xFC4A8000,
};
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 8bd54e3..fd43f57 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -57,7 +57,9 @@
const struct acpu_level *max_acpu_lvl;
const struct l2_level *l2_freq_tbl;
struct scalable *scalable;
+ struct hfpll_data *hfpll_data;
u32 bus_perf_client;
+ struct msm_bus_scale_pdata *bus_scale;
struct device *dev;
} drv;
@@ -130,7 +132,7 @@
}
/* Disable PLL bypass mode. */
- writel_relaxed(0x2, sc->hfpll_base + sc->hfpll_data->mode_offset);
+ writel_relaxed(0x2, sc->hfpll_base + drv.hfpll_data->mode_offset);
/*
* H/W requires a 5us delay between disabling the bypass and
@@ -140,14 +142,14 @@
udelay(10);
/* De-assert active-low PLL reset. */
- writel_relaxed(0x6, sc->hfpll_base + sc->hfpll_data->mode_offset);
+ writel_relaxed(0x6, sc->hfpll_base + drv.hfpll_data->mode_offset);
/* Wait for PLL to lock. */
mb();
udelay(60);
/* Enable PLL output. */
- writel_relaxed(0x7, sc->hfpll_base + sc->hfpll_data->mode_offset);
+ writel_relaxed(0x7, sc->hfpll_base + drv.hfpll_data->mode_offset);
}
/* Disable a HFPLL for power-savings or while it's being reprogrammed. */
@@ -157,7 +159,7 @@
* Disable the PLL output, disable test mode, enable the bypass mode,
* and assert the reset.
*/
- writel_relaxed(0, sc->hfpll_base + sc->hfpll_data->mode_offset);
+ writel_relaxed(0, sc->hfpll_base + drv.hfpll_data->mode_offset);
if (!skip_regulators) {
/* Remove voltage votes required by the HFPLL. */
@@ -170,19 +172,17 @@
static void hfpll_set_rate(struct scalable *sc, const struct core_speed *tgt_s)
{
writel_relaxed(tgt_s->pll_l_val,
- sc->hfpll_base + sc->hfpll_data->l_offset);
+ sc->hfpll_base + drv.hfpll_data->l_offset);
}
/* Return the L2 speed that should be applied. */
-static const struct l2_level *compute_l2_level(struct scalable *sc,
- const struct l2_level *vote_l)
+static unsigned int compute_l2_level(struct scalable *sc, unsigned int vote_l)
{
- const struct l2_level *new_l;
+ unsigned int new_l = 0;
int cpu;
/* Find max L2 speed vote. */
sc->l2_vote = vote_l;
- new_l = drv.l2_freq_tbl;
for_each_present_cpu(cpu)
new_l = max(new_l, drv.scalable[cpu].l2_vote);
@@ -350,23 +350,23 @@
static int calculate_vdd_mem(const struct acpu_level *tgt)
{
- return tgt->l2_level->vdd_mem;
+ return drv.l2_freq_tbl[tgt->l2_level].vdd_mem;
}
static int calculate_vdd_dig(const struct acpu_level *tgt)
{
int pll_vdd_dig;
- const int *hfpll_vdd = drv.scalable[L2].hfpll_data->vdd;
- const u32 low_vdd_l_max = drv.scalable[L2].hfpll_data->low_vdd_l_max;
+ const int *hfpll_vdd = drv.hfpll_data->vdd;
+ const u32 low_vdd_l_max = drv.hfpll_data->low_vdd_l_max;
- if (tgt->l2_level->speed.src != HFPLL)
+ if (drv.l2_freq_tbl[tgt->l2_level].speed.src != HFPLL)
pll_vdd_dig = hfpll_vdd[HFPLL_VDD_NONE];
- else if (tgt->l2_level->speed.pll_l_val > low_vdd_l_max)
+ else if (drv.l2_freq_tbl[tgt->l2_level].speed.pll_l_val > low_vdd_l_max)
pll_vdd_dig = hfpll_vdd[HFPLL_VDD_NOM];
else
pll_vdd_dig = hfpll_vdd[HFPLL_VDD_LOW];
- return max(tgt->l2_level->vdd_dig, pll_vdd_dig);
+ return max(drv.l2_freq_tbl[tgt->l2_level].vdd_dig, pll_vdd_dig);
}
static int calculate_vdd_core(const struct acpu_level *tgt)
@@ -379,8 +379,8 @@
enum setrate_reason reason)
{
const struct core_speed *strt_acpu_s, *tgt_acpu_s;
- const struct l2_level *tgt_l2_l;
const struct acpu_level *tgt;
+ int tgt_l2_l;
int vdd_mem, vdd_dig, vdd_core;
unsigned long flags;
int rc = 0;
@@ -436,7 +436,7 @@
*/
spin_lock_irqsave(&l2_lock, flags);
tgt_l2_l = compute_l2_level(&drv.scalable[cpu], tgt->l2_level);
- set_speed(&drv.scalable[L2], &tgt_l2_l->speed);
+ set_speed(&drv.scalable[L2], &drv.l2_freq_tbl[tgt_l2_l].speed);
spin_unlock_irqrestore(&l2_lock, flags);
/* Nothing else to do for power collapse or SWFI. */
@@ -444,7 +444,7 @@
goto out;
/* Update bus bandwith request. */
- set_bus_bw(tgt_l2_l->bw_level);
+ set_bus_bw(drv.l2_freq_tbl[tgt_l2_l].bw_level);
/* Drop VDD levels if we can. */
decrease_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
@@ -467,15 +467,15 @@
hfpll_disable(sc, true);
/* Configure PLL parameters for integer mode. */
- writel_relaxed(sc->hfpll_data->config_val,
- sc->hfpll_base + sc->hfpll_data->config_offset);
- writel_relaxed(0, sc->hfpll_base + sc->hfpll_data->m_offset);
- writel_relaxed(1, sc->hfpll_base + sc->hfpll_data->n_offset);
+ writel_relaxed(drv.hfpll_data->config_val,
+ sc->hfpll_base + drv.hfpll_data->config_offset);
+ writel_relaxed(0, sc->hfpll_base + drv.hfpll_data->m_offset);
+ writel_relaxed(1, sc->hfpll_base + drv.hfpll_data->n_offset);
/* Program droop controller, if supported */
- if (sc->hfpll_data->has_droop_ctl)
- writel_relaxed(sc->hfpll_data->droop_val,
- sc->hfpll_base + sc->hfpll_data->droop_offset);
+ if (drv.hfpll_data->has_droop_ctl)
+ writel_relaxed(drv.hfpll_data->droop_val,
+ sc->hfpll_base + drv.hfpll_data->droop_offset);
/* Set an initial rate and enable the PLL. */
hfpll_set_rate(sc, tgt_s);
@@ -679,18 +679,18 @@
}
/* Register with bus driver. */
-static void __init bus_init(struct msm_bus_scale_pdata *bus_scale_data)
+static void __init bus_init(void)
{
int ret;
- drv.bus_perf_client = msm_bus_scale_register_client(bus_scale_data);
+ drv.bus_perf_client = msm_bus_scale_register_client(drv.bus_scale);
if (!drv.bus_perf_client) {
dev_err(drv.dev, "unable to register bus client\n");
BUG();
}
ret = msm_bus_scale_client_update_request(drv.bus_perf_client,
- drv.max_acpu_lvl->l2_level->bw_level);
+ drv.l2_freq_tbl[drv.max_acpu_lvl->l2_level].bw_level);
if (ret)
dev_err(drv.dev, "initial bandwidth req failed (%d)\n", ret);
}
@@ -792,13 +792,11 @@
tbl->vdd_core = 1150000;
}
-static void __init select_freq_plan(struct acpu_level *const *pvs_tbl,
- u32 qfprom_phys)
+static int __init select_freq_plan(u32 qfprom_phys)
{
- const struct acpu_level *l;
void __iomem *qfprom_base;
u32 pte_efuse, pvs, tbl_idx;
- char *pvs_names[] = { "Slow", "Nominal", "Fast", "Unknown" };
+ char *pvs_names[] = { "Slow", "Nominal", "Fast", "Faster", "Unknown" };
qfprom_base = ioremap(qfprom_phys, SZ_256);
/* Select frequency tables. */
@@ -820,6 +818,9 @@
case 0x3:
tbl_idx = PVS_FAST;
break;
+ case 0x4:
+ tbl_idx = PVS_FASTER;
+ break;
default:
tbl_idx = PVS_UNKNOWN;
break;
@@ -828,24 +829,29 @@
tbl_idx = PVS_UNKNOWN;
dev_err(drv.dev, "Unable to map QFPROM base\n");
}
- dev_info(drv.dev, "ACPU PVS: %s\n", pvs_names[tbl_idx]);
if (tbl_idx == PVS_UNKNOWN) {
tbl_idx = PVS_SLOW;
dev_warn(drv.dev, "ACPU PVS: Defaulting to %s\n",
pvs_names[tbl_idx]);
+ } else {
+ dev_info(drv.dev, "ACPU PVS: %s\n", pvs_names[tbl_idx]);
}
- drv.acpu_freq_tbl = pvs_tbl[tbl_idx];
- if (krait_needs_vmin())
- krait_apply_vmin(drv.acpu_freq_tbl);
+ return tbl_idx;
+}
- /* Find the max supported scaling frequency. */
- for (l = drv.acpu_freq_tbl; l->speed.khz != 0; l++)
+static const struct acpu_level __init *find_max_acpu_lvl(struct acpu_level *tbl)
+{
+ struct acpu_level *l, *max_lvl = NULL;
+
+ for (l = tbl; l->speed.khz != 0; l++)
if (l->use_for_scaling)
- drv.max_acpu_lvl = l;
- BUG_ON(!drv.max_acpu_lvl);
- dev_info(drv.dev, "Max ACPU freq: %lu KHz\n",
- drv.max_acpu_lvl->speed.khz);
+ max_lvl = l;
+
+ BUG_ON(!max_lvl);
+ dev_info(drv.dev, "Max CPU freq: %lu KHz\n", max_lvl->speed.khz);
+
+ return max_lvl;
}
static struct acpuclk_data acpuclk_krait_data = {
@@ -855,20 +861,51 @@
.wait_for_irq_khz = STBY_KHZ,
};
-int __init acpuclk_krait_init(struct device *dev,
- const struct acpuclk_krait_params *params)
+static void __init drv_data_init(struct device *dev,
+ const struct acpuclk_krait_params *params)
{
- struct scalable *l2;
+ int tbl_idx;
+
+ drv.dev = dev;
+ drv.scalable = kmemdup(params->scalable, params->scalable_size,
+ GFP_KERNEL);
+ BUG_ON(!drv.scalable);
+
+ drv.hfpll_data = kmemdup(params->hfpll_data, sizeof(*drv.hfpll_data),
+ GFP_KERNEL);
+ BUG_ON(!drv.hfpll_data);
+
+ drv.l2_freq_tbl = kmemdup(params->l2_freq_tbl, params->l2_freq_tbl_size,
+ GFP_KERNEL);
+ BUG_ON(!drv.l2_freq_tbl);
+
+ drv.bus_scale = kmemdup(params->bus_scale, sizeof(*drv.bus_scale),
+ GFP_KERNEL);
+ BUG_ON(!drv.bus_scale);
+ drv.bus_scale->usecase = kmemdup(drv.bus_scale->usecase,
+ drv.bus_scale->num_usecases * sizeof(*drv.bus_scale->usecase),
+ GFP_KERNEL);
+ BUG_ON(!drv.bus_scale->usecase);
+
+ tbl_idx = select_freq_plan(params->qfprom_phys_base);
+ drv.acpu_freq_tbl = kmemdup(params->pvs_tables[tbl_idx].table,
+ params->pvs_tables[tbl_idx].size,
+ GFP_KERNEL);
+ BUG_ON(!drv.acpu_freq_tbl);
+
+ drv.max_acpu_lvl = find_max_acpu_lvl(drv.acpu_freq_tbl);
+}
+
+static void __init hw_init(void)
+{
+ struct scalable *l2 = &drv.scalable[L2];
int cpu, rc;
- drv.scalable = params->scalable;
- drv.l2_freq_tbl = params->l2_freq_tbl;
- drv.dev = dev;
+ if (krait_needs_vmin())
+ krait_apply_vmin(drv.acpu_freq_tbl);
- select_freq_plan(params->pvs_acpu_freq_tbl, params->qfprom_phys_base);
- bus_init(params->bus_scale_data);
+ bus_init();
- l2 = &drv.scalable[L2];
l2->hfpll_base = ioremap(l2->hfpll_phys_base, SZ_32);
BUG_ON(!l2->hfpll_base);
@@ -878,17 +915,23 @@
rc = rpm_regulator_init(l2, VREG_HFPLL_B,
l2->vreg[VREG_HFPLL_B].max_vdd, false);
BUG_ON(rc);
-
- rc = init_clock_sources(l2, &drv.max_acpu_lvl->l2_level->speed);
+ rc = init_clock_sources(l2,
+ &drv.l2_freq_tbl[drv.max_acpu_lvl->l2_level].speed);
BUG_ON(rc);
for_each_online_cpu(cpu) {
rc = per_cpu_init(cpu);
BUG_ON(rc);
}
+}
+
+int __init acpuclk_krait_init(struct device *dev,
+ const struct acpuclk_krait_params *params)
+{
+ drv_data_init(dev, params);
+ hw_init();
cpufreq_table_init();
-
acpuclk_register(&acpuclk_krait_data);
register_hotcpu_notifier(&acpuclk_cpu_notifier);
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index f121548..f92aaf3 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -15,7 +15,7 @@
#define __ARCH_ARM_MACH_MSM_ACPUCLOCK_KRAIT_H
#define STBY_KHZ 1
-
+#define L2(x) (x)
#define BW_MBPS(_bw) \
{ \
.vectors = (struct msm_bus_vectors[]){ \
@@ -50,6 +50,7 @@
PVS_SLOW = 0,
PVS_NOMINAL,
PVS_FAST,
+ PVS_FASTER,
PVS_UNKNOWN,
NUM_PVS
};
@@ -146,7 +147,7 @@
struct acpu_level {
const int use_for_scaling;
const struct core_speed speed;
- const struct l2_level *l2_level;
+ const unsigned int l2_level;
int vdd_core;
};
@@ -162,7 +163,7 @@
* @droop_offset: Droop controller register offset from base address.
* @droop_val: Value to initialize the @config_offset register to.
* @low_vdd_l_max: Maximum "L" value supported at HFPLL_VDD_LOW.
- * @vdd: voltage requirements for each VDD level.
+ * @vdd: voltage requirements for each VDD level for the L2 PLL.
*/
struct hfpll_data {
const u32 mode_offset;
@@ -185,7 +186,6 @@
* @aux_clk_sel_phys: Physical address of auxiliary MUX.
* @aux_clk_sel: Auxiliary mux input to select at boot.
* @l2cpmr_iaddr: Indirect address of the CPMR MUX/divider CP15 register.
- * @hfpll_data: Descriptive data of HFPLL hardware.
* @cur_speed: Pointer to currently-set speed.
* @l2_vote: L2 performance level vote associate with the current CPU speed.
* @vreg: Array of voltage regulators needed by the scalable.
@@ -197,29 +197,42 @@
const phys_addr_t aux_clk_sel_phys;
const u32 aux_clk_sel;
const u32 l2cpmr_iaddr;
- const struct hfpll_data *hfpll_data;
const struct core_speed *cur_speed;
- const struct l2_level *l2_vote;
+ unsigned int l2_vote;
struct vreg vreg[NUM_VREG];
bool initialized;
};
/**
+ * struct pvs_table - CPU performance level table and size.
+ * @table: CPU performance level table
+ * @size: sizeof(@table)
+ */
+struct pvs_table {
+ struct acpu_level *table;
+ size_t size;
+};
+
+/**
* struct acpuclk_krait_params - SoC specific driver parameters.
* @scalable: Array of scalables.
- * @pvs_acpu_freq_tbl: Array of CPU frequency tables.
+ * @scalable_size: Size of @scalable.
+ * @hfpll_data: HFPLL configuration data.
+ * @pvs_tables: CPU frequency tables.
* @l2_freq_tbl: L2 frequency table.
- * @l2_freq_tbl_size: Number of rows in @l2_freq_tbl.
+ * @l2_freq_tbl_size: Size of @l2_freq_tbl.
* @qfprom_phys_base: Physical base address of QFPROM.
- * @bus_scale_data: MSM bus driver parameters.
+ * @bus_scale: MSM bus driver parameters.
*/
struct acpuclk_krait_params {
struct scalable *scalable;
- struct acpu_level *pvs_acpu_freq_tbl[NUM_PVS];
- const struct l2_level *l2_freq_tbl;
- const size_t l2_freq_tbl_size;
- const phys_addr_t qfprom_phys_base;
- struct msm_bus_scale_pdata *bus_scale_data;
+ size_t scalable_size;
+ struct hfpll_data *hfpll_data;
+ struct pvs_table *pvs_tables;
+ struct l2_level *l2_freq_tbl;
+ size_t l2_freq_tbl_size;
+ phys_addr_t qfprom_phys_base;
+ struct msm_bus_scale_pdata *bus_scale;
};
/**
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 177e1fd..330d7a8 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -1045,7 +1045,8 @@
}
}
-void __init apq8064_set_display_params(char *prim_panel, char *ext_panel)
+void __init apq8064_set_display_params(char *prim_panel, char *ext_panel,
+ unsigned char resolution)
{
/*
* For certain MPQ boards, HDMI should be set as primary display
@@ -1080,4 +1081,6 @@
pr_debug("msm_fb_pdata.ext_panel_name %s\n",
msm_fb_pdata.ext_panel_name);
}
+
+ msm_fb_pdata.ext_resolution = resolution;
}
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 29416de..a84cb39 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -179,11 +179,11 @@
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
- REGULATOR_SUPPLY("krait0", NULL),
+ REGULATOR_SUPPLY("krait0", "acpuclk-8064"),
};
VREG_CONSUMERS(S6) = {
REGULATOR_SUPPLY("8921_s6", NULL),
- REGULATOR_SUPPLY("krait1", NULL),
+ REGULATOR_SUPPLY("krait1", "acpuclk-8064"),
};
VREG_CONSUMERS(S7) = {
REGULATOR_SUPPLY("8921_s7", NULL),
@@ -237,11 +237,11 @@
};
VREG_CONSUMERS(8821_S0) = {
REGULATOR_SUPPLY("8821_s0", NULL),
- REGULATOR_SUPPLY("krait2", NULL),
+ REGULATOR_SUPPLY("krait2", "acpuclk-8064"),
};
VREG_CONSUMERS(8821_S1) = {
REGULATOR_SUPPLY("8821_s1", NULL),
- REGULATOR_SUPPLY("krait3", NULL),
+ REGULATOR_SUPPLY("krait3", "acpuclk-8064"),
};
VREG_CONSUMERS(EXT_5V) = {
REGULATOR_SUPPLY("ext_5v", NULL),
@@ -606,10 +606,37 @@
int msm8064_pm8921_regulator_pdata_len __devinitdata =
ARRAY_SIZE(msm8064_pm8921_regulator_pdata);
+#define RPM_REG_MAP(_id, _sleep_also, _voter, _supply, _dev_name) \
+ { \
+ .vreg_id = RPM_VREG_ID_PM8921_##_id, \
+ .sleep_also = _sleep_also, \
+ .voter = _voter, \
+ .supply = _supply, \
+ .dev_name = _dev_name, \
+ }
+static struct rpm_regulator_consumer_mapping
+ msm_rpm_regulator_consumer_mapping[] __devinitdata = {
+ RPM_REG_MAP(LVS7, 0, 1, "krait0_hfpll", "acpuclk-8064"),
+ RPM_REG_MAP(LVS7, 0, 2, "krait1_hfpll", "acpuclk-8064"),
+ RPM_REG_MAP(LVS7, 0, 4, "krait2_hfpll", "acpuclk-8064"),
+ RPM_REG_MAP(LVS7, 0, 5, "krait3_hfpll", "acpuclk-8064"),
+ RPM_REG_MAP(LVS7, 0, 6, "l2_hfpll", "acpuclk-8064"),
+ RPM_REG_MAP(L24, 0, 1, "krait0_mem", "acpuclk-8064"),
+ RPM_REG_MAP(L24, 0, 2, "krait1_mem", "acpuclk-8064"),
+ RPM_REG_MAP(L24, 0, 4, "krait2_mem", "acpuclk-8064"),
+ RPM_REG_MAP(L24, 0, 5, "krait3_mem", "acpuclk-8064"),
+ RPM_REG_MAP(S3, 0, 1, "krait0_dig", "acpuclk-8064"),
+ RPM_REG_MAP(S3, 0, 2, "krait1_dig", "acpuclk-8064"),
+ RPM_REG_MAP(S3, 0, 4, "krait2_dig", "acpuclk-8064"),
+ RPM_REG_MAP(S3, 0, 5, "krait3_dig", "acpuclk-8064"),
+};
+
struct rpm_regulator_platform_data apq8064_rpm_regulator_pdata __devinitdata = {
.init_data = apq8064_rpm_regulator_init_data,
.num_regulators = ARRAY_SIZE(apq8064_rpm_regulator_init_data),
.version = RPM_VREG_VERSION_8960,
.vreg_id_vdd_mem = RPM_VREG_ID_PM8921_L24,
.vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3,
+ .consumer_map = msm_rpm_regulator_consumer_mapping,
+ .consumer_map_len = ARRAY_SIZE(msm_rpm_regulator_consumer_mapping),
};
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 08c3408..3e07833 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -657,6 +657,9 @@
static char prim_panel_name[PANEL_NAME_MAX_LEN];
static char ext_panel_name[PANEL_NAME_MAX_LEN];
+
+static int ext_resolution;
+
static int __init prim_display_setup(char *param)
{
if (strnlen(param, PANEL_NAME_MAX_LEN))
@@ -673,9 +676,18 @@
}
early_param("ext_display", ext_display_setup);
+static int __init hdmi_resulution_setup(char *param)
+{
+ int ret;
+ ret = kstrtoint(param, 10, &ext_resolution);
+ return ret;
+}
+early_param("ext_resolution", hdmi_resulution_setup);
+
static void __init apq8064_reserve(void)
{
- apq8064_set_display_params(prim_panel_name, ext_panel_name);
+ apq8064_set_display_params(prim_panel_name, ext_panel_name,
+ ext_resolution);
msm_reserve();
if (apq8064_fmem_pdata.size) {
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
@@ -2037,12 +2049,6 @@
},
};
-static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
- .base_addr = MSM_ACC0_BASE + 0x08,
- .cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
- .mask = 1UL << 13,
-};
-
static void __init apq8064_init_buses(void)
{
msm_bus_rpm_set_mt_mask();
@@ -2148,7 +2154,7 @@
};
static struct platform_device *common_devices[] __initdata = {
- &msm8960_device_acpuclk,
+ &apq8064_device_acpuclk,
&apq8064_device_dmov,
&apq8064_device_qup_spi_gsbi5,
&apq8064_device_ext_5v_vreg,
@@ -2953,7 +2959,6 @@
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
msm_spm_l2_init(msm_spm_l2_data);
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
- msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
apq8064_epm_adc_init();
}
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index a241ab3..2258b8d 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -87,7 +87,8 @@
void apq8064_init_fb(void);
void apq8064_allocate_fb_region(void);
void apq8064_mdp_writeback(struct memtype_reserve *reserve_table);
-void __init apq8064_set_display_params(char *prim_panel, char *ext_panel);
+void __init apq8064_set_display_params(char *prim_panel, char *ext_panel,
+ unsigned char resolution);
void apq8064_init_gpu(void);
void apq8064_pm8xxx_gpio_mpp_init(void);
diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c
index 105a5aa..bd343c1 100644
--- a/arch/arm/mach-msm/board-8930-gpu.c
+++ b/arch/arm/mach-msm/board-8930-gpu.c
@@ -162,8 +162,8 @@
{
unsigned int version = socinfo_get_version();
- if (cpu_is_msm8627())
- kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 400000000;
+ if (cpu_is_msm8930aa())
+ kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 450000000;
if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
(SOCINFO_VERSION_MINOR(version) == 2))
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 88c0924..d7a077c 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -2401,12 +2401,6 @@
.mode = MSM_PM_BOOT_CONFIG_TZ,
};
-static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
- .base_addr = MSM_ACC0_BASE + 0x08,
- .cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
- .mask = 1UL << 13,
-};
-
#ifdef CONFIG_I2C
#define I2C_SURF 1
#define I2C_FFA (1 << 1)
@@ -2603,7 +2597,6 @@
ARRAY_SIZE(msm_slim_devices));
change_memory_power = &msm8930_change_memory_power;
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
- msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
if (PLATFORM_IS_CHARM25())
platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 53e7c9e..5851990 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -76,6 +76,18 @@
.pull = GPIOMUX_PULL_NONE,
};
+static struct gpiomux_setting gsbi8_uartdm_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi8_uartdm_suspended_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
static struct gpiomux_setting gsbi9_active_cfg = {
.func = GPIOMUX_FUNC_2,
.drv = GPIOMUX_DRV_8MA,
@@ -310,6 +322,37 @@
},
};
#endif
+/* GSBI8 UART GPIOs for Atheros Bluetooth */
+static struct msm_gpiomux_config msm8960_gsbi8_uartdm_configs[] = {
+ {
+ .gpio = 34,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+ }
+ },
+ {
+ .gpio = 35,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+ }
+ },
+ {
+ .gpio = 36,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+ }
+ },
+ {
+ .gpio = 37,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+ }
+ },
+};
static struct msm_gpiomux_config msm8960_fusion_gsbi_configs[] = {
{
@@ -988,6 +1031,10 @@
msm_gpiomux_install(msm8960_mdp_vsync_configs,
ARRAY_SIZE(msm8960_mdp_vsync_configs));
+ if (socinfo_get_platform_subtype() != PLATFORM_SUBTYPE_SGLTE)
+ msm_gpiomux_install(msm8960_gsbi8_uartdm_configs,
+ ARRAY_SIZE(msm8960_gsbi8_uartdm_configs));
+
if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
msm_gpiomux_install(msm8960_gsbi8_uart_configs,
ARRAY_SIZE(msm8960_gsbi8_uart_configs));
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 650ac28..6ad44d8 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -181,11 +181,11 @@
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
- REGULATOR_SUPPLY("krait0", NULL),
+ REGULATOR_SUPPLY("krait0", "acpuclk-8960"),
};
VREG_CONSUMERS(S6) = {
REGULATOR_SUPPLY("8921_s6", NULL),
- REGULATOR_SUPPLY("krait1", NULL),
+ REGULATOR_SUPPLY("krait1", "acpuclk-8960"),
};
VREG_CONSUMERS(S7) = {
REGULATOR_SUPPLY("8921_s7", NULL),
@@ -561,10 +561,34 @@
int msm_pm8921_regulator_pdata_len __devinitdata =
ARRAY_SIZE(msm_pm8921_regulator_pdata);
+#define RPM_REG_MAP(_id, _sleep_also, _voter, _supply, _dev_name) \
+ { \
+ .vreg_id = RPM_VREG_ID_PM8921_##_id, \
+ .sleep_also = _sleep_also, \
+ .voter = _voter, \
+ .supply = _supply, \
+ .dev_name = _dev_name, \
+ }
+static struct rpm_regulator_consumer_mapping
+ msm_rpm_regulator_consumer_mapping[] __devinitdata = {
+ RPM_REG_MAP(L23, 0, 1, "krait0_l23", "acpuclk-8960"),
+ RPM_REG_MAP(L23, 0, 2, "krait1_l23", "acpuclk-8960"),
+ RPM_REG_MAP(L23, 0, 6, "l2_l23", "acpuclk-8960"),
+ RPM_REG_MAP(L24, 0, 1, "krait0_mem", "acpuclk-8960"),
+ RPM_REG_MAP(L24, 0, 2, "krait1_mem", "acpuclk-8960"),
+ RPM_REG_MAP(S3, 0, 1, "krait0_dig", "acpuclk-8960"),
+ RPM_REG_MAP(S3, 0, 2, "krait1_dig", "acpuclk-8960"),
+ RPM_REG_MAP(S8, 0, 1, "krait0_s8", "acpuclk-8960"),
+ RPM_REG_MAP(S8, 0, 2, "krait1_s8", "acpuclk-8960"),
+ RPM_REG_MAP(S8, 0, 6, "l2_s8", "acpuclk-8960"),
+};
+
struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata = {
.init_data = msm_rpm_regulator_init_data,
.num_regulators = ARRAY_SIZE(msm_rpm_regulator_init_data),
.version = RPM_VREG_VERSION_8960,
.vreg_id_vdd_mem = RPM_VREG_ID_PM8921_L24,
.vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3,
+ .consumer_map = msm_rpm_regulator_consumer_mapping,
+ .consumer_map_len = ARRAY_SIZE(msm_rpm_regulator_consumer_mapping),
};
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 0fcaf78..d56bdbd 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2321,12 +2321,6 @@
.src_clk_rate = 24000000,
};
-static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
- .base_addr = MSM_ACC0_BASE + 0x08,
- .cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
- .mask = 1UL << 13,
-};
-
static struct ks8851_pdata spi_eth_pdata = {
.irq_gpio = KS8851_IRQ_GPIO,
.rst_gpio = KS8851_RST_GPIO,
@@ -2462,7 +2456,36 @@
static struct msm_serial_hs_platform_data msm_uart_dm9_pdata = {
.gpio_config = configure_uart_gpios,
};
+
+static int configure_gsbi8_uart_gpios(int on)
+{
+ int ret = 0, i;
+ int uart_gpios[] = {34, 35, 36, 37};
+
+ for (i = 0; i < ARRAY_SIZE(uart_gpios); i++) {
+ if (on) {
+ ret = gpio_request(uart_gpios[i], NULL);
+ if (ret) {
+ pr_err("%s: unable to request uart gpio[%d]\n",
+ __func__, uart_gpios[i]);
+ break;
+ }
+ } else {
+ gpio_free(uart_gpios[i]);
+ }
+ }
+
+ if (ret && on && i)
+ for (; i >= 0; i--)
+ gpio_free(uart_gpios[i]);
+ return ret;
+}
+
+static struct msm_serial_hs_platform_data msm_uart_dm8_pdata = {
+ .gpio_config = configure_gsbi8_uart_gpios,
+};
#else
+static struct msm_serial_hs_platform_data msm_uart_dm8_pdata;
static struct msm_serial_hs_platform_data msm_uart_dm9_pdata;
#endif
@@ -3047,7 +3070,6 @@
slim_register_board_info(msm_slim_devices,
ARRAY_SIZE(msm_slim_devices));
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
- msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
}
static void __init msm8960_rumi3_init(void)
@@ -3077,7 +3099,6 @@
slim_register_board_info(msm_slim_devices,
ARRAY_SIZE(msm_slim_devices));
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
- msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
}
static void __init msm8960_cdp_init(void)
@@ -3143,6 +3164,11 @@
platform_device_register(&msm_device_uart_dm9);
}
+ /* For 8960 Standalone External Bluetooth Interface */
+ if (socinfo_get_platform_subtype() != PLATFORM_SUBTYPE_SGLTE) {
+ msm_device_uart_dm8.dev.platform_data = &msm_uart_dm8_pdata;
+ platform_device_register(&msm_device_uart_dm8);
+ }
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm8960_pm8921_gpio_mpp_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
@@ -3161,7 +3187,6 @@
msm8960_init_dsps();
change_memory_power = &msm8960_change_memory_power;
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
- msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
mdm_sglte_device.dev.platform_data = &sglte_platform_data;
platform_device_register(&mdm_sglte_device);
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 7562c83..6b46a2f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -383,6 +383,7 @@
static void __init msm_8974_early_memory(void)
{
reserve_info = &msm_8974_reserve_info;
+ of_scan_flat_dt(dt_scan_for_memory_reserve, msm_8974_reserve_table);
}
void __init msm_8974_reserve(void)
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 7db4bda..ba4e098 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -48,7 +48,6 @@
#include <mach/msm_battery.h>
#include <linux/smsc911x.h>
#include <linux/atmel_maxtouch.h>
-#include <linux/fmem.h>
#include <linux/msm_adc.h>
#include <linux/ion.h>
#include "devices.h"
@@ -448,9 +447,6 @@
.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
.cached = 1,
.memory_type = MEMTYPE_EBI1,
- .request_region = request_fmem_c_region,
- .release_region = release_fmem_c_region,
- .reusable = 1,
};
static struct platform_device android_pmem_adsp_device = {
@@ -778,14 +774,6 @@
static void msm7x27a_cfg_uart2dm_serial(void) { }
#endif
-static struct fmem_platform_data fmem_pdata;
-
-static struct platform_device fmem_device = {
- .name = "fmem",
- .id = 1,
- .dev = { .platform_data = &fmem_pdata },
-};
-
static struct platform_device *rumi_sim_devices[] __initdata = {
&msm_device_dmov,
&msm_device_smd,
@@ -823,7 +811,6 @@
&android_pmem_device,
&android_pmem_adsp_device,
&android_pmem_audio_device,
- &fmem_device,
&msm_device_nand,
&msm_device_snd,
&msm_device_adspdec,
@@ -966,32 +953,10 @@
{
#ifdef CONFIG_ANDROID_PMEM
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- unsigned int i;
- unsigned int reusable_count = 0;
-
android_pmem_adsp_pdata.size = pmem_adsp_size;
android_pmem_pdata.size = pmem_mdp_size;
android_pmem_audio_pdata.size = pmem_audio_size;
- fmem_pdata.size = 0;
- fmem_pdata.align = PAGE_SIZE;
-
- /* Find pmem devices that should use FMEM (reusable) memory.
- */
- for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
- struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
- if (!reusable_count && pdata->reusable)
- fmem_pdata.size += pdata->size;
-
- reusable_count += (pdata->reusable) ? 1 : 0;
-
- if (pdata->reusable && reusable_count > 1) {
- pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
- __func__, pdata->name);
- pdata->reusable = 0;
- }
- }
#endif
#endif
}
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index bd73b70..a694557 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -31,7 +31,6 @@
#include <linux/memblock.h>
#include <linux/input/ft5x06_ts.h>
#include <linux/msm_adc.h>
-#include <linux/fmem.h>
#include <linux/regulator/msm-gpio-regulator.h>
#include <linux/ion.h>
#include <asm/mach/mmc.h>
@@ -394,9 +393,6 @@
.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
.cached = 1,
.memory_type = MEMTYPE_EBI1,
- .request_region = request_fmem_c_region,
- .release_region = release_fmem_c_region,
- .reusable = 1,
};
static struct platform_device android_pmem_adsp_device = {
@@ -639,14 +635,6 @@
},
};
-static struct fmem_platform_data fmem_pdata;
-
-static struct platform_device fmem_device = {
- .name = "fmem",
- .id = 1,
- .dev = { .platform_data = &fmem_pdata },
-};
-
#define GPIO_VREG_INIT(_id, _reg_name, _gpio_label, _gpio, _active_low) \
[GPIO_VREG_ID_##_id] = { \
.init_data = { \
@@ -717,7 +705,6 @@
&asoc_msm_dai0,
&asoc_msm_dai1,
&msm_adc_device,
- &fmem_device,
#ifdef CONFIG_ION_MSM
&ion_dev,
#endif
@@ -858,32 +845,9 @@
{
#ifdef CONFIG_ANDROID_PMEM
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- unsigned int i;
- unsigned int reusable_count = 0;
-
android_pmem_adsp_pdata.size = pmem_adsp_size;
android_pmem_pdata.size = pmem_mdp_size;
android_pmem_audio_pdata.size = pmem_audio_size;
-
- fmem_pdata.size = 0;
- fmem_pdata.align = PAGE_SIZE;
-
- /* Find pmem devices that should use FMEM (reusable) memory.
- */
- for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
- struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
- if (!reusable_count && pdata->reusable)
- fmem_pdata.size += pdata->size;
-
- reusable_count += (pdata->reusable) ? 1 : 0;
-
- if (pdata->reusable && reusable_count > 1) {
- pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
- __func__, pdata->name);
- pdata->reusable = 0;
- }
- }
#endif
#endif
}
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index c3302ec..8a73c84 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -253,22 +253,11 @@
int print_regs = cesr & CESR_PRINT_MASK;
int log_event = cesr & CESR_LOG_EVENT_MASK;
- void *const saw_bases[] = {
- MSM_SAW0_BASE,
- MSM_SAW1_BASE,
- MSM_SAW2_BASE,
- MSM_SAW3_BASE,
- };
-
if (print_regs) {
pr_alert("L1 / TLB Error detected on CPU %d!\n", cpu);
pr_alert("\tCESR = 0x%08x\n", cesr);
pr_alert("\tCPU speed = %lu\n", acpuclk_get_rate(cpu));
pr_alert("\tMIDR = 0x%08x\n", read_cpuid_id());
- pr_alert("\tPTE fuses = 0x%08x\n",
- readl_relaxed(MSM_QFPROM_BASE + 0xC0));
- pr_alert("\tPMIC_VREG = 0x%08x\n",
- readl_relaxed(saw_bases[cpu] + 0x14));
}
if (cesr & CESR_DCTPE) {
@@ -550,12 +539,18 @@
return 0;
}
+static struct of_device_id cache_erp_match_table[] = {
+ { .compatible = "qcom,cache_erp", },
+ {}
+};
+
static struct platform_driver msm_cache_erp_driver = {
.probe = msm_cache_erp_probe,
.remove = msm_cache_erp_remove,
.driver = {
.name = MODULE_NAME,
.owner = THIS_MODULE,
+ .of_match_table = cache_erp_match_table,
},
};
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 2d71355..56b774d 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -2689,6 +2689,7 @@
.ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
CLK_INIT(csi0_src_clk.c),
+ .warned = true,
},
};
@@ -2706,6 +2707,7 @@
.dbg_name = "csi0_clk",
.ops = &clk_ops_branch,
CLK_INIT(csi0_clk.c),
+ .warned = true,
},
};
@@ -2745,6 +2747,7 @@
.ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
CLK_INIT(csi1_src_clk.c),
+ .warned = true,
},
};
@@ -2762,6 +2765,7 @@
.dbg_name = "csi1_clk",
.ops = &clk_ops_branch,
CLK_INIT(csi1_clk.c),
+ .warned = true,
},
};
@@ -2801,6 +2805,7 @@
.ops = &clk_ops_rcg,
VDD_DIG_FMAX_MAP2(LOW, 86000000, NOMINAL, 178000000),
CLK_INIT(csi2_src_clk.c),
+ .warned = true,
},
};
@@ -2818,6 +2823,7 @@
.dbg_name = "csi2_clk",
.ops = &clk_ops_branch,
CLK_INIT(csi2_clk.c),
+ .warned = true,
},
};
@@ -5502,7 +5508,10 @@
CLK_LOOKUP("core_clk", gsbi5_uart_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("core_clk", gsbi6_uart_clk.c, "msm_serial_hs.0"),
CLK_LOOKUP("core_clk", gsbi7_uart_clk.c, ""),
+ /* used on 8960 SGLTE for console */
CLK_LOOKUP("core_clk", gsbi8_uart_clk.c, "msm_serial_hsl.1"),
+ /* used on 8960 standalone with Atheros Bluetooth */
+ CLK_LOOKUP("core_clk", gsbi8_uart_clk.c, "msm_serial_hs.2"),
CLK_LOOKUP("core_clk", gsbi9_uart_clk.c, "msm_serial_hs.1"),
CLK_LOOKUP("core_clk", gsbi10_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi11_uart_clk.c, ""),
@@ -5554,7 +5563,10 @@
CLK_LOOKUP("iface_clk", gsbi5_p_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("iface_clk", gsbi6_p_clk.c, "msm_serial_hs.0"),
CLK_LOOKUP("iface_clk", gsbi7_p_clk.c, ""),
+ /* used on 8960 SGLTE for serial console */
CLK_LOOKUP("iface_clk", gsbi8_p_clk.c, "msm_serial_hsl.1"),
+ /* used on 8960 standalone with Atheros Bluetooth */
+ CLK_LOOKUP("iface_clk", gsbi8_p_clk.c, "msm_serial_hs.2"),
CLK_LOOKUP("iface_clk", gsbi9_p_clk.c, "msm_serial_hs.1"),
CLK_LOOKUP("iface_clk", gsbi10_p_clk.c, "qup_i2c.10"),
CLK_LOOKUP("iface_clk", gsbi11_p_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 48f16b0..6b58257 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -2115,6 +2115,7 @@
static struct branch_clk gcc_usb30_master_clk = {
.cbcr_reg = USB30_MASTER_CBCR,
+ .bcr_reg = USB_30_BCR,
.parent = &usb30_master_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[GCC_BASE],
@@ -2149,6 +2150,7 @@
static struct branch_clk gcc_usb_hs_system_clk = {
.cbcr_reg = USB_HS_SYSTEM_CBCR,
+ .bcr_reg = USB_HS_BCR,
.parent = &usb_hs_system_clk_src.c,
.base = &virt_bases[GCC_BASE],
.c = {
@@ -2171,6 +2173,7 @@
static struct branch_clk gcc_usb_hsic_clk = {
.cbcr_reg = USB_HSIC_CBCR,
+ .bcr_reg = USB_HS_HSIC_BCR,
.parent = &usb_hsic_clk_src.c,
.base = &virt_bases[GCC_BASE],
.c = {
@@ -3987,9 +3990,9 @@
.has_sibling = 1,
.base = &virt_bases[LPASS_BASE],
.c = {
- .dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+ .dbg_name = "audio_core_lpaif_codec_spkr_osr_clk",
.ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+ CLK_INIT(audio_core_lpaif_codec_spkr_osr_clk.c),
},
};
@@ -3998,9 +4001,9 @@
.has_sibling = 1,
.base = &virt_bases[LPASS_BASE],
.c = {
- .dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+ .dbg_name = "audio_core_lpaif_codec_spkr_ebit_clk",
.ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+ CLK_INIT(audio_core_lpaif_codec_spkr_ebit_clk.c),
},
};
@@ -4011,9 +4014,9 @@
.max_div = 15,
.base = &virt_bases[LPASS_BASE],
.c = {
- .dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+ .dbg_name = "audio_core_lpaif_codec_spkr_ibit_clk",
.ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+ CLK_INIT(audio_core_lpaif_codec_spkr_ibit_clk.c),
},
};
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 8a41a7c..aa67690 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -852,6 +852,11 @@
},
};
+struct platform_device apq8064_device_acpuclk = {
+ .name = "acpuclk-8064",
+ .id = -1,
+};
+
#define SHARED_IMEM_TZ_BASE 0x2a03f720
static struct resource tzlog_resources[] = {
{
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index d74d4aa..9a0c2d7 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -292,6 +292,52 @@
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
+
+/* GSBI 8 used into UARTDM Mode */
+static struct resource msm_uart_dm8_resources[] = {
+ {
+ .start = MSM_UART8DM_PHYS,
+ .end = MSM_UART8DM_PHYS + PAGE_SIZE - 1,
+ .name = "uartdm_resource",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = GSBI8_UARTDM_IRQ,
+ .end = GSBI8_UARTDM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM_GSBI8_PHYS,
+ .end = MSM_GSBI8_PHYS + 4 - 1,
+ .name = "gsbi_resource",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = DMOV_HSUART_GSBI8_TX_CHAN,
+ .end = DMOV_HSUART_GSBI8_RX_CHAN,
+ .name = "uartdm_channels",
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .start = DMOV_HSUART_GSBI8_TX_CRCI,
+ .end = DMOV_HSUART_GSBI8_RX_CRCI,
+ .name = "uartdm_crci",
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static u64 msm_uart_dm8_dma_mask = DMA_BIT_MASK(32);
+struct platform_device msm_device_uart_dm8 = {
+ .name = "msm_serial_hs",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(msm_uart_dm8_resources),
+ .resource = msm_uart_dm8_resources,
+ .dev = {
+ .dma_mask = &msm_uart_dm8_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
/*
* GSBI 9 used into UARTDM Mode
* For 8960 Fusion 2.2 Primary IPC
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 2207e3c..daf70a8 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -53,6 +53,7 @@
extern struct platform_device msm_device_uart_dm12;
extern struct platform_device *msm_device_uart_gsbi9;
extern struct platform_device msm_device_uart_dm6;
+extern struct platform_device msm_device_uart_dm8;
extern struct platform_device msm_device_uart_dm9;
extern struct platform_device msm8960_device_uart_gsbi2;
@@ -419,6 +420,7 @@
extern struct platform_device msm7x27a_device_acpuclk;
extern struct platform_device msm7x27aa_device_acpuclk;
extern struct platform_device msm7x30_device_acpuclk;
+extern struct platform_device apq8064_device_acpuclk;
extern struct platform_device msm8625_device_acpuclk;
extern struct platform_device msm8627_device_acpuclk;
extern struct platform_device msm8x50_device_acpuclk;
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 86720d8..f21d296 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -475,6 +475,7 @@
struct msm_fb_platform_data {
int (*detect_client)(const char *name);
int mddi_prescan;
+ unsigned char ext_resolution;
int (*allow_set_offset)(void);
char prim_panel_name[PANEL_NAME_MAX_LEN];
char ext_panel_name[PANEL_NAME_MAX_LEN];
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index 381ea12..6a389de 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -188,6 +188,12 @@
#define DMOV_HSUART_GSBI6_RX_CHAN 8
#define DMOV_HSUART_GSBI6_RX_CRCI 11
+#define DMOV_HSUART_GSBI8_TX_CHAN 7
+#define DMOV_HSUART_GSBI8_TX_CRCI 10
+
+#define DMOV_HSUART_GSBI8_RX_CHAN 8
+#define DMOV_HSUART_GSBI8_RX_CRCI 9
+
#define DMOV_HSUART_GSBI9_TX_CHAN 4
#define DMOV_HSUART_GSBI9_TX_CRCI 13
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index 2596364..bf92f7d 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -118,6 +118,23 @@
(virt) - MEMBANK0_PAGE_OFFSET + MEMBANK0_PHYS_OFFSET)
#endif
+/*
+ * Need a temporary unique variable that no one will ever see to
+ * hold the compat string. Line number gives this easily.
+ * Need another layer of indirection to get __LINE__ to expand
+ * properly as opposed to appending and ending up with
+ * __compat___LINE__
+ */
+#define __CONCAT(a, b) ___CONCAT(a, b)
+#define ___CONCAT(a, b) a ## b
+
+#define EXPORT_COMPAT(com) \
+static char *__CONCAT(__compat_, __LINE__) __used \
+ __attribute((__section__(".exportcompat.init"))) = com
+
+extern char *__compat_exports_start[];
+extern char *__compat_exports_end[];
+
#endif
#if defined CONFIG_ARCH_MSM_SCORPION || defined CONFIG_ARCH_MSM_KRAIT
@@ -135,4 +152,5 @@
#ifndef CONFIG_ARCH_MSM7X27
#define CONSISTENT_DMA_SIZE (SZ_1M * 14)
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_memory_dump.h b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
new file mode 100644
index 0000000..3b8c9fd
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+#ifndef __MSM_MEMORY_DUMP_H
+#define __MSM_MEMORY_DUMP_H
+
+#include <linux/types.h>
+
+enum dump_client_type {
+ MSM_CPU_CTXT = 0,
+ MSM_CACHE,
+ MSM_OCMEM,
+ MSM_ETB,
+ MSM_ETM,
+ MSM_TMC,
+ MAX_NUM_CLIENTS,
+};
+
+struct msm_client_dump {
+ enum dump_client_type id;
+ unsigned long start_addr;
+ unsigned long end_addr;
+};
+
+struct msm_dump_table {
+ u32 version;
+ u32 num_entries;
+ struct msm_client_dump client_entries[MAX_NUM_CLIENTS];
+};
+
+struct msm_memory_dump {
+ unsigned long dump_table_phys;
+ struct msm_dump_table *dump_table_ptr;
+};
+
+#define TABLE_MAJOR(val) (val >> 20)
+#define TABLE_MINOR(val) (val & 0xFFFFF)
+#define MK_TABLE(ma, mi) ((ma << 20) | mi)
+
+#ifndef CONFIG_MSM_MEMORY_DUMP
+static inline int msm_dump_table_register(struct msm_client_dump *entry)
+{
+ return -EIO;
+}
+#else
+int msm_dump_table_register(struct msm_client_dump *client_entry);
+#endif
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
index 7afb38d..5ca5861 100644
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -66,5 +66,8 @@
extern struct reserve_info *reserve_info;
+int __init dt_scan_for_memory_reserve(unsigned long node, const char *uname,
+ int depth, void *data);
+
unsigned long __init reserve_memory_for_fmem(unsigned long, unsigned long);
#endif
diff --git a/arch/arm/mach-msm/include/mach/ocmem.h b/arch/arm/mach-msm/include/mach/ocmem.h
index 927624d..415f8ed 100644
--- a/arch/arm/mach-msm/include/mach/ocmem.h
+++ b/arch/arm/mach-msm/include/mach/ocmem.h
@@ -22,7 +22,7 @@
/* Maximum number of slots in DM */
#define OCMEM_MAX_CHUNKS 32
-#define MIN_CHUNK_SIZE (SZ_1K/8)
+#define MIN_CHUNK_SIZE 128
struct ocmem_notifier;
@@ -61,7 +61,7 @@
/* IMEM Clients */
OCMEM_LP_AUDIO,
OCMEM_SENSORS,
- OCMEM_BLAST,
+ OCMEM_OTHER_OS,
OCMEM_CLIENT_MAX,
};
@@ -108,8 +108,13 @@
int ocmem_shrink(int client_id, struct ocmem_buf *buf,
unsigned long new_size);
-int ocmem_expand(int client_id, struct ocmem_buf *buf,
- unsigned long new_size);
+/* Transfer APIs */
+int ocmem_map(int client_id, struct ocmem_buf *buffer,
+ struct ocmem_map_list *list);
+
+
+int ocmem_unmap(int client_id, struct ocmem_buf *buffer,
+ struct ocmem_map_list *list);
/* Priority Enforcement APIs */
int ocmem_evict(int client_id);
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 64c9ffe..70b5a45 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -20,12 +20,13 @@
#include "ocmem.h"
#include <mach/msm_iomap.h>
#include <asm/io.h>
+#include <linux/platform_device.h>
#define OCMEM_PHYS_BASE 0xFEC00000
#define OCMEM_PHYS_SIZE 0x180000
-#define TO_OCMEM 0x1
-#define TO_DDR 0x2
+#define TO_OCMEM 0x0
+#define TO_DDR 0x1
struct ocmem_zone;
@@ -38,7 +39,7 @@
int owner;
int active_regions;
int max_regions;
- struct list_head region_list;
+ struct list_head req_list;
unsigned long z_start;
unsigned long z_end;
unsigned long z_head;
@@ -78,12 +79,24 @@
bool interleaved;
};
+struct ocmem_eviction_data {
+ struct completion completion;
+ struct list_head victim_list;
+ struct list_head req_list;
+ struct work_struct work;
+ int prio;
+ int pending;
+ bool passive;
+};
+
struct ocmem_req {
struct rw_semaphore rw_sem;
/* Chain in sched queue */
struct list_head sched_list;
/* Chain in zone list */
struct list_head zone_list;
+ /* Chain in eviction list */
+ struct list_head eviction_list;
int owner;
int prio;
uint32_t req_id;
@@ -100,6 +113,7 @@
unsigned long req_start;
unsigned long req_end;
unsigned long req_sz;
+ struct ocmem_eviction_data *edata;
};
struct ocmem_handle {
@@ -150,13 +164,20 @@
int ocmem_notifier_init(void);
int check_notifier(int);
+const char *get_name(int);
+int check_id(int);
int dispatch_notification(int, enum ocmem_notif_type, struct ocmem_buf *);
int ocmem_sched_init(void);
+int ocmem_rdm_init(struct platform_device *);
int process_allocate(int, struct ocmem_handle *, unsigned long, unsigned long,
unsigned long, bool, bool);
int process_free(int, struct ocmem_handle *);
-int process_xfer(int, struct ocmem_handle *, struct ocmem_map_list *,
- int direction);
+int process_xfer(int, struct ocmem_handle *, struct ocmem_map_list *, int);
+int process_evict(int);
+int process_restore(int);
+int process_shrink(int, struct ocmem_handle *, unsigned long);
+int ocmem_rdm_transfer(int, struct ocmem_map_list *,
+ unsigned long, int);
unsigned long process_quota(int);
#endif
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index e65f71c..ea368ae 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -49,8 +49,8 @@
static void msm_lpm_exit_sleep(void *limits, bool from_idle,
bool notify_rpm, bool collapsed)
{
- /* TODO */
- return;
+ msm_lpmrs_exit_sleep((struct msm_rpmrs_limits *)limits,
+ from_idle, notify_rpm, collapsed);
}
void msm_lpm_show_resources(void)
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index f57f974..e5be352 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -18,14 +18,14 @@
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/cpu.h>
-#include <mach/mpm.h>
#include <linux/notifier.h>
#include <linux/hrtimer.h>
#include <linux/tick.h>
+#include <mach/mpm.h>
+#include <mach/rpm-smd.h>
#include "spm.h"
#include "lpm_resources.h"
#include "rpm-notifier.h"
-#include <mach/rpm-smd.h>
#include "idle.h"
/*Debug Definitions*/
@@ -243,6 +243,7 @@
uint32_t key, uint8_t *value)
{
int ret = 0;
+ int msg_id;
if (!handle)
return ret;
@@ -255,10 +256,18 @@
return ret;
}
- ret = msm_rpm_send_request_noirq(handle);
- if (ret < 0) {
+ msg_id = msm_rpm_send_request_noirq(handle);
+ if (!msg_id) {
pr_err("%s: Error sending RPM request key %u, handle 0x%x\n",
__func__, key, (unsigned int)handle);
+ ret = -EIO;
+ return ret;
+ }
+
+ ret = msm_rpm_wait_for_ack(msg_id);
+ if (ret < 0) {
+ pr_err("%s: Couldn't get ACK from RPM for Msg %d Error %d",
+ __func__, msg_id, ret);
return ret;
}
if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_RPM)
@@ -666,12 +675,14 @@
return ret;
}
-void msm_lpmrs_exit_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm)
+void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+ bool from_idle, bool notify_rpm, bool collapsed)
{
/* MPM exit sleep
if (msm_lpm_use_mpm(limits))
msm_mpm_exit_sleep(from_idle);*/
+
+ msm_spm_l2_set_low_power_mode(MSM_SPM_MODE_DISABLED, notify_rpm);
}
static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
diff --git a/arch/arm/mach-msm/lpm_resources.h b/arch/arm/mach-msm/lpm_resources.h
index 9973fbf..bc06d7b 100644
--- a/arch/arm/mach-msm/lpm_resources.h
+++ b/arch/arm/mach-msm/lpm_resources.h
@@ -83,14 +83,14 @@
/**
* msm_lpmrs_exit_sleep() - Exit sleep, reset the MPM and L2 mode.
- * @ sclk_count - Sleep Clock count.
* @ limits: pointer to resource limits of the most recent low power mode.
* @from_idle: bool to determine if this call being made as a part of
* idle power collapse.
* @notify_rpm: bool that informs if this is an RPM notified power collapse.
+ * @collapsed: bool that informs if the Krait was power collapsed.
*/
-void msm_lpmrs_exit_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
- bool from_idle, bool notify_rpm);
+void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+ bool from_idle, bool notify_rpm, bool collapsed);
/**
* msm_lpmrs_module_init() - Init function that parses the device tree to
* get the low power resource attributes and registers with RPM driver for
@@ -112,9 +112,8 @@
return 0;
}
-static inline void msm_lpmrs_exit_sleep(uint32_t sclk_count,
- struct msm_rpmrs_limits *limits, bool from_idle,
- bool notify_rpm)
+static inline void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+ bool from_idle, bool notify_rpm, bool collapsed)
{
return;
}
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index a1b21c5..63c2d3a 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -37,6 +37,7 @@
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
#include <linux/sched.h>
+#include <linux/of_fdt.h>
/* fixme */
#include <asm/tlbflush.h>
@@ -381,3 +382,117 @@
{
return fmem_set_state(FMEM_T_STATE);
}
+
+static char * const memtype_names[] = {
+ [MEMTYPE_SMI_KERNEL] = "SMI_KERNEL",
+ [MEMTYPE_SMI] = "SMI",
+ [MEMTYPE_EBI0] = "EBI0",
+ [MEMTYPE_EBI1] = "EBI1",
+};
+
+static int reserve_memory_type(char *mem_name,
+ struct memtype_reserve *reserve_table,
+ int size)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(memtype_names); i++) {
+ if (memtype_names[i] && strcmp(mem_name,
+ memtype_names[i]) == 0) {
+ reserve_table[i].size += size;
+ return 0;
+ }
+ }
+
+ pr_err("Could not find memory type %s\n", mem_name);
+ return -EINVAL;
+}
+
+static int check_for_compat(unsigned long node)
+{
+ char **start = __compat_exports_start;
+
+ for ( ; start < __compat_exports_end; start++)
+ if (of_flat_dt_is_compatible(node, *start))
+ return 1;
+
+ return 0;
+}
+
+int __init dt_scan_for_memory_reserve(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ char *memory_name_prop;
+ unsigned int *memory_remove_prop;
+ unsigned long memory_name_prop_length;
+ unsigned long memory_remove_prop_length;
+ unsigned long memory_size_prop_length;
+ unsigned int *memory_size_prop;
+ unsigned int memory_size;
+ unsigned int memory_start;
+ int ret;
+
+ memory_name_prop = of_get_flat_dt_prop(node,
+ "qcom,memory-reservation-type",
+ &memory_name_prop_length);
+ memory_remove_prop = of_get_flat_dt_prop(node,
+ "qcom,memblock-remove",
+ &memory_remove_prop_length);
+
+ if (memory_name_prop || memory_remove_prop) {
+ if (!check_for_compat(node))
+ goto out;
+ } else {
+ goto out;
+ }
+
+ if (memory_name_prop) {
+ if (strnlen(memory_name_prop, memory_name_prop_length) == 0) {
+ WARN(1, "Memory name was malformed\n");
+ goto mem_remove;
+ }
+
+ memory_size_prop = of_get_flat_dt_prop(node,
+ "qcom,memory-reservation-size",
+ &memory_size_prop_length);
+
+ if (memory_size_prop &&
+ (memory_size_prop_length == sizeof(unsigned int))) {
+ memory_size = be32_to_cpu(*memory_size_prop);
+
+ if (reserve_memory_type(memory_name_prop,
+ data, memory_size) == 0)
+ pr_info("%s reserved %s size %x\n",
+ uname, memory_name_prop, memory_size);
+ else
+ WARN(1, "Node %s reserve failed\n",
+ uname);
+ } else {
+ WARN(1, "Node %s specified bad/nonexistent size\n",
+ uname);
+ }
+ }
+
+mem_remove:
+
+ if (memory_remove_prop) {
+ if (memory_remove_prop_length != (2*sizeof(unsigned int))) {
+ WARN(1, "Memory remove malformed\n");
+ goto out;
+ }
+
+ memory_start = be32_to_cpu(memory_remove_prop[0]);
+ memory_size = be32_to_cpu(memory_remove_prop[1]);
+
+ ret = memblock_remove(memory_start, memory_size);
+ if (ret)
+ WARN(1, "Failed to remove memory %x-%x\n",
+ memory_start, memory_start+memory_size);
+ else
+ pr_info("Node %s removed memory %x-%x\n", uname,
+ memory_start, memory_start+memory_size);
+ }
+
+out:
+ return 0;
+}
diff --git a/arch/arm/mach-msm/mpm-8625.c b/arch/arm/mach-msm/mpm-8625.c
index 954e5cc..3c219be 100644
--- a/arch/arm/mach-msm/mpm-8625.c
+++ b/arch/arm/mach-msm/mpm-8625.c
@@ -221,7 +221,7 @@
/* save the contents of GIC CPU interface and Distributor
* Disable all the Interrupts, if we enter from idle pc
*/
- msm_gic_save(modem_wake, from_idle);
+ msm_gic_save();
irq_set_irq_type(MSM8625_INT_A9_M2A_6, IRQF_TRIGGER_RISING);
enable_irq(MSM8625_INT_A9_M2A_6);
pr_debug("%s going for sleep now\n", __func__);
diff --git a/arch/arm/mach-msm/msm-krait-l2-accessors.c b/arch/arm/mach-msm/msm-krait-l2-accessors.c
index 3d341e3..41a2490 100644
--- a/arch/arm/mach-msm/msm-krait-l2-accessors.c
+++ b/arch/arm/mach-msm/msm-krait-l2-accessors.c
@@ -14,19 +14,83 @@
#include <linux/spinlock.h>
#include <linux/module.h>
#include <asm/mach-types.h>
+#include <asm/cputype.h>
DEFINE_RAW_SPINLOCK(l2_access_lock);
+#define L2CPMR 0x500
+#define L2CPUCPMR 0x501
+#define L2CPUVRF8 0x708
+#define CPUNDX_MASK (0x7 << 12)
+
+/*
+ * For Krait versions found in APQ8064v1.x, save L2CPUVRF8 before
+ * L2CPMR or L2CPUCPMR writes and restore it after to work around an
+ * issue where L2CPUVRF8 becomes corrupt.
+ */
+static bool l2cpuvrf8_needs_fix(u32 reg_addr)
+{
+ switch (read_cpuid_id()) {
+ case 0x510F06F0: /* KR28M4A10 */
+ case 0x510F06F1: /* KR28M4A10B */
+ case 0x510F06F2: /* KR28M4A11 */
+ break;
+ default:
+ return false;
+ };
+
+ switch (reg_addr & ~CPUNDX_MASK) {
+ case L2CPMR:
+ case L2CPUCPMR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static u32 l2cpuvrf8_fix_save(u32 reg_addr, u32 *l2cpuvrf8_val)
+{
+ u32 l2cpuvrf8_addr = L2CPUVRF8 | (reg_addr & CPUNDX_MASK);
+
+ mb();
+ asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
+ "isb\n\t"
+ "mrc p15, 3, %[l2cpdr], c15, c0, 7\n\t"
+ : [l2cpdr]"=r" (*l2cpuvrf8_val)
+ : [l2cpselr]"r" (l2cpuvrf8_addr)
+ );
+
+ return l2cpuvrf8_addr;
+}
+
+static void l2cpuvrf8_fix_restore(u32 l2cpuvrf8_addr, u32 l2cpuvrf8_val)
+{
+ mb();
+ asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
+ "isb\n\t"
+ "mcr p15, 3, %[l2cpdr], c15, c0, 7\n\t"
+ "isb\n\t"
+ :
+ : [l2cpselr]"r" (l2cpuvrf8_addr),
+ [l2cpdr]"r" (l2cpuvrf8_val)
+ );
+}
+
u32 set_get_l2_indirect_reg(u32 reg_addr, u32 val)
{
unsigned long flags;
+ u32 uninitialized_var(l2cpuvrf8_val), l2cpuvrf8_addr = 0;
u32 ret_val;
+
/* CP15 registers are not emulated on RUMI3. */
if (machine_is_msm8960_rumi3())
return 0;
raw_spin_lock_irqsave(&l2_access_lock, flags);
+ if (l2cpuvrf8_needs_fix(reg_addr))
+ l2cpuvrf8_addr = l2cpuvrf8_fix_save(reg_addr, &l2cpuvrf8_val);
+
mb();
asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
"isb\n\t"
@@ -36,6 +100,10 @@
: [l2cpdr_read]"=r" (ret_val)
: [l2cpselr]"r" (reg_addr), [l2cpdr]"r" (val)
);
+
+ if (l2cpuvrf8_addr)
+ l2cpuvrf8_fix_restore(l2cpuvrf8_addr, l2cpuvrf8_val);
+
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
return ret_val;
@@ -45,11 +113,17 @@
void set_l2_indirect_reg(u32 reg_addr, u32 val)
{
unsigned long flags;
+ u32 uninitialized_var(l2cpuvrf8_val), l2cpuvrf8_addr = 0;
+
/* CP15 registers are not emulated on RUMI3. */
if (machine_is_msm8960_rumi3())
return;
raw_spin_lock_irqsave(&l2_access_lock, flags);
+
+ if (l2cpuvrf8_needs_fix(reg_addr))
+ l2cpuvrf8_addr = l2cpuvrf8_fix_save(reg_addr, &l2cpuvrf8_val);
+
mb();
asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
"isb\n\t"
@@ -58,6 +132,10 @@
:
: [l2cpselr]"r" (reg_addr), [l2cpdr]"r" (val)
);
+
+ if (l2cpuvrf8_addr)
+ l2cpuvrf8_fix_restore(l2cpuvrf8_addr, l2cpuvrf8_val);
+
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
}
EXPORT_SYMBOL(set_l2_indirect_reg);
diff --git a/arch/arm/mach-msm/msm_memory_dump.c b/arch/arm/mach-msm/msm_memory_dump.c
new file mode 100644
index 0000000..4f48a0d
--- /dev/null
+++ b/arch/arm/mach-msm/msm_memory_dump.c
@@ -0,0 +1,78 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 <asm/cacheflush.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/export.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_memory_dump.h>
+
+
+/*TODO: Needs to be set to correct value */
+#define DUMP_TABLE_OFFSET 0x20
+#define MSM_DUMP_TABLE_VERSION MK_TABLE(1, 0)
+
+static struct msm_memory_dump mem_dump_data;
+
+static int msm_memory_dump_panic(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ writel_relaxed(0, MSM_IMEM_BASE + DUMP_TABLE_OFFSET);
+ return 0;
+}
+
+static struct notifier_block msm_memory_dump_blk = {
+ .notifier_call = msm_memory_dump_panic,
+};
+
+int msm_dump_table_register(struct msm_client_dump *client_entry)
+{
+ struct msm_client_dump *entry;
+ struct msm_dump_table *table = mem_dump_data.dump_table_ptr;
+
+ if (!table || table->num_entries >= MAX_NUM_CLIENTS)
+ return -EINVAL;
+ entry = &table->client_entries[table->num_entries];
+ entry->id = client_entry->id;
+ entry->start_addr = client_entry->start_addr;
+ entry->end_addr = client_entry->end_addr;
+ table->num_entries++;
+ /* flush cache */
+ dmac_flush_range(table, table + sizeof(struct msm_dump_table));
+ return 0;
+}
+EXPORT_SYMBOL(msm_dump_table_register);
+
+static int __init init_memory_dump(void)
+{
+ struct msm_dump_table *table;
+
+ mem_dump_data.dump_table_ptr = kzalloc(sizeof(struct msm_dump_table),
+ GFP_KERNEL);
+ if (!mem_dump_data.dump_table_ptr) {
+ printk(KERN_ERR "unable to allocate memory for dump table\n");
+ return -ENOMEM;
+ }
+ table = mem_dump_data.dump_table_ptr;
+ table->version = MSM_DUMP_TABLE_VERSION;
+ mem_dump_data.dump_table_phys = virt_to_phys(table);
+ /* TODO: Need to write physical address of table to IMEM */
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &msm_memory_dump_blk);
+ printk(KERN_INFO "MSM Memory Dump table set up\n");
+ return 0;
+}
+
+early_initcall(init_memory_dump);
+
diff --git a/arch/arm/mach-msm/msm_smem_iface.c b/arch/arm/mach-msm/msm_smem_iface.c
new file mode 100644
index 0000000..b09fda5
--- /dev/null
+++ b/arch/arm/mach-msm/msm_smem_iface.c
@@ -0,0 +1,44 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 "msm_smem_iface.h"
+
+/**
+ * mem_get_cpr_info() - Copy Core Power Reduction (CPR) driver specific
+ * data from Shared memory (SMEM).
+ * @cpr_info - Pointer to CPR data. Memory to be allocated and freed by
+ * calling function.
+ *
+ * Copy CPR specific data from SMEM to cpr_info.
+ */
+
+void msm_smem_get_cpr_info(struct cpr_info_type *cpr_info)
+{
+ struct boot_info_for_apps *boot_info;
+ struct cpr_info_type *temp_cpr_info;
+ uint32_t smem_boot_info_size;
+
+ boot_info = smem_get_entry(SMEM_BOOT_INFO_FOR_APPS,
+ &smem_boot_info_size);
+ BUG_ON(!boot_info);
+ if (smem_boot_info_size < sizeof(struct boot_info_for_apps)) {
+ pr_err("%s: Shared boot info data structure too small!\n",
+ __func__);
+ BUG();
+ } else {
+ pr_debug("%s: Shared boot info available.\n", __func__);
+ }
+ temp_cpr_info = (struct cpr_info_type *) &(boot_info->cpr_info);
+ cpr_info->ring_osc = temp_cpr_info->ring_osc;
+ cpr_info->turbo_quot = temp_cpr_info->turbo_quot;
+ cpr_info->pvs_fuse = temp_cpr_info->pvs_fuse;
+}
diff --git a/arch/arm/mach-msm/msm_smem_iface.h b/arch/arm/mach-msm/msm_smem_iface.h
new file mode 100644
index 0000000..2da0232
--- /dev/null
+++ b/arch/arm/mach-msm/msm_smem_iface.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_SMEM_IFACE_H
+#define __ARCH_ARM_MACH_MSM_SMEM_IFACE_H
+
+#include <mach/msm_smsm.h>
+#include "smd_private.h"
+
+#define MAX_KEY_EVENTS 10
+#define MAX_SEC_KEY_PAYLOAD 32
+
+struct boot_shared_ssd_status_info {
+ uint32_t update_status; /* To check if process is successful or not */
+ uint32_t bl_error_code; /* To indicate error code in bootloader */
+};
+
+struct boot_symmetric_key_info {
+ uint32_t key_len; /* Encrypted Symmetric Key Length */
+ uint32_t iv_len; /* Initialization Vector Length */
+ uint8_t key[MAX_SEC_KEY_PAYLOAD]; /* Encrypted Symmetric Key */
+ uint8_t iv[MAX_SEC_KEY_PAYLOAD]; /* Initialization Vector */
+};
+
+struct cpr_info_type {
+ uint8_t ring_osc; /* CPR FUSE [0]: TURBO RO SEL BIT */
+ uint8_t turbo_quot; /* CPRFUSE[1:7] : TURBO QUOT*/
+ uint8_t pvs_fuse; /* TURBO PVS FUSE */
+};
+
+struct boot_info_for_apps {
+ uint32_t apps_image_start_addr; /* apps image start address */
+ uint32_t boot_flags; /* bit mask of upto 32 flags */
+ struct boot_shared_ssd_status_info ssd_status_info; /* SSD status */
+ struct boot_symmetric_key_info key_info;
+ uint16_t boot_keys_pressed[MAX_KEY_EVENTS]; /* Log of key presses */
+ uint32_t timetick; /* Modem tick timer value before apps out of reset */
+ struct cpr_info_type cpr_info;
+ uint8_t PAD[25];
+};
+
+void msm_smem_get_cpr_info(struct cpr_info_type *cpr_info);
+
+#endif /* __ARCH_ARM_MACH_MSM_SMEM_IFACE_H */
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index a233080..b42ac8f 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -55,6 +55,7 @@
static struct ocmem_plat_data *ocmem_pdata;
#define CLIENT_NAME_MAX 10
+
/* Must be in sync with enum ocmem_client */
static const char *client_names[OCMEM_CLIENT_MAX] = {
"graphics",
@@ -64,7 +65,7 @@
"voice",
"lp_audio",
"sensors",
- "blast",
+ "other_os",
};
struct ocmem_quota_table {
@@ -85,7 +86,7 @@
{ "voice", OCMEM_VOICE, 0x0, 0x0, 0x0, 0 },
{ "hp_audio", OCMEM_HP_AUDIO, 0x0, 0x0, 0x0, 0},
{ "lp_audio", OCMEM_LP_AUDIO, 0x80000, 0xA0000, 0xA0000, 0},
- { "blast", OCMEM_BLAST, 0x120000, 0x20000, 0x20000, 0},
+ { "other_os", OCMEM_OTHER_OS, 0x120000, 0x20000, 0x20000, 0},
{ "sensors", OCMEM_SENSORS, 0x140000, 0x40000, 0x40000, 0},
};
@@ -99,6 +100,18 @@
return -EINVAL;
}
+int check_id(int id)
+{
+ return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
+}
+
+const char *get_name(int id)
+{
+ if (!check_id(id))
+ return NULL;
+ return client_names[id];
+}
+
inline unsigned long phys_to_offset(unsigned long addr)
{
if (!ocmem_pdata)
@@ -455,7 +468,7 @@
zone->owner = part->id;
zone->active_regions = 0;
zone->max_regions = 0;
- INIT_LIST_HEAD(&zone->region_list);
+ INIT_LIST_HEAD(&zone->req_list);
zone->z_ops = z_ops;
if (part->p_tail) {
z_ops->allocate = allocate_tail;
@@ -519,6 +532,10 @@
writel_relaxed(REGION_ENABLE, ocmem_region_vbase);
writel_relaxed(REGION_ENABLE, ocmem_region_vbase + 4);
writel_relaxed(REGION_ENABLE, ocmem_region_vbase + 8);
+
+ if (ocmem_rdm_init(pdev))
+ return -EBUSY;
+
dev_dbg(dev, "initialized successfully\n");
return 0;
}
diff --git a/arch/arm/mach-msm/ocmem_api.c b/arch/arm/mach-msm/ocmem_api.c
index bed13de..bb32fca 100644
--- a/arch/arm/mach-msm/ocmem_api.c
+++ b/arch/arm/mach-msm/ocmem_api.c
@@ -13,10 +13,8 @@
#include <linux/slab.h>
#include <mach/ocmem_priv.h>
-static inline int check_id(int id)
-{
- return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
-}
+static DEFINE_MUTEX(ocmem_eviction_lock);
+static DECLARE_BITMAP(evicted, OCMEM_CLIENT_MAX);
static struct ocmem_handle *generate_handle(void)
{
@@ -61,6 +59,24 @@
return 0;
}
+static int __ocmem_shrink(int id, struct ocmem_buf *buf, unsigned long len)
+{
+ int ret = 0;
+ struct ocmem_handle *handle = buffer_to_handle(buf);
+
+ if (!handle)
+ return -EINVAL;
+
+ mutex_lock(&handle->handle_mutex);
+ ret = process_shrink(id, handle, len);
+ mutex_unlock(&handle->handle_mutex);
+
+ if (ret)
+ return -EINVAL;
+
+ return 0;
+}
+
static struct ocmem_buf *__ocmem_allocate_range(int id, unsigned long min,
unsigned long max, unsigned long step, bool block, bool wait)
{
@@ -218,6 +234,15 @@
return __ocmem_free(client_id, buffer);
}
+int ocmem_shrink(int client_id, struct ocmem_buf *buffer, unsigned long len)
+{
+ if (!buffer)
+ return -EINVAL;
+ if (len >= buffer->len)
+ return -EINVAL;
+ return __ocmem_shrink(client_id, buffer, len);
+}
+
int pre_validate_chunk_list(struct ocmem_map_list *list)
{
int i = 0;
@@ -236,8 +261,12 @@
for (i = 0; i < list->num_chunks; i++) {
if (!chunks[i].ddr_paddr ||
- chunks[i].size < MIN_CHUNK_SIZE)
+ chunks[i].size < MIN_CHUNK_SIZE ||
+ !IS_ALIGNED(chunks[i].size, MIN_CHUNK_SIZE)) {
+ pr_err("Invalid ocmem chunk at index %d (p: %lx, size %lx)\n",
+ i, chunks[i].ddr_paddr, chunks[i].size);
return -EINVAL;
+ }
}
return 0;
}
@@ -265,7 +294,7 @@
return -EINVAL;
}
- if (!pre_validate_chunk_list(list))
+ if (pre_validate_chunk_list(list) != 0)
return -EINVAL;
handle = buffer_to_handle(buffer);
@@ -303,14 +332,10 @@
return -EINVAL;
}
- if (!pre_validate_chunk_list(list))
+ if (pre_validate_chunk_list(list) != 0)
return -EINVAL;
handle = buffer_to_handle(buffer);
-
- if (!handle)
- return -EINVAL;
-
mutex_lock(&handle->handle_mutex);
ret = process_xfer(client_id, handle, list, TO_DDR);
mutex_unlock(&handle->handle_mutex);
@@ -325,3 +350,52 @@
}
return process_quota(client_id);
}
+
+/* Synchronous eviction/restore calls */
+/* Only a single eviction or restoration is allowed */
+/* Evictions/Restorations cannot be concurrent with other maps */
+int ocmem_evict(int client_id)
+{
+ int ret = 0;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ocmem_eviction_lock);
+ if (test_bit(client_id, evicted)) {
+ pr_err("ocmem: Previous eviction was not restored by %d\n",
+ client_id);
+ mutex_unlock(&ocmem_eviction_lock);
+ return -EINVAL;
+ }
+
+ ret = process_evict(client_id);
+ if (ret == 0)
+ set_bit(client_id, evicted);
+
+ mutex_unlock(&ocmem_eviction_lock);
+ return ret;
+}
+
+int ocmem_restore(int client_id)
+{
+ int ret = 0;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ocmem_eviction_lock);
+ if (!test_bit(client_id, evicted)) {
+ pr_err("ocmem: No previous eviction by %d\n", client_id);
+ mutex_unlock(&ocmem_eviction_lock);
+ return -EINVAL;
+ }
+ ret = process_restore(client_id);
+ clear_bit(client_id, evicted);
+ mutex_unlock(&ocmem_eviction_lock);
+ return ret;
+}
diff --git a/arch/arm/mach-msm/ocmem_notifier.c b/arch/arm/mach-msm/ocmem_notifier.c
index 4754f44..9fbcd73 100644
--- a/arch/arm/mach-msm/ocmem_notifier.c
+++ b/arch/arm/mach-msm/ocmem_notifier.c
@@ -24,11 +24,6 @@
unsigned listeners;
} notifiers[OCMEM_CLIENT_MAX];
-static int check_id(int id)
-{
- return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
-}
-
int check_notifier(int id)
{
int ret = 0;
diff --git a/arch/arm/mach-msm/ocmem_rdm.c b/arch/arm/mach-msm/ocmem_rdm.c
new file mode 100644
index 0000000..6b93d04
--- /dev/null
+++ b/arch/arm/mach-msm/ocmem_rdm.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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/module.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/rbtree.h>
+#include <linux/genalloc.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <mach/ocmem_priv.h>
+
+#define RDM_MAX_ENTRIES 32
+#define RDM_MAX_CLIENTS 2
+
+/* Data Mover Parameters */
+#define DM_BLOCK_128 0x0
+#define DM_BLOCK_256 0x1
+#define DM_BR_ID_LPASS 0x0
+#define DM_BR_ID_GPS 0x1
+
+#define DM_INTR_CLR (0x8)
+#define DM_INTR_MASK (0xC)
+#define DM_GEN_STATUS (0x10)
+#define DM_STATUS (0x14)
+#define DM_CTRL (0x1000)
+#define DM_TBL_BASE (0x1010)
+#define DM_TBL_IDX(x) ((x) * 0x18)
+#define DM_TBL_n(x) (DM_TBL_BASE + (DM_TBL_IDX(x)))
+#define DM_TBL_n_offset(x) DM_TBL_n(x)
+#define DM_TBL_n_size(x) (DM_TBL_n(x)+0x4)
+#define DM_TBL_n_paddr(x) (DM_TBL_n(x)+0x8)
+#define DM_TBL_n_ctrl(x) (DM_TBL_n(x)+0x10)
+
+#define BR_CTRL (0x0)
+#define BR_CLIENT_BASE (0x4)
+#define BR_CLIENT_n_IDX(x) ((x) * 0x4)
+#define BR_CLIENT_n_ctrl(x) (BR_CLIENT_BASE + (BR_CLIENT_n_IDX(x)))
+#define BR_STATUS (0x14)
+/* 16 entries per client are supported */
+/* Use entries 0 - 15 for client0 */
+#define BR_CLIENT0_MASK (0x1000)
+/* Use entries 16- 31 for client1 */
+#define BR_CLIENT1_MASK (0x2010)
+
+#define BR_TBL_BASE (0x40)
+#define BR_TBL_IDX(x) ((x) * 0x18)
+#define BR_TBL_n(x) (BR_TBL_BASE + (BR_TBL_IDX(x)))
+#define BR_TBL_n_offset(x) BR_TBL_n(x)
+#define BR_TBL_n_size(x) (BR_TBL_n(x)+0x4)
+#define BR_TBL_n_paddr(x) (BR_TBL_n(x)+0x8)
+#define BR_TBL_n_ctrl(x) (BR_TBL_n(x)+0x10)
+
+/* Constants and Shifts */
+#define BR_TBL_ENTRY_ENABLE 0x1
+#define BR_TBL_START 0x0
+#define BR_TBL_END 0x8
+#define BR_RW_SHIFT 0x2
+
+#define DM_TBL_START 0x10
+#define DM_TBL_END 0x18
+#define DM_CLIENT_SHIFT 0x8
+#define DM_BR_ID_SHIFT 0x4
+#define DM_BR_BLK_SHIFT 0x1
+#define DM_DIR_SHIFT 0x0
+
+#define DM_DONE 0x1
+#define DM_INTR_ENABLE 0x0
+#define DM_INTR_DISABLE 0x1
+
+static void *br_base;
+static void *dm_base;
+
+static atomic_t dm_pending;
+static wait_queue_head_t dm_wq;
+/* Shadow tables for debug purposes */
+struct ocmem_br_table {
+ unsigned int offset;
+ unsigned int size;
+ unsigned int ddr_low;
+ unsigned int ddr_high;
+ unsigned int ctrl;
+} br_table[RDM_MAX_ENTRIES];
+
+/* DM Table replicates an entire BR table */
+/* Note: There are more than 1 BRs in the system */
+struct ocmem_dm_table {
+ unsigned int offset;
+ unsigned int size;
+ unsigned int ddr_low;
+ unsigned int ddr_high;
+ unsigned int ctrl;
+} dm_table[RDM_MAX_ENTRIES];
+
+/* Wrapper that will shadow these values later */
+static int ocmem_read(void *at)
+{
+ return readl_relaxed(at);
+}
+
+/* Wrapper that will shadow these values later */
+static int ocmem_write(unsigned long val, void *at)
+{
+ writel_relaxed(val, at);
+ return 0;
+}
+
+static inline int client_ctrl_id(int id)
+{
+ return (id == OCMEM_SENSORS) ? 1 : 0;
+}
+
+static inline int client_slot_start(int id)
+{
+
+ return client_ctrl_id(id) * 16;
+}
+
+static irqreturn_t ocmem_dm_irq_handler(int irq, void *dev_id)
+{
+ atomic_set(&dm_pending, 0);
+ ocmem_write(DM_INTR_DISABLE, dm_base + DM_INTR_CLR);
+ wake_up_interruptible(&dm_wq);
+ return IRQ_HANDLED;
+}
+
+/* Lock during transfers */
+int ocmem_rdm_transfer(int id, struct ocmem_map_list *clist,
+ unsigned long start, int direction)
+{
+ int num_chunks = clist->num_chunks;
+ int slot = client_slot_start(id);
+ int table_start = 0;
+ int table_end = 0;
+ int br_ctrl = 0;
+ int br_id = 0;
+ int dm_ctrl = 0;
+ int i = 0;
+ int j = 0;
+ int status = 0;
+
+ for (i = 0, j = slot; i < num_chunks; i++, j++) {
+
+ struct ocmem_chunk *chunk = &clist->chunks[i];
+ int sz = chunk->size;
+ int paddr = chunk->ddr_paddr;
+ int tbl_n_ctrl = 0;
+
+ tbl_n_ctrl |= BR_TBL_ENTRY_ENABLE;
+ if (chunk->ro)
+ tbl_n_ctrl |= (1 << BR_RW_SHIFT);
+
+ /* Table Entry n of BR and DM */
+ ocmem_write(start, br_base + BR_TBL_n_offset(j));
+ ocmem_write(sz, br_base + BR_TBL_n_size(j));
+ ocmem_write(paddr, br_base + BR_TBL_n_paddr(j));
+ ocmem_write(tbl_n_ctrl, br_base + BR_TBL_n_ctrl(j));
+
+ ocmem_write(start, dm_base + DM_TBL_n_offset(j));
+ ocmem_write(sz, dm_base + DM_TBL_n_size(j));
+ ocmem_write(paddr, dm_base + DM_TBL_n_paddr(j));
+ ocmem_write(tbl_n_ctrl, dm_base + DM_TBL_n_ctrl(j));
+
+ start += sz;
+ }
+
+ br_id = client_ctrl_id(id);
+ table_start = slot;
+ table_end = slot + num_chunks - 1;
+ br_ctrl |= (table_start << BR_TBL_START);
+ br_ctrl |= (table_end << BR_TBL_END);
+
+ ocmem_write(br_ctrl, (br_base + BR_CLIENT_n_ctrl(br_id)));
+ /* Enable BR */
+ ocmem_write(0x1, br_base + BR_CTRL);
+
+ /* Compute DM Control Value */
+ dm_ctrl |= (table_start << DM_TBL_START);
+ dm_ctrl |= (table_end << DM_TBL_END);
+
+ dm_ctrl |= (DM_BR_ID_LPASS << DM_BR_ID_SHIFT);
+ dm_ctrl |= (DM_BLOCK_256 << DM_BR_BLK_SHIFT);
+ dm_ctrl |= (direction << DM_DIR_SHIFT);
+
+ status = ocmem_read(dm_base + DM_STATUS);
+ pr_debug("Transfer status before %x\n", status);
+ atomic_set(&dm_pending, 1);
+ /* Trigger DM */
+ ocmem_write(dm_ctrl, dm_base + DM_CTRL);
+ pr_debug("ocmem: rdm: dm_ctrl %x br_ctrl %x\n", dm_ctrl, br_ctrl);
+
+ wait_event_interruptible(dm_wq,
+ atomic_read(&dm_pending) == 0);
+
+ return 0;
+}
+
+int ocmem_rdm_init(struct platform_device *pdev)
+{
+
+ struct ocmem_plat_data *pdata = NULL;
+ int rc = 0;
+
+ pdata = platform_get_drvdata(pdev);
+
+ br_base = pdata->br_base;
+ dm_base = pdata->dm_base;
+
+ rc = devm_request_irq(&pdev->dev, pdata->dm_irq, ocmem_dm_irq_handler,
+ IRQF_TRIGGER_RISING, "ocmem_dm_irq", pdata);
+
+ if (rc) {
+ dev_err(&pdev->dev, "Failed to request dm irq");
+ return -EINVAL;
+ }
+
+ init_waitqueue_head(&dm_wq);
+ /* enable dm interrupts */
+ ocmem_write(DM_INTR_ENABLE, dm_base + DM_INTR_MASK);
+ return 0;
+}
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 10a267c..f6d066d 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -54,7 +54,7 @@
MIN_PRIO = 0x0,
NO_PRIO = MIN_PRIO,
PRIO_SENSORS = 0x1,
- PRIO_BLAST = 0x1,
+ PRIO_OTHER_OS = 0x1,
PRIO_LP_AUDIO = 0x1,
PRIO_HP_AUDIO = 0x2,
PRIO_VOICE = 0x3,
@@ -75,6 +75,21 @@
*/
#define SCHED_DELAY 10
+static struct list_head rdm_queue;
+static struct mutex rdm_mutex;
+static struct workqueue_struct *ocmem_rdm_wq;
+static struct workqueue_struct *ocmem_eviction_wq;
+
+static struct ocmem_eviction_data *evictions[OCMEM_CLIENT_MAX];
+
+struct ocmem_rdm_work {
+ int id;
+ struct ocmem_map_list *list;
+ struct ocmem_handle *handle;
+ int direction;
+ struct work_struct work;
+};
+
/* OCMEM Operational modes */
enum ocmem_client_modes {
OCMEM_PERFORMANCE = 1,
@@ -107,7 +122,7 @@
{OCMEM_VOICE, PRIO_VOICE, OCMEM_PASSIVE, OCMEM_BLOCKED},
{OCMEM_LP_AUDIO, PRIO_LP_AUDIO, OCMEM_LOW_POWER, OCMEM_SYSNOC},
{OCMEM_SENSORS, PRIO_SENSORS, OCMEM_LOW_POWER, OCMEM_SYSNOC},
- {OCMEM_BLAST, PRIO_BLAST, OCMEM_LOW_POWER, OCMEM_SYSNOC},
+ {OCMEM_OTHER_OS, PRIO_OTHER_OS, OCMEM_LOW_POWER, OCMEM_SYSNOC},
};
static struct rb_root sched_tree;
@@ -119,6 +134,8 @@
struct rb_node region_rb;
/* Hash map of requests */
struct idr region_idr;
+ /* Chain in eviction list */
+ struct list_head eviction_list;
unsigned long r_start;
unsigned long r_end;
unsigned long r_sz;
@@ -244,6 +261,7 @@
if (!p)
return NULL;
idr_init(&p->region_idr);
+ INIT_LIST_HEAD(&p->eviction_list);
p->r_start = p->r_end = p->r_sz = 0x0;
p->max_prio = NO_PRIO;
return p;
@@ -461,10 +479,14 @@
{
int rc = 0;
+ down_write(&req->rw_sem);
+
mutex_lock(&sched_mutex);
rc = __sched_map(req);
mutex_unlock(&sched_mutex);
+ up_write(&req->rw_sem);
+
if (rc == OP_FAIL)
return -EINVAL;
@@ -475,10 +497,14 @@
{
int rc = 0;
+ down_write(&req->rw_sem);
+
mutex_lock(&sched_mutex);
rc = __sched_unmap(req);
mutex_unlock(&sched_mutex);
+ up_write(&req->rw_sem);
+
if (rc == OP_FAIL)
return -EINVAL;
@@ -713,6 +739,104 @@
}
/* Must be called with sched_mutex held */
+static int __sched_shrink(struct ocmem_req *req, unsigned long new_sz)
+{
+ int owner = req->owner;
+ int ret = 0;
+
+ struct ocmem_req *matched_req = NULL;
+ struct ocmem_region *matched_region = NULL;
+ struct ocmem_region *region = NULL;
+ unsigned long alloc_addr = 0x0;
+
+ struct ocmem_zone *zone = get_zone(owner);
+
+ BUG_ON(!zone);
+
+ /* The shrink should not be called for zero size */
+ BUG_ON(new_sz == 0);
+
+ matched_region = find_region_match(req->req_start, req->req_end);
+ matched_req = find_req_match(req->req_id, matched_region);
+
+ if (!matched_region || !matched_req)
+ goto invalid_op_error;
+ if (matched_req != req)
+ goto invalid_op_error;
+
+
+ ret = zone->z_ops->free(zone,
+ matched_req->req_start, matched_req->req_sz);
+
+ if (ret < 0) {
+ pr_err("Zone Allocation operation failed\n");
+ goto internal_error;
+ }
+
+ alloc_addr = zone->z_ops->allocate(zone, new_sz);
+
+ if (alloc_addr < 0) {
+ pr_err("Zone Allocation operation failed\n");
+ goto internal_error;
+ }
+
+ /* Detach the region from the interval tree */
+ /* This is to guarantee that the change in size
+ * causes the tree to be rebalanced if required */
+
+ detach_req(matched_region, req);
+ if (req_count(matched_region) == 0) {
+ remove_region(matched_region);
+ region = matched_region;
+ } else {
+ region = create_region();
+ if (!region) {
+ pr_err("ocmem: Unable to create region\n");
+ goto internal_error;
+ }
+ }
+ /* update the request */
+ req->req_start = alloc_addr;
+ req->req_sz = new_sz;
+ req->req_end = alloc_addr + req->req_sz;
+
+ if (req_count(region) == 0) {
+ remove_region(matched_region);
+ destroy_region(matched_region);
+ }
+
+ /* update request state */
+ SET_STATE(req, R_MUST_GROW);
+ SET_STATE(req, R_MUST_MAP);
+ req->op = SCHED_MAP;
+
+ /* attach the request to the region */
+ attach_req(region, req);
+ populate_region(region, req);
+ update_region_prio(region);
+
+ /* update the tree with new region */
+ if (insert_region(region)) {
+ pr_err("ocmem: Failed to insert the region\n");
+ zone->z_ops->free(zone, alloc_addr, new_sz);
+ detach_req(region, req);
+ update_region_prio(region);
+ /* req will be destroyed by the caller */
+ goto region_error;
+ }
+ return OP_COMPLETE;
+
+region_error:
+ destroy_region(region);
+internal_error:
+ pr_err("ocmem: shrink: Failed\n");
+ return OP_FAIL;
+invalid_op_error:
+ pr_err("ocmem: shrink: Failed to find matching region\n");
+ return OP_FAIL;
+}
+
+/* Must be called with sched_mutex held */
static int __sched_allocate(struct ocmem_req *req, bool can_block,
bool can_wait)
{
@@ -906,12 +1030,6 @@
return req;
}
-int process_xfer(int id, struct ocmem_handle *handle,
- struct ocmem_map_list *list, int direction)
-{
-
- return 0;
-}
unsigned long process_quota(int id)
{
@@ -989,6 +1107,35 @@
return 0;
}
+static int do_shrink(struct ocmem_req *req, unsigned long shrink_size)
+{
+
+ int rc = 0;
+ struct ocmem_buf *buffer = NULL;
+
+ down_write(&req->rw_sem);
+ buffer = req->buffer;
+
+ /* Take the scheduler mutex */
+ mutex_lock(&sched_mutex);
+ rc = __sched_shrink(req, shrink_size);
+ mutex_unlock(&sched_mutex);
+
+ if (rc == OP_FAIL)
+ goto err_op_fail;
+
+ else if (rc == OP_COMPLETE) {
+ buffer->addr = device_address(req->owner, req->req_start);
+ buffer->len = req->req_sz;
+ }
+
+ up_write(&req->rw_sem);
+ return 0;
+err_op_fail:
+ up_write(&req->rw_sem);
+ return -EINVAL;
+}
+
static void ocmem_sched_wk_func(struct work_struct *work);
DECLARE_DELAYED_WORK(ocmem_sched_thread, ocmem_sched_wk_func);
@@ -1076,6 +1223,250 @@
return 0;
}
+static void ocmem_rdm_worker(struct work_struct *work)
+{
+ int offset = 0;
+ int rc = 0;
+ int event;
+ struct ocmem_rdm_work *work_data = container_of(work,
+ struct ocmem_rdm_work, work);
+ int id = work_data->id;
+ struct ocmem_map_list *list = work_data->list;
+ int direction = work_data->direction;
+ struct ocmem_handle *handle = work_data->handle;
+ struct ocmem_req *req = handle_to_req(handle);
+ struct ocmem_buf *buffer = handle_to_buffer(handle);
+
+ down_write(&req->rw_sem);
+ offset = phys_to_offset(req->req_start);
+ rc = ocmem_rdm_transfer(id, list, offset, direction);
+ if (work_data->direction == TO_OCMEM)
+ event = (rc == 0) ? OCMEM_MAP_DONE : OCMEM_MAP_FAIL;
+ else
+ event = (rc == 0) ? OCMEM_UNMAP_DONE : OCMEM_UNMAP_FAIL;
+
+ up_write(&req->rw_sem);
+ kfree(work_data);
+ dispatch_notification(id, event, buffer);
+}
+
+int queue_transfer(struct ocmem_req *req, struct ocmem_handle *handle,
+ struct ocmem_map_list *list, int direction)
+{
+ struct ocmem_rdm_work *work_data = NULL;
+
+ down_write(&req->rw_sem);
+
+ work_data = kzalloc(sizeof(struct ocmem_rdm_work), GFP_ATOMIC);
+ if (!work_data)
+ BUG();
+
+ work_data->handle = handle;
+ work_data->list = list;
+ work_data->id = req->owner;
+ work_data->direction = direction;
+ INIT_WORK(&work_data->work, ocmem_rdm_worker);
+ up_write(&req->rw_sem);
+ queue_work(ocmem_rdm_wq, &work_data->work);
+ return 0;
+}
+
+int process_xfer_out(int id, struct ocmem_handle *handle,
+ struct ocmem_map_list *list)
+{
+ struct ocmem_req *req = NULL;
+ int rc = 0;
+
+ req = handle_to_req(handle);
+
+ if (!req)
+ return -EINVAL;
+
+ if (!is_mapped(req)) {
+ pr_err("Buffer is not already mapped\n");
+ goto transfer_out_error;
+ }
+
+ rc = process_unmap(req, req->req_start, req->req_end);
+ if (rc < 0) {
+ pr_err("Unmapping the buffer failed\n");
+ goto transfer_out_error;
+ }
+
+ rc = queue_transfer(req, handle, list, TO_DDR);
+
+ if (rc < 0) {
+ pr_err("Failed to queue rdm transfer to DDR\n");
+ goto transfer_out_error;
+ }
+
+ return 0;
+
+transfer_out_error:
+ return -EINVAL;
+}
+
+int process_xfer_in(int id, struct ocmem_handle *handle,
+ struct ocmem_map_list *list)
+{
+ struct ocmem_req *req = NULL;
+ int rc = 0;
+
+ req = handle_to_req(handle);
+
+ if (!req)
+ return -EINVAL;
+
+ if (is_mapped(req)) {
+ pr_err("Buffer is already mapped\n");
+ goto transfer_in_error;
+ }
+
+ rc = process_map(req, req->req_start, req->req_end);
+ if (rc < 0) {
+ pr_err("Mapping the buffer failed\n");
+ goto transfer_in_error;
+ }
+
+ rc = queue_transfer(req, handle, list, TO_OCMEM);
+
+ if (rc < 0) {
+ pr_err("Failed to queue rdm transfer to OCMEM\n");
+ goto transfer_in_error;
+ }
+
+ return 0;
+transfer_in_error:
+ return -EINVAL;
+}
+
+int process_shrink(int id, struct ocmem_handle *handle, unsigned long size)
+{
+ struct ocmem_req *req = NULL;
+ struct ocmem_buf *buffer = NULL;
+ struct ocmem_eviction_data *edata = NULL;
+ int rc = 0;
+
+ if (is_blocked(id)) {
+ pr_err("Client %d cannot request free\n", id);
+ return -EINVAL;
+ }
+
+ req = handle_to_req(handle);
+ buffer = handle_to_buffer(handle);
+
+ if (!req)
+ return -EINVAL;
+
+ if (req->req_start != core_address(id, buffer->addr)) {
+ pr_err("Invalid buffer handle passed for shrink\n");
+ return -EINVAL;
+ }
+
+ edata = req->edata;
+
+ if (is_tcm(req->owner))
+ do_unmap(req);
+
+ if (size == 0) {
+ pr_info("req %p being shrunk to zero\n", req);
+ rc = do_free(req);
+ if (rc < 0)
+ return -EINVAL;
+ } else {
+ rc = do_shrink(req, size);
+ if (rc < 0)
+ return -EINVAL;
+ }
+
+ edata->pending--;
+ if (edata->pending == 0) {
+ pr_debug("All regions evicted");
+ complete(&edata->completion);
+ }
+
+ return 0;
+}
+
+int process_xfer(int id, struct ocmem_handle *handle,
+ struct ocmem_map_list *list, int direction)
+{
+ int rc = 0;
+
+ if (is_tcm(id)) {
+ WARN(1, "Mapping operation is invalid for client\n");
+ return -EINVAL;
+ }
+
+ if (direction == TO_DDR)
+ rc = process_xfer_out(id, handle, list);
+ else if (direction == TO_OCMEM)
+ rc = process_xfer_in(id, handle, list);
+ return rc;
+}
+
+int ocmem_eviction_thread(struct work_struct *work)
+{
+ return 0;
+}
+
+int process_evict(int id)
+{
+ struct ocmem_eviction_data *edata = NULL;
+ int prio = ocmem_client_table[id].priority;
+ struct rb_node *rb_node = NULL;
+ struct ocmem_req *req = NULL;
+ struct ocmem_buf buffer;
+ int j = 0;
+
+ edata = kzalloc(sizeof(struct ocmem_eviction_data), GFP_ATOMIC);
+
+ INIT_LIST_HEAD(&edata->victim_list);
+ INIT_LIST_HEAD(&edata->req_list);
+ edata->prio = prio;
+ edata->pending = 0;
+ edata->passive = 1;
+ evictions[id] = edata;
+
+ mutex_lock(&sched_mutex);
+
+ for (rb_node = rb_first(&sched_tree); rb_node;
+ rb_node = rb_next(rb_node)) {
+ struct ocmem_region *tmp_region = NULL;
+ tmp_region = rb_entry(rb_node, struct ocmem_region, region_rb);
+ if (tmp_region->max_prio < prio) {
+ for (j = id - 1; j > NO_PRIO; j--) {
+ req = find_req_match(j, tmp_region);
+ if (req) {
+ pr_info("adding %p to eviction list\n",
+ tmp_region);
+ list_add_tail(
+ &tmp_region->eviction_list,
+ &edata->victim_list);
+ list_add_tail(
+ &req->eviction_list,
+ &edata->req_list);
+ edata->pending++;
+ req->edata = edata;
+ buffer.addr = req->req_start;
+ buffer.len = 0x0;
+ dispatch_notification(req->owner,
+ OCMEM_ALLOC_SHRINK, &buffer);
+ }
+ }
+ } else {
+ pr_info("skipping %p from eviction\n", tmp_region);
+ }
+ }
+ mutex_unlock(&sched_mutex);
+ pr_debug("Waiting for all regions to be shrunk\n");
+ if (edata->pending > 0) {
+ init_completion(&edata->completion);
+ wait_for_completion(&edata->completion);
+ }
+ return 0;
+}
+
static int do_allocate(struct ocmem_req *req, bool can_block, bool can_wait)
{
int rc = 0;
@@ -1113,6 +1504,31 @@
return -EINVAL;
}
+int process_restore(int id)
+{
+ struct ocmem_req *req = NULL;
+ struct ocmem_req *next = NULL;
+ struct ocmem_eviction_data *edata = evictions[id];
+
+ if (!edata)
+ return 0;
+
+ list_for_each_entry_safe(req, next, &edata->req_list, eviction_list)
+ {
+ if (req) {
+ pr_debug("ocmem: Fetched evicted request %p\n",
+ req);
+ list_del(&req->sched_list);
+ req->op = SCHED_ALLOCATE;
+ sched_enqueue(req);
+ }
+ }
+ kfree(edata);
+ evictions[id] = NULL;
+ pr_debug("Restore all evicted regions\n");
+ ocmem_schedule_pending();
+ return 0;
+}
int process_allocate(int id, struct ocmem_handle *handle,
unsigned long min, unsigned long max,
@@ -1185,6 +1601,7 @@
rc = do_allocate(req, true, false);
+
if (rc < 0)
goto do_allocate_error;
@@ -1251,5 +1668,13 @@
for (i = MIN_PRIO; i < MAX_OCMEM_PRIO; i++)
INIT_LIST_HEAD(&sched_queue[i]);
+ mutex_init(&rdm_mutex);
+ INIT_LIST_HEAD(&rdm_queue);
+ ocmem_rdm_wq = alloc_workqueue("ocmem_rdm_wq", 0, 0);
+ if (!ocmem_rdm_wq)
+ return -ENOMEM;
+ ocmem_eviction_wq = alloc_workqueue("ocmem_eviction_wq", 0, 0);
+ if (!ocmem_eviction_wq)
+ return -ENOMEM;
return 0;
}
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 42616c6..e203667 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -24,7 +24,6 @@
#include <linux/smp.h>
#include <linux/suspend.h>
#include <linux/tick.h>
-#include <linux/delay.h>
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
#include <mach/system.h>
@@ -799,28 +798,6 @@
return 0;
}
-static struct msm_pm_sleep_status_data *msm_pm_slp_sts;
-
-static DEFINE_PER_CPU_SHARED_ALIGNED(enum msm_pm_sleep_mode,
- msm_pm_last_slp_mode);
-
-bool msm_pm_verify_cpu_pc(unsigned int cpu)
-{
- enum msm_pm_sleep_mode mode = per_cpu(msm_pm_last_slp_mode, cpu);
-
- if (msm_pm_slp_sts) {
- int acc_sts = __raw_readl(msm_pm_slp_sts->base_addr
- + cpu * msm_pm_slp_sts->cpu_offset);
-
- if ((acc_sts & msm_pm_slp_sts->mask) &&
- ((mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) ||
- (mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)))
- return true;
- }
-
- return false;
-}
-
void msm_pm_cpu_enter_lowpower(unsigned int cpu)
{
int i;
@@ -836,54 +813,14 @@
if (MSM_PM_DEBUG_HOTPLUG & msm_pm_debug_mask)
pr_notice("CPU%u: %s: shutting down cpu\n", cpu, __func__);
- if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE]) {
- per_cpu(msm_pm_last_slp_mode, cpu)
- = MSM_PM_SLEEP_MODE_POWER_COLLAPSE;
+ if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE])
msm_pm_power_collapse(false);
- } else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
- per_cpu(msm_pm_last_slp_mode, cpu)
- = MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE;
+ else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE])
msm_pm_power_collapse_standalone(false);
- } else if (allow[MSM_PM_SLEEP_MODE_RETENTION]) {
- per_cpu(msm_pm_last_slp_mode, cpu)
- = MSM_PM_SLEEP_MODE_RETENTION;
+ else if (allow[MSM_PM_SLEEP_MODE_RETENTION])
msm_pm_retention();
- } else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
- per_cpu(msm_pm_last_slp_mode, cpu)
- = MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT;
+ else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT])
msm_pm_swfi();
- } else
- per_cpu(msm_pm_last_slp_mode, cpu) = MSM_PM_SLEEP_MODE_NR;
-}
-
-int msm_pm_wait_cpu_shutdown(unsigned int cpu)
-{
-
- int timeout = 10;
-
- if (!msm_pm_slp_sts)
- return 0;
-
- while (timeout--) {
-
- /*
- * Check for the SPM of the core being hotplugged to set
- * its sleep state.The SPM sleep state indicates that the
- * core has been power collapsed.
- */
-
- int acc_sts = __raw_readl(msm_pm_slp_sts->base_addr
- + cpu * msm_pm_slp_sts->cpu_offset);
- mb();
-
- if (acc_sts & msm_pm_slp_sts->mask)
- return 0;
-
- usleep(100);
- }
- pr_warn("%s(): Timed out waiting for CPU %u SPM to enter sleep state",
- __func__, cpu);
- return -EBUSY;
}
static int msm_pm_enter(suspend_state_t state)
@@ -980,12 +917,6 @@
/******************************************************************************
* Initialization routine
*****************************************************************************/
-void __init msm_pm_init_sleep_status_data(
- struct msm_pm_sleep_status_data *data)
-{
- msm_pm_slp_sts = data;
-}
-
void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops)
{
if (ops)
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index 70d54da..c722ff6 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -70,12 +70,6 @@
extern struct msm_pm_platform_data msm_pm_sleep_modes[];
-struct msm_pm_sleep_status_data {
- void *base_addr;
- uint32_t cpu_offset;
- uint32_t mask;
-};
-
struct msm_pm_sleep_ops {
void *(*lowest_limits)(bool from_idle,
enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
@@ -93,19 +87,11 @@
int msm_pm_idle_enter(enum msm_pm_sleep_mode sleep_mode);
void msm_pm_cpu_enter_lowpower(unsigned int cpu);
-void __init msm_pm_init_sleep_status_data(
- struct msm_pm_sleep_status_data *sleep_data);
-
-
#ifdef CONFIG_MSM_PM8X60
void msm_pm_set_rpm_wakeup_irq(unsigned int irq);
-int msm_pm_wait_cpu_shutdown(unsigned int cpu);
-bool msm_pm_verify_cpu_pc(unsigned int cpu);
void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops);
#else
static inline void msm_pm_set_rpm_wakeup_irq(unsigned int irq) {}
-static inline int msm_pm_wait_cpu_shutdown(unsigned int cpu) { return 0; }
-static inline bool msm_pm_verify_cpu_pc(unsigned int cpu) { return true; }
static inline void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops) {}
#endif
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 2403c02..a0bfb27 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -372,10 +372,14 @@
if (q6.state == APR_Q6_NOIMG) {
q6.pil = pil_get("q6");
if (IS_ERR(q6.pil)) {
- rc = PTR_ERR(q6.pil);
- pr_err("APR: Unable to load q6 image, error:%d\n", rc);
- mutex_unlock(&q6.lock);
- return svc;
+ q6.pil = pil_get("adsp");
+ if (IS_ERR(q6.pil)) {
+ rc = PTR_ERR(q6.pil);
+ pr_err("APR: Unable to load q6 image, error:%d\n",
+ rc);
+ mutex_unlock(&q6.lock);
+ return svc;
+ }
}
q6.state = APR_Q6_LOADED;
}
diff --git a/arch/arm/mach-msm/rpm_log.c b/arch/arm/mach-msm/rpm_log.c
index 3ed55da..4835cef 100644
--- a/arch/arm/mach-msm/rpm_log.c
+++ b/arch/arm/mach-msm/rpm_log.c
@@ -115,13 +115,11 @@
continue;
}
/*
- * Ensure that the reported buffer size is within limits of
- * known maximum size and that all indices are 4 byte aligned.
- * These conditions are required to interact with a ULog buffer
+ * Ensure that all indices are 4 byte aligned.
+ * This conditions is required to interact with a ULog buffer
* properly.
*/
- if (tail_idx - head_idx > pdata->log_len ||
- !IS_ALIGNED((tail_idx | head_idx | *read_idx), 4))
+ if (!IS_ALIGNED((tail_idx | head_idx | *read_idx), 4))
break;
msg_len = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_BUFFER,
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 54512ab..948dbbb 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -559,7 +559,11 @@
* on DEM-based targets. Grabbing a wakelock in this case will
* abort the power-down sequencing.
*/
- smsm_cb_snapshot(0);
+ if (smsm_info.intr_mask &&
+ (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_APPS))
+ & notify_mask)) {
+ smsm_cb_snapshot(0);
+ }
}
void smd_diag(void)
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 32f61f5..b6fb52a 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -32,6 +32,7 @@
#include <asm/sizes.h>
#include <asm/tlb.h>
#include <asm/fixmap.h>
+#include <asm/cputype.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -40,6 +41,8 @@
static unsigned long phys_initrd_start __initdata = 0;
static unsigned long phys_initrd_size __initdata = 0;
+int msm_krait_need_wfe_fixup;
+EXPORT_SYMBOL(msm_krait_need_wfe_fixup);
static int __init early_initrd(char *p)
{
@@ -916,3 +919,17 @@
__setup("keepinitrd", keepinitrd_setup);
#endif
+
+#ifdef CONFIG_MSM_KRAIT_WFE_FIXUP
+static int __init msm_krait_wfe_init(void)
+{
+ unsigned int val, midr;
+ midr = read_cpuid_id() & 0xffffff00;
+ if ((midr == 0x511f0400) || (midr == 0x510f0600)) {
+ asm volatile("mrc p15, 7, %0, c15, c0, 5" : "=r" (val));
+ msm_krait_need_wfe_fixup = (val & 0x10000) ? 1 : 0;
+ }
+ return 0;
+}
+pure_initcall(msm_krait_wfe_init);
+#endif
diff --git a/drivers/leds/leds-pm8xxx.c b/drivers/leds/leds-pm8xxx.c
index 3261037..04041e4 100644
--- a/drivers/leds/leds-pm8xxx.c
+++ b/drivers/leds/leds-pm8xxx.c
@@ -323,12 +323,17 @@
}
static void
-led_rgb_set(struct pm8xxx_led_data *led, enum led_brightness value)
+led_rgb_write(struct pm8xxx_led_data *led, u16 addr, enum led_brightness value)
{
int rc;
u8 val, mask;
- rc = pm8xxx_readb(led->dev->parent, SSBI_REG_ADDR_RGB_CNTL2, &val);
+ if (led->id != PM8XXX_ID_RGB_LED_BLUE &&
+ led->id != PM8XXX_ID_RGB_LED_RED &&
+ led->id != PM8XXX_ID_RGB_LED_GREEN)
+ return;
+
+ rc = pm8xxx_readb(led->dev->parent, addr, &val);
if (rc) {
dev_err(led->cdev.dev, "can't read rgb ctrl register rc=%d\n",
rc);
@@ -354,12 +359,24 @@
else
val &= ~mask;
- rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_RGB_CNTL2, val);
+ rc = pm8xxx_writeb(led->dev->parent, addr, val);
if (rc < 0)
dev_err(led->cdev.dev, "can't set rgb led %d level rc=%d\n",
led->id, rc);
}
+static void
+led_rgb_set(struct pm8xxx_led_data *led, enum led_brightness value)
+{
+ if (value) {
+ led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1, value);
+ led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL2, value);
+ } else {
+ led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL2, value);
+ led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1, value);
+ }
+}
+
static int pm8xxx_led_pwm_work(struct pm8xxx_led_data *led)
{
int duty_us;
@@ -369,12 +386,23 @@
duty_us = (led->pwm_period_us * led->cdev.brightness) /
LED_FULL;
rc = pwm_config(led->pwm_dev, duty_us, led->pwm_period_us);
- if (led->cdev.brightness)
+ if (led->cdev.brightness) {
+ led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1,
+ led->cdev.brightness);
rc = pwm_enable(led->pwm_dev);
- else
+ } else {
pwm_disable(led->pwm_dev);
+ led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1,
+ led->cdev.brightness);
+ }
} else {
+ if (led->cdev.brightness)
+ led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1,
+ led->cdev.brightness);
rc = pm8xxx_pwm_lut_enable(led->pwm_dev, led->cdev.brightness);
+ if (!led->cdev.brightness)
+ led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1,
+ led->cdev.brightness);
}
return rc;
@@ -658,35 +686,6 @@
return 0;
}
-static int __devinit init_rgb_led(struct pm8xxx_led_data *led)
-{
- int rc;
- u8 val;
-
- rc = pm8xxx_readb(led->dev->parent, SSBI_REG_ADDR_RGB_CNTL1, &val);
- if (rc) {
- dev_err(led->cdev.dev, "can't read rgb ctrl1 register rc=%d\n",
- rc);
- return rc;
- }
-
- switch (led->id) {
- case PM8XXX_ID_RGB_LED_RED:
- val |= PM8XXX_DRV_RGB_RED_LED;
- break;
- case PM8XXX_ID_RGB_LED_GREEN:
- val |= PM8XXX_DRV_RGB_GREEN_LED;
- break;
- case PM8XXX_ID_RGB_LED_BLUE:
- val |= PM8XXX_DRV_RGB_BLUE_LED;
- break;
- default:
- return -EINVAL;
- }
-
- return pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_RGB_CNTL1, val);
-}
-
static int __devinit get_init_value(struct pm8xxx_led_data *led, u8 *val)
{
int rc, offset;
@@ -717,12 +716,6 @@
case PM8XXX_ID_RGB_LED_RED:
case PM8XXX_ID_RGB_LED_GREEN:
case PM8XXX_ID_RGB_LED_BLUE:
- rc = init_rgb_led(led);
- if (rc) {
- dev_err(led->cdev.dev, "can't initialize rgb rc=%d\n",
- rc);
- return rc;
- }
addr = SSBI_REG_ADDR_RGB_CNTL1;
break;
default:
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 9ad79e9..071d209 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -168,6 +168,7 @@
struct dmx_ts_feed {
int is_filtering; /* Set to non-zero when filtering in progress */
struct dmx_demux *parent; /* Back-pointer */
+ const struct dvb_ringbuffer *buffer;
void *priv; /* Pointer to private data of the API client */
int (*set) (struct dmx_ts_feed *feed,
u16 pid,
@@ -184,6 +185,8 @@
struct dmx_buffer_status *dmx_buffer_status);
int (*data_ready_cb)(struct dmx_ts_feed *feed,
dmx_ts_data_ready_cb callback);
+ int (*notify_data_read)(struct dmx_ts_feed *feed,
+ u32 bytes_num);
};
/*--------------------------------------------------------------------------*/
@@ -195,6 +198,7 @@
u8 filter_mask [DMX_MAX_FILTER_SIZE];
u8 filter_mode [DMX_MAX_FILTER_SIZE];
struct dmx_section_feed* parent; /* Back-pointer */
+ const struct dvb_ringbuffer *buffer;
void* priv; /* Pointer to private data of the API client */
};
@@ -227,6 +231,8 @@
int (*stop_filtering) (struct dmx_section_feed* feed);
int (*data_ready_cb)(struct dmx_section_feed *feed,
dmx_section_data_ready_cb callback);
+ int (*notify_data_read)(struct dmx_section_filter *filter,
+ u32 bytes_num);
};
/*--------------------------------------------------------------------------*/
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 433e796..8353f6f 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -60,6 +60,35 @@
return dvb_ringbuffer_write(buf, src, len);
}
+static inline void dvb_dmxdev_notify_data_read(struct dmxdev_filter *filter,
+ int bytes_read)
+{
+ if (!filter)
+ return;
+
+ if (filter->type == DMXDEV_TYPE_SEC) {
+ if (filter->feed.sec->notify_data_read)
+ filter->feed.sec->notify_data_read(
+ filter->filter.sec,
+ bytes_read);
+ } else {
+ struct dmxdev_feed *feed;
+
+ /*
+ * All feeds of same demux-handle share the same output
+ * buffer, it is enough to notify on the buffer status
+ * on one of the feeds
+ */
+ feed = list_first_entry(&filter->feed.ts,
+ struct dmxdev_feed, next);
+
+ if (feed->ts->notify_data_read)
+ feed->ts->notify_data_read(
+ feed->ts,
+ bytes_read);
+ }
+}
+
static inline u32 dvb_dmxdev_advance_event_idx(u32 index)
{
index++;
@@ -460,6 +489,7 @@
}
dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
dvb_dmxdev_flush_events(&dmxdev->dvr_output_events);
+ dmxdev->dvr_feeds_count = 0;
dvbdev->readers--;
} else if (!dvbdev->writers) {
@@ -719,9 +749,22 @@
buf, count, ppos);
if (res > 0) {
+ dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, res);
spin_lock_irq(&dmxdev->lock);
dvb_dmxdev_update_events(&dmxdev->dvr_output_events, res);
spin_unlock_irq(&dmxdev->lock);
+ } else if (res == -EOVERFLOW) {
+ /*
+ * When buffer overflowed, demux-dev flushed the
+ * buffer and marked the buffer in error state.
+ * Data from underlying driver is discarded until
+ * user gets notified that buffer has overflowed.
+ * Now that the user is notified, notify underlying
+ * driver that data was flushed from output buffer.
+ */
+ dvb_dmxdev_notify_data_read(dmxdev->dvr_feed,
+ dmxdev->dvr_flush_data_len);
+ dmxdev->dvr_flush_data_len = 0;
}
return res;
@@ -873,8 +916,20 @@
res = dvb_dmxdev_remove_event(&dmxdev->dvr_output_events, event);
- if (event->type == DMX_EVENT_BUFFER_OVERFLOW)
+ if (event->type == DMX_EVENT_BUFFER_OVERFLOW) {
+ /*
+ * When buffer overflowed, demux-dev flushed the
+ * buffer and marked the buffer in error state.
+ * Data from underlying driver is discarded until
+ * user gets notified that buffer has overflowed.
+ * Now that the user is notified, notify underlying
+ * driver that data was flushed from output buffer.
+ */
+ dvb_dmxdev_notify_data_read(dmxdev->dvr_feed,
+ dmxdev->dvr_flush_data_len);
+ dmxdev->dvr_flush_data_len = 0;
dmxdev->dvr_buffer.error = 0;
+ }
spin_unlock_irq(&dmxdev->lock);
@@ -899,7 +954,23 @@
spin_lock_irq(lock);
dmx_buffer_status->error = buf->error;
- buf->error = 0;
+ if (buf->error) {
+ if (buf->error == -EOVERFLOW) {
+ /*
+ * When buffer overflowed, demux-dev flushed the
+ * buffer and marked the buffer in error state.
+ * Data from underlying driver is discarded until
+ * user gets notified that buffer has overflowed.
+ * Now that the user is notified, notify underlying
+ * driver that data was flushed from output buffer.
+ */
+ dvb_dmxdev_notify_data_read(dmxdev->dvr_feed,
+ dmxdev->dvr_flush_data_len);
+ dmxdev->dvr_flush_data_len = 0;
+ }
+
+ buf->error = 0;
+ }
dmx_buffer_status->fullness = dvb_ringbuffer_avail(buf);
dmx_buffer_status->free_bytes = dvb_ringbuffer_free(buf);
@@ -931,6 +1002,7 @@
DVB_RINGBUFFER_SKIP(&dmxdev->dvr_buffer, bytes_count);
+ dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, bytes_count);
spin_lock_irq(&dmxdev->lock);
dvb_dmxdev_update_events(&dmxdev->dvr_output_events, bytes_count);
spin_unlock_irq(&dmxdev->lock);
@@ -1183,27 +1255,39 @@
struct dmxdev_feed *feed;
int ret;
- /* Ask for status of decoder's buffer from underlying HW */
- list_for_each_entry(feed, &dmxdevfilter->feed.ts,
- next) {
- if (feed->ts->get_decoder_buff_status)
- ret = feed->ts->get_decoder_buff_status(
- feed->ts,
- dmx_buffer_status);
- else
- ret = -ENODEV;
+ /* Only one feed should be in the list in case of decoder */
+ feed = list_first_entry(&dmxdevfilter->feed.ts,
+ struct dmxdev_feed, next);
- /*
- * There should not be more than one ts feed
- * in the list as this is DECODER feed.
- */
- spin_unlock_irq(&dmxdevfilter->dev->lock);
- return ret;
- }
+ /* Ask for status of decoder's buffer from underlying HW */
+ if (feed->ts->get_decoder_buff_status)
+ ret = feed->ts->get_decoder_buff_status(
+ feed->ts,
+ dmx_buffer_status);
+ else
+ ret = -ENODEV;
+
+ spin_unlock_irq(&dmxdevfilter->dev->lock);
+ return ret;
}
dmx_buffer_status->error = buf->error;
- buf->error = 0;
+ if (buf->error) {
+ if (buf->error == -EOVERFLOW) {
+ /*
+ * When buffer overflowed, demux-dev flushed the
+ * buffer and marked the buffer in error state.
+ * Data from underlying driver is discarded until
+ * user gets notified that buffer has overflowed.
+ * Now that the user is notified, notify underlying
+ * driver that data was flushed from output buffer.
+ */
+ dvb_dmxdev_notify_data_read(dmxdevfilter,
+ dmxdevfilter->flush_data_len);
+ dmxdevfilter->flush_data_len = 0;
+ }
+ buf->error = 0;
+ }
dmx_buffer_status->fullness = dvb_ringbuffer_avail(buf);
dmx_buffer_status->free_bytes = dvb_ringbuffer_free(buf);
@@ -1234,6 +1318,7 @@
DVB_RINGBUFFER_SKIP(&dmxdevfilter->buffer, bytes_count);
+ dvb_dmxdev_notify_data_read(dmxdevfilter, bytes_count);
spin_lock_irq(&dmxdevfilter->dev->lock);
dvb_dmxdev_update_events(&dmxdevfilter->events, bytes_count);
spin_unlock_irq(&dmxdevfilter->dev->lock);
@@ -1252,8 +1337,20 @@
res = dvb_dmxdev_remove_event(&dmxdevfilter->events, event);
- if (event->type == DMX_EVENT_BUFFER_OVERFLOW)
+ if (event->type == DMX_EVENT_BUFFER_OVERFLOW) {
+ /*
+ * When buffer overflowed, demux-dev flushed the
+ * buffer and marked the buffer in error state.
+ * Data from underlying driver is discarded until
+ * user gets notified that buffer has overflowed.
+ * Now that the user is notified, notify underlying
+ * driver that data was flushed from output buffer.
+ */
+ dvb_dmxdev_notify_data_read(dmxdevfilter,
+ dmxdevfilter->flush_data_len);
+ dmxdevfilter->flush_data_len = 0;
dmxdevfilter->buffer.error = 0;
+ }
spin_unlock_irq(&dmxdevfilter->dev->lock);
@@ -1334,6 +1431,8 @@
buffer2_len);
if (ret < 0) {
+ dmxdevfilter->flush_data_len =
+ dvb_ringbuffer_avail(&dmxdevfilter->buffer);
dvb_dmxdev_flush_output(&dmxdevfilter->buffer,
&dmxdevfilter->events);
dmxdevfilter->buffer.error = ret;
@@ -1372,6 +1471,7 @@
struct dmxdev_events_queue *events;
struct dmx_filter_event event;
int ret;
+ u32 *flush_data_len;
spin_lock(&dmxdevfilter->dev->lock);
if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
@@ -1383,9 +1483,11 @@
|| dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
buffer = &dmxdevfilter->buffer;
events = &dmxdevfilter->events;
+ flush_data_len = &dmxdevfilter->flush_data_len;
} else {
buffer = &dmxdevfilter->dev->dvr_buffer;
events = &dmxdevfilter->dev->dvr_output_events;
+ flush_data_len = &dmxdevfilter->dev->dvr_flush_data_len;
}
if (buffer->error) {
@@ -1435,6 +1537,8 @@
ret = dvb_dmxdev_buffer_write(buffer, buffer2,
buffer2_len);
if (ret < 0) {
+ *flush_data_len =
+ dvb_ringbuffer_avail(&dmxdevfilter->buffer);
dvb_dmxdev_flush_output(buffer, events);
buffer->error = ret;
@@ -1507,6 +1611,8 @@
if ((DMX_OVERRUN_ERROR == dmx_data_ready->status) ||
(dmx_data_ready->data_length > free)) {
+ dmxdevfilter->flush_data_len =
+ dvb_ringbuffer_avail(&dmxdevfilter->buffer);
dvb_dmxdev_flush_output(&dmxdevfilter->buffer,
&dmxdevfilter->events);
@@ -1548,6 +1654,7 @@
struct dvb_ringbuffer *buffer;
struct dmxdev_events_queue *events;
struct dmx_filter_event event;
+ u32 *flush_data_len;
int free;
spin_lock(&dmxdevfilter->dev->lock);
@@ -1560,9 +1667,11 @@
if (dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) {
buffer = &dmxdevfilter->buffer;
events = &dmxdevfilter->events;
+ flush_data_len = &dmxdevfilter->flush_data_len;
} else {
buffer = &dmxdevfilter->dev->dvr_buffer;
events = &dmxdevfilter->dev->dvr_output_events;
+ flush_data_len = &dmxdevfilter->dev->dvr_flush_data_len;
}
if (dmx_data_ready->status == DMX_OK_PCR) {
@@ -1592,6 +1701,8 @@
if ((DMX_OVERRUN_ERROR == dmx_data_ready->status) ||
(dmx_data_ready->data_length > free)) {
+ *flush_data_len =
+ dvb_ringbuffer_avail(&dmxdevfilter->buffer);
dvb_dmxdev_flush_output(buffer, events);
dprintk("dmxdev: buffer overflow\n");
@@ -1761,6 +1872,12 @@
case DMXDEV_TYPE_PES:
dvb_dmxdev_feed_stop(dmxdevfilter);
demux = dmxdevfilter->dev->demux;
+ if (dmxdevfilter->params.pes.output == DMX_OUT_TS_TAP) {
+ dmxdevfilter->dev->dvr_feeds_count--;
+ if (!dmxdevfilter->dev->dvr_feeds_count)
+ dmxdevfilter->dev->dvr_feed = NULL;
+ }
+
list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) {
demux->release_ts_feed(demux, feed->ts);
feed->ts = NULL;
@@ -1844,6 +1961,15 @@
tsfeed = feed->ts;
tsfeed->priv = filter;
+ if (filter->params.pes.output == DMX_OUT_TS_TAP) {
+ tsfeed->buffer = &dmxdev->dvr_buffer;
+ if (!dmxdev->dvr_feeds_count)
+ dmxdev->dvr_feed = filter;
+ dmxdev->dvr_feeds_count++;
+ } else {
+ tsfeed->buffer = &filter->buffer;
+ }
+
if (tsfeed->data_ready_cb) {
ret = tsfeed->data_ready_cb(tsfeed, dvb_dmxdev_ts_event_cb);
@@ -1979,6 +2105,7 @@
}
(*secfilter)->priv = filter;
+ (*secfilter)->buffer = &filter->buffer;
memcpy(&((*secfilter)->filter_value[3]),
&(para->filter.filter[1]), DMX_FILTER_SIZE - 1);
@@ -2278,9 +2405,22 @@
buf, count, ppos);
if (ret > 0) {
+ dvb_dmxdev_notify_data_read(dmxdevfilter, ret);
spin_lock_irq(&dmxdevfilter->dev->lock);
dvb_dmxdev_update_events(&dmxdevfilter->events, ret);
spin_unlock_irq(&dmxdevfilter->dev->lock);
+ } else if (ret == -EOVERFLOW) {
+ /*
+ * When buffer overflowed, demux-dev flushed the
+ * buffer and marked the buffer in error state.
+ * Data from underlying driver is discarded until
+ * user gets notified that buffer has overflowed.
+ * Now that the user is notified, notify underlying
+ * driver that data was flushed from output buffer.
+ */
+ dvb_dmxdev_notify_data_read(dmxdevfilter->dev->dvr_feed,
+ dmxdevfilter->flush_data_len);
+ dmxdevfilter->flush_data_len = 0;
}
mutex_unlock(&dmxdevfilter->mutex);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 6fa7054..9fd900e 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -113,6 +113,7 @@
enum dmxdev_state state;
struct dmxdev *dev;
struct dvb_ringbuffer buffer;
+ u32 flush_data_len;
struct mutex mutex;
@@ -153,6 +154,9 @@
struct dvb_ringbuffer dvr_buffer;
struct dmxdev_events_queue dvr_output_events;
+ struct dmxdev_filter *dvr_feed;
+ u32 dvr_flush_data_len;
+ int dvr_feeds_count;
struct dvb_ringbuffer dvr_input_buffer;
struct workqueue_struct *dvr_input_workqueue;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 0be6a22..0bdf6cb 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1137,6 +1137,7 @@
(*ts_feed)->set_indexing_params = dmx_ts_set_indexing_params;
(*ts_feed)->get_decoder_buff_status = dmx_ts_feed_decoder_buff_status;
(*ts_feed)->data_ready_cb = dmx_ts_feed_data_ready_cb;
+ (*ts_feed)->notify_data_read = NULL;
if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
feed->state = DMX_STATE_FREE;
@@ -1434,6 +1435,7 @@
(*feed)->stop_filtering = dmx_section_feed_stop_filtering;
(*feed)->release_filter = dmx_section_feed_release_filter;
(*feed)->data_ready_cb = dmx_section_feed_data_ready_cb;
+ (*feed)->notify_data_read = NULL;
mutex_unlock(&dvbdmx->mutex);
return 0;
diff --git a/drivers/media/video/msm/gemini/msm_gemini_sync.c b/drivers/media/video/msm/gemini/msm_gemini_sync.c
index e878329..97bb611 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_sync.c
+++ b/drivers/media/video/msm/gemini/msm_gemini_sync.c
@@ -218,6 +218,7 @@
return -EAGAIN;
}
+ memset(&ctrl_cmd, 0, sizeof(struct msm_gemini_ctrl_cmd));
ctrl_cmd.type = buf_p->vbuf.type;
kfree(buf_p);
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index d9ede7a..29aba08 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -92,6 +92,33 @@
return rc;
}
+static int msm_camera_v4l2_private_g_ctrl(struct file *f, void *pctx,
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+ int rc = -EINVAL;
+ struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+ struct msm_cam_v4l2_dev_inst *pcam_inst;
+ pcam_inst = container_of(f->private_data,
+ struct msm_cam_v4l2_dev_inst, eventHandle);
+
+ WARN_ON(pctx != f->private_data);
+
+ mutex_lock(&pcam->vid_lock);
+ switch (ioctl_ptr->id) {
+ case MSM_V4L2_PID_INST_HANDLE:
+ COPY_TO_USER(rc, (void __user *)ioctl_ptr->ioctl_ptr,
+ (void *)&pcam_inst->inst_handle, sizeof(uint32_t));
+ if (rc)
+ ERR_COPY_TO_USER();
+ break;
+ default:
+ pr_err("%s Unsupported ioctl %d ", __func__, ioctl_ptr->id);
+ break;
+ }
+ mutex_unlock(&pcam->vid_lock);
+ return rc;
+}
+
static int msm_camera_v4l2_g_ctrl(struct file *f, void *pctx,
struct v4l2_control *c)
{
@@ -686,7 +713,9 @@
struct msm_cam_v4l2_dev_inst *pcam_inst;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
- pcam_inst->image_mode = a->parm.capture.extendedmode;
+ pcam_inst->image_mode = (a->parm.capture.extendedmode & 0x7F);
+ SET_IMG_MODE(pcam_inst->inst_handle, pcam_inst->image_mode);
+ SET_VIDEO_INST_IDX(pcam_inst->inst_handle, pcam_inst->my_index);
pcam_inst->pcam->dev_inst_map[pcam_inst->image_mode] = pcam_inst;
pcam_inst->path = msm_vidbuf_get_path(pcam_inst->image_mode);
D("%spath=%d,rc=%d\n", __func__,
@@ -745,6 +774,12 @@
case MSM_CAM_V4L2_IOCTL_PRIVATE_S_CTRL:
rc = msm_camera_v4l2_private_s_ctrl(file, fh, ioctl_ptr);
break;
+ case MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL:
+ rc = msm_camera_v4l2_private_g_ctrl(file, fh, ioctl_ptr);
+ break;
+ default:
+ pr_err("%s Unsupported ioctl cmd %d ", __func__, cmd);
+ break;
}
return rc;
}
@@ -853,7 +888,10 @@
goto msm_cam_server_begin_session_failed;
}
pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
-
+ if (!pmctl) {
+ pr_err("%s mctl ptr is null ", __func__);
+ goto msm_cam_server_begin_session_failed;
+ }
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
pmctl->client = msm_ion_client_create(-1, "camera");
kref_init(&pmctl->refcount);
@@ -876,13 +914,8 @@
}
pmctl->pcam_ptr = pcam;
- rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
+ msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
pcam->pvdev);
- if (rc < 0) {
- pr_err("%s: msm_setup_v4l2_event_queue failed %d",
- __func__, rc);
- goto mctl_event_q_setup_failed;
- }
}
pcam_inst->vbqueue_initialized = 0;
rc = 0;
@@ -905,9 +938,8 @@
return rc;
msm_send_open_server_failed:
- v4l2_fh_del(&pcam_inst->eventHandle);
- v4l2_fh_exit(&pcam_inst->eventHandle);
-mctl_event_q_setup_failed:
+ msm_destroy_v4l2_event_queue(&pcam_inst->eventHandle);
+
if (pmctl->mctl_release)
if (pmctl->mctl_release(pmctl) < 0)
pr_err("%s: mctl_release failed\n", __func__);
@@ -1051,10 +1083,11 @@
D("%s index %d nodeid %d count %d\n", __func__, pcam_inst->my_index,
pcam->vnode_id, pcam->use_count);
pcam->dev_inst[pcam_inst->my_index] = NULL;
- if (pcam_inst->my_index == 0) {
- v4l2_fh_del(&pcam_inst->eventHandle);
- v4l2_fh_exit(&pcam_inst->eventHandle);
- }
+ if (pcam_inst->my_index == 0)
+ msm_destroy_v4l2_event_queue(&pcam_inst->eventHandle);
+
+ CLR_VIDEO_INST_IDX(pcam_inst->inst_handle);
+ CLR_IMG_MODE(pcam_inst->inst_handle);
mutex_unlock(&pcam_inst->inst_lock);
mutex_destroy(&pcam_inst->inst_lock);
kfree(pcam_inst);
@@ -1137,18 +1170,6 @@
return 0;
}
-int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
- struct video_device *pvdev)
-{
- int rc = 0;
- /* v4l2_fh support */
- spin_lock_init(&pvdev->fh_lock);
- INIT_LIST_HEAD(&pvdev->fh_list);
-
- v4l2_fh_init(eventHandle, pvdev);
- v4l2_fh_add(eventHandle);
- return rc;
-}
static struct v4l2_file_operations g_msm_fops = {
.owner = THIS_MODULE,
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 5fc2f68..d77defd 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -122,7 +122,7 @@
struct msm_free_buf {
uint8_t num_planes;
- int32_t image_mode;
+ uint32_t inst_handle;
uint32_t ch_paddr[VIDEO_MAX_PLANES];
uint32_t vb;
};
@@ -323,7 +323,7 @@
enum v4l2_mbus_pixelcode sensor_pxlcode;
struct msm_cam_v4l2_device *pcam;
int my_index;
- int image_mode;
+ uint32_t image_mode;
int path;
int buf_count;
/* buffer offsets, if any */
@@ -335,6 +335,7 @@
struct img_plane_info plane_info;
int vbqueue_initialized;
struct mutex inst_lock;
+ uint32_t inst_handle;
};
struct msm_cam_mctl_node {
@@ -547,6 +548,18 @@
struct msm_cam_server_irqmap_entry hw_irqmap[CAMERA_SS_IRQ_MAX];
};
+enum msm_cam_buf_lookup_type {
+ BUF_LOOKUP_INVALID,
+ BUF_LOOKUP_BY_IMG_MODE,
+ BUF_LOOKUP_BY_INST_HANDLE,
+};
+
+struct msm_cam_buf_handle {
+ uint16_t buf_lookup_type;
+ uint32_t image_mode;
+ uint32_t inst_handle;
+};
+
/* ISP related functions */
void msm_isp_vfe_dev_init(struct v4l2_subdev *vd);
/*
@@ -562,33 +575,34 @@
int msm_mctl_buf_init(struct msm_cam_v4l2_device *pcam);
int msm_mctl_init_user_formats(struct msm_cam_v4l2_device *pcam);
int msm_mctl_buf_done(struct msm_cam_media_controller *pmctl,
- int msg_type, struct msm_free_buf *buf,
- uint32_t frame_id);
+ struct msm_cam_buf_handle *buf_handle,
+ struct msm_free_buf *buf,
+ uint32_t frame_id);
int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
- int msg_type, struct msm_free_buf *frame, int dirty, int node_type);
+ struct msm_cam_buf_handle *buf_handle,
+ struct msm_free_buf *frame, int dirty, int node_type);
int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
- struct msm_cam_v4l2_dev_inst *pcam_inst,
- int path, struct msm_free_buf *free_buf);
+ struct msm_cam_v4l2_dev_inst *pcam_inst,
+ struct msm_cam_buf_handle *buf_handle,
+ struct msm_free_buf *free_buf);
int msm_mctl_release_free_buf(struct msm_cam_media_controller *pmctl,
- struct msm_cam_v4l2_dev_inst *pcam_inst,
- int path, struct msm_free_buf *free_buf);
+ struct msm_cam_v4l2_dev_inst *pcam_inst,
+ struct msm_free_buf *free_buf);
/*Memory(PMEM) functions*/
int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
- struct ion_client *client);
+ struct ion_client *client);
int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg,
- struct ion_client *client);
+ struct ion_client *client);
int msm_pmem_region_get_phy_addr(struct hlist_head *ptype,
struct msm_mem_map_info *mem_map, int32_t *phyaddr);
uint8_t msm_pmem_region_lookup(struct hlist_head *ptype,
int pmem_type, struct msm_pmem_region *reg, uint8_t maxcount);
uint8_t msm_pmem_region_lookup_2(struct hlist_head *ptype,
- int pmem_type,
- struct msm_pmem_region *reg,
- uint8_t maxcount);
+ int pmem_type, struct msm_pmem_region *reg,
+ uint8_t maxcount);
unsigned long msm_pmem_stats_vtop_lookup(
- struct msm_cam_media_controller *mctl,
- unsigned long buffer,
- int fd);
+ struct msm_cam_media_controller *mctl,
+ unsigned long buffer, int fd);
unsigned long msm_pmem_stats_ptov_lookup(
struct msm_cam_media_controller *mctl,
unsigned long addr, int *fd);
@@ -605,33 +619,25 @@
int msm_mctl_is_pp_msg_type(struct msm_cam_media_controller *p_mctl,
int msg_type);
int msm_mctl_do_pp(struct msm_cam_media_controller *p_mctl,
- int msg_type, uint32_t y_phy, uint32_t frame_id);
+ int msg_type, uint32_t y_phy, uint32_t frame_id);
int msm_mctl_pp_ioctl(struct msm_cam_media_controller *p_mctl,
- unsigned int cmd, unsigned long arg);
+ unsigned int cmd, unsigned long arg);
int msm_mctl_pp_notify(struct msm_cam_media_controller *pmctl,
- struct msm_mctl_pp_frame_info *pp_frame_info);
+ struct msm_mctl_pp_frame_info *pp_frame_info);
int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
- int out_type, int node_type);
+ int out_type, int node_type);
struct msm_frame_buffer *msm_mctl_buf_find(
struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst, int del_buf,
- int msg_type, struct msm_free_buf *fbuf);
+ struct msm_free_buf *fbuf);
void msm_mctl_gettimeofday(struct timeval *tv);
-struct msm_frame_buffer *msm_mctl_get_free_buf(
- struct msm_cam_media_controller *pmctl,
- int msg_type);
-int msm_mctl_put_free_buf(
- struct msm_cam_media_controller *pmctl,
- int msg_type, struct msm_frame_buffer *buf);
int msm_mctl_check_pp(struct msm_cam_media_controller *p_mctl,
- int msg_type, int *pp_divert_type, int *pp_type);
+ int msg_type, int *pp_divert_type, int *pp_type);
int msm_mctl_do_pp_divert(
struct msm_cam_media_controller *p_mctl,
- int msg_type, struct msm_free_buf *fbuf,
+ struct msm_cam_buf_handle *buf_handle,
+ struct msm_free_buf *fbuf,
uint32_t frame_id, int pp_type);
-int msm_mctl_buf_del(struct msm_cam_media_controller *pmctl,
- int msg_type,
- struct msm_frame_buffer *my_buf);
int msm_mctl_pp_release_free_frame(
struct msm_cam_media_controller *p_mctl,
void __user *arg);
@@ -639,23 +645,24 @@
struct msm_cam_media_controller *p_mctl,
void __user *arg);
int msm_mctl_set_pp_key(struct msm_cam_media_controller *p_mctl,
- void __user *arg);
+ void __user *arg);
int msm_mctl_pp_done(
struct msm_cam_media_controller *p_mctl,
void __user *arg);
int msm_mctl_pp_divert_done(
struct msm_cam_media_controller *p_mctl,
void __user *arg);
-int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
- struct video_device *pvdev);
+void msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
+ struct video_device *pvdev);
+void msm_destroy_v4l2_event_queue(struct v4l2_fh *eventHandle);
int msm_setup_mctl_node(struct msm_cam_v4l2_device *pcam);
struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
- struct msm_cam_media_controller *pmctl,
- int image_mode);
+ struct msm_cam_media_controller *pmctl,
+ struct msm_cam_buf_handle *buf_handle);
int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
- int image_mode, struct msm_frame_buffer *buf);
+ int image_mode, struct msm_frame_buffer *buf);
int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
- void __user *arg);
+ void __user *arg);
void msm_release_ion_client(struct kref *ref);
int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
struct msm_cam_subdev_info *sd_info);
@@ -668,7 +675,7 @@
int *p_active);
int msm_cam_server_close_mctl_session(struct msm_cam_v4l2_device *pcam);
long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl,
- unsigned int cmd, unsigned long evt);
+ unsigned int cmd, unsigned long evt);
int msm_mctl_pp_get_vpe_buf_info(struct msm_mctl_pp_frame_info *zoom);
void msm_queue_init(struct msm_device_queue *queue, const char *name);
void msm_enqueue(struct msm_device_queue *queue, struct list_head *entry);
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 9e1d9c1..67e7c02 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -168,7 +168,9 @@
struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
struct msm_frame_info *frame_info =
(struct msm_frame_info *)vdata->evt_msg.data;
- uint32_t vfe_id, image_mode;
+ uint32_t vfe_id;
+ struct msm_cam_buf_handle buf_handle;
+
if (!pcam) {
pr_debug("%s pcam is null. return\n", __func__);
msm_isp_sync_free(vdata);
@@ -176,10 +178,13 @@
}
if (frame_info) {
vfe_id = frame_info->path;
- image_mode = frame_info->image_mode;
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+ buf_handle.inst_handle = frame_info->inst_handle;
} else {
vfe_id = vdata->evt_msg.msg_id;
- image_mode = msm_isp_vfe_msg_to_img_mode(pmctl, vfe_id);
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
+ buf_handle.image_mode =
+ msm_isp_vfe_msg_to_img_mode(pmctl, vfe_id);
}
switch (vdata->type) {
@@ -189,14 +194,14 @@
D("%s Got V32_START_*: Getting ping addr id = %d",
__func__, vfe_id);
msm_mctl_reserve_free_buf(pmctl, NULL,
- image_mode, &free_buf);
+ &buf_handle, &free_buf);
cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
cfgcmd.value = &vfe_id;
vfe_params.vfe_cfg = &cfgcmd;
vfe_params.data = (void *)&free_buf;
rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
msm_mctl_reserve_free_buf(pmctl, NULL,
- image_mode, &free_buf);
+ &buf_handle, &free_buf);
cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
cfgcmd.value = &vfe_id;
vfe_params.vfe_cfg = &cfgcmd;
@@ -208,7 +213,7 @@
pr_debug("%s Got V32_CAPTURE: getting buffer for id = %d",
__func__, vfe_id);
msm_mctl_reserve_free_buf(pmctl, NULL,
- image_mode, &free_buf);
+ &buf_handle, &free_buf);
cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
cfgcmd.value = &vfe_id;
vfe_params.vfe_cfg = &cfgcmd;
@@ -216,7 +221,7 @@
rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
temp_free_buf = free_buf;
if (msm_mctl_reserve_free_buf(pmctl, NULL,
- image_mode, &free_buf)) {
+ &buf_handle, &free_buf)) {
/* Write the same buffer into PONG */
free_buf = temp_free_buf;
}
@@ -254,7 +259,7 @@
D("%s Got OUTPUT_IRQ: Getting free buf id = %d",
__func__, vfe_id);
msm_mctl_reserve_free_buf(pmctl, NULL,
- image_mode, &free_buf);
+ &buf_handle, &free_buf);
cfgcmd.cmd_type = CMD_CONFIG_FREE_BUF_ADDR;
cfgcmd.value = &vfe_id;
vfe_params.vfe_cfg = &cfgcmd;
@@ -320,10 +325,10 @@
}
case NOTIFY_VFE_MSG_OUT: {
uint8_t msgid;
- int32_t image_mode = -1;
+ struct msm_cam_buf_handle buf_handle;
struct isp_msg_output *isp_output =
(struct isp_msg_output *)arg;
- if (isp_output->buf.image_mode < 0) {
+ if (!isp_output->buf.inst_handle) {
switch (isp_output->output_id) {
case MSG_ID_OUTPUT_P:
msgid = VFE_MSG_OUTPUT_P;
@@ -356,19 +361,22 @@
rc = -EINVAL;
break;
}
- if (!rc)
- image_mode =
+ if (!rc) {
+ buf_handle.buf_lookup_type =
+ BUF_LOOKUP_BY_IMG_MODE;
+ buf_handle.image_mode =
msm_isp_vfe_msg_to_img_mode(pmctl, msgid);
+ }
} else {
- image_mode = isp_output->buf.image_mode;
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+ buf_handle.inst_handle = isp_output->buf.inst_handle;
}
isp_event->isp_data.isp_msg.msg_id =
isp_output->output_id;
isp_event->isp_data.isp_msg.frame_id =
isp_output->frameCounter;
buf = isp_output->buf;
- BUG_ON(image_mode < 0);
- msm_mctl_buf_done(pmctl, image_mode,
+ msm_mctl_buf_done(pmctl, &buf_handle,
&buf, isp_output->frameCounter);
}
break;
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 0a61b69..fd5591c 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -437,7 +437,7 @@
/* open sub devices - once only*/
if (!p_mctl->opencnt) {
struct msm_sensor_csi_info csi_info;
- uint32_t csid_version;
+ uint32_t csid_version = 0;
wake_lock(&p_mctl->wake_lock);
csid_core = camdev->csid_core;
@@ -792,12 +792,9 @@
}
D("%s active %d\n", __func__, pcam->mctl_node.active);
- rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
- pcam->mctl_node.pvdev);
- if (rc < 0) {
- mutex_unlock(&pcam->mctl_node.dev_lock);
- return rc;
- }
+ msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
+ pcam->mctl_node.pvdev);
+
pcam_inst->vbqueue_initialized = 0;
kref_get(&pmctl->refcount);
f->private_data = &pcam_inst->eventHandle;
@@ -880,8 +877,10 @@
vb2_queue_release(&pcam_inst->vid_bufq);
D("%s Closing down instance %p ", __func__, pcam_inst);
pcam->mctl_node.dev_inst[pcam_inst->my_index] = NULL;
- v4l2_fh_del(&pcam_inst->eventHandle);
- v4l2_fh_exit(&pcam_inst->eventHandle);
+ msm_destroy_v4l2_event_queue(&pcam_inst->eventHandle);
+ CLR_MCTLPP_INST_IDX(pcam_inst->inst_handle);
+ CLR_IMG_MODE(pcam_inst->inst_handle);
+
mutex_destroy(&pcam_inst->inst_lock);
kfree(pcam_inst);
@@ -1328,6 +1327,10 @@
WARN_ON(pctx != f->private_data);
pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
+ if (!pmctl) {
+ pr_err("%s mctl ptr is null ", __func__);
+ return -EINVAL;
+ }
if (!pcam_inst->vbqueue_initialized) {
pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
V4L2_BUF_TYPE_VIDEO_CAPTURE);
@@ -1352,6 +1355,10 @@
WARN_ON(pctx != f->private_data);
pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
+ if (!pmctl) {
+ pr_err("%s mctl ptr is null ", __func__);
+ return -EINVAL;
+ }
if (!pcam_inst->vbqueue_initialized) {
pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
@@ -1454,7 +1461,9 @@
struct msm_cam_v4l2_dev_inst *pcam_inst;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
- pcam_inst->image_mode = a->parm.capture.extendedmode;
+ pcam_inst->image_mode = (a->parm.capture.extendedmode & 0x7F);
+ SET_IMG_MODE(pcam_inst->inst_handle, pcam_inst->image_mode);
+ SET_MCTLPP_INST_IDX(pcam_inst->inst_handle, pcam_inst->my_index);
pcam_inst->pcam->mctl_node.dev_inst_map[pcam_inst->image_mode] =
pcam_inst;
pcam_inst->path = msm_mctl_vidbuf_get_path(pcam_inst->image_mode);
@@ -1499,6 +1508,51 @@
return rc;
}
+static int msm_mctl_v4l2_private_g_ctrl(struct file *f, void *pctx,
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+ int rc = -EINVAL;
+ struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+ struct msm_cam_v4l2_dev_inst *pcam_inst;
+ pcam_inst = container_of(f->private_data,
+ struct msm_cam_v4l2_dev_inst, eventHandle);
+
+ WARN_ON(pctx != f->private_data);
+
+ mutex_lock(&pcam->mctl_node.dev_lock);
+ switch (ioctl_ptr->id) {
+ case MSM_V4L2_PID_INST_HANDLE:
+ COPY_TO_USER(rc, (void __user *)ioctl_ptr->ioctl_ptr,
+ (void *)&pcam_inst->inst_handle, sizeof(uint32_t));
+ if (rc)
+ ERR_COPY_TO_USER();
+ break;
+ default:
+ pr_err("%s Unsupported ioctl %d ", __func__, ioctl_ptr->id);
+ break;
+ }
+ mutex_unlock(&pcam->mctl_node.dev_lock);
+ return rc;
+}
+
+static long msm_mctl_v4l2_private_ioctl(struct file *file, void *fh,
+ bool valid_prio, int cmd, void *arg)
+{
+ int rc = -EINVAL;
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+ D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
+
+ switch (cmd) {
+ case MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL:
+ rc = msm_mctl_v4l2_private_g_ctrl(file, fh, ioctl_ptr);
+ break;
+ default:
+ pr_err("%s Unsupported ioctl cmd %d ", __func__, cmd);
+ break;
+ }
+ return rc;
+}
+
/* mctl node v4l2_ioctl_ops */
static const struct v4l2_ioctl_ops g_msm_mctl_ioctl_ops = {
.vidioc_querycap = msm_mctl_v4l2_querycap,
@@ -1538,6 +1592,7 @@
/* event subscribe/unsubscribe */
.vidioc_subscribe_event = msm_mctl_v4l2_subscribe_event,
.vidioc_unsubscribe_event = msm_mctl_v4l2_unsubscribe_event,
+ .vidioc_default = msm_mctl_v4l2_private_ioctl,
};
int msm_setup_mctl_node(struct msm_cam_v4l2_device *pcam)
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index cd86a80..befd213 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -368,7 +368,7 @@
struct msm_frame_buffer *msm_mctl_buf_find(
struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst, int del_buf,
- int image_mode, struct msm_free_buf *fbuf)
+ struct msm_free_buf *fbuf)
{
struct msm_frame_buffer *buf = NULL, *tmp;
uint32_t buf_phyaddr = 0;
@@ -409,14 +409,13 @@
int msm_mctl_buf_done_proc(
struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst,
- int image_mode, struct msm_free_buf *fbuf,
+ struct msm_free_buf *fbuf,
uint32_t *frame_id, int gen_timestamp)
{
struct msm_frame_buffer *buf = NULL;
int del_buf = 1;
- buf = msm_mctl_buf_find(pmctl, pcam_inst, del_buf,
- image_mode, fbuf);
+ buf = msm_mctl_buf_find(pmctl, pcam_inst, del_buf, fbuf);
if (!buf) {
pr_err("%s: buf=0x%x not found\n",
__func__, fbuf->ch_paddr[0]);
@@ -434,48 +433,81 @@
int msm_mctl_buf_done(struct msm_cam_media_controller *p_mctl,
- int image_mode, struct msm_free_buf *fbuf,
- uint32_t frame_id)
+ struct msm_cam_buf_handle *buf_handle,
+ struct msm_free_buf *fbuf,
+ uint32_t frame_id)
{
struct msm_cam_v4l2_dev_inst *pcam_inst;
int idx, rc;
int pp_divert_type = 0, pp_type = 0;
+ uint32_t image_mode;
+
+ if (!p_mctl || !buf_handle || !fbuf) {
+ pr_err("%s Invalid argument. ", __func__);
+ return -EINVAL;
+ }
+ if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE)
+ image_mode = buf_handle->image_mode;
+ else
+ image_mode = GET_IMG_MODE(buf_handle->inst_handle);
+
+ if (image_mode > MSM_V4L2_EXT_CAPTURE_MODE_MAX) {
+ pr_err("%s Invalid image mode %d ", __func__, image_mode);
+ return -EINVAL;
+ }
msm_mctl_check_pp(p_mctl, image_mode, &pp_divert_type, &pp_type);
D("%s: pp_type=%d, pp_divert_type = %d, frame_id = 0x%x image_mode %d",
__func__, pp_type, pp_divert_type, frame_id, image_mode);
- if (pp_type || pp_divert_type)
- rc = msm_mctl_do_pp_divert(p_mctl,
- image_mode, fbuf, frame_id, pp_type);
- else {
- idx = msm_mctl_img_mode_to_inst_index(
- p_mctl, image_mode, 0);
- if (idx < 0) {
- /* check mctl node */
- if ((image_mode >= 0) &&
- p_mctl->pcam_ptr->mctl_node.
- dev_inst_map[image_mode]) {
- int index = p_mctl->pcam_ptr->mctl_node.
- dev_inst_map[image_mode]->my_index;
- pcam_inst = p_mctl->pcam_ptr->mctl_node.
- dev_inst[index];
- D("%s: Mctl node index %d inst %p",
- __func__, index, pcam_inst);
- rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
- image_mode, fbuf,
- &frame_id, 1);
- D("%s mctl node buf done %d\n", __func__, 0);
- return rc;
+ if (pp_type || pp_divert_type) {
+ rc = msm_mctl_do_pp_divert(p_mctl, buf_handle,
+ fbuf, frame_id, pp_type);
+ } else {
+ /* Find the instance on which vb2_buffer_done() needs to be
+ * called, so that the user can get the buffer.
+ * If the lookup type is
+ * - By instance handle:
+ * Either mctl_pp inst idx or video inst idx should be set.
+ * Try to get the MCTL_PP inst idx first, if its not set,
+ * fall back to video inst idx. Once we get the inst idx,
+ * get the pcam_inst from the corresponding dev_inst[] map.
+ * If neither are set, its a serious error, trigger a BUG_ON.
+ * - By image mode:
+ * Legacy usecase. Use the image mode and get the pcam_inst
+ * from the video node.
+ */
+ if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_INST_HANDLE) {
+ idx = GET_MCTLPP_INST_IDX(buf_handle->inst_handle);
+ if (idx > MSM_DEV_INST_MAX) {
+ idx = GET_VIDEO_INST_IDX(
+ buf_handle->inst_handle);
+ BUG_ON(idx > MSM_DEV_INST_MAX);
+ pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
} else {
- pr_err("%s Invalid instance, dropping buffer\n",
- __func__);
- return idx;
+ pcam_inst = p_mctl->pcam_ptr->mctl_node.
+ dev_inst[idx];
}
+ } else if (buf_handle->buf_lookup_type ==
+ BUF_LOOKUP_BY_IMG_MODE) {
+ idx = msm_mctl_img_mode_to_inst_index(p_mctl,
+ buf_handle->image_mode, 0);
+ if (idx < 0) {
+ pr_err("%s Invalid idx %d ", __func__, idx);
+ return -EINVAL;
+ }
+ pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
+ } else {
+ pr_err("%s Invalid buffer lookup type %d", __func__,
+ buf_handle->buf_lookup_type);
+ return -EINVAL;
}
- pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
+ if (!pcam_inst) {
+ pr_err("%s Invalid instance, Dropping buffer. ",
+ __func__);
+ return -EINVAL;
+ }
rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
- image_mode, fbuf,
- &frame_id, 1);
+ fbuf, &frame_id, 1);
}
return rc;
}
@@ -508,58 +540,99 @@
return ret;
}
-struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
- struct msm_cam_media_controller *pmctl,
- int image_mode)
+struct msm_cam_v4l2_dev_inst *msm_mctl_get_inst_by_img_mode(
+ struct msm_cam_media_controller *pmctl, uint32_t img_mode)
{
struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
int idx;
- if (image_mode >= 0) {
- /* Valid image mode. Search the mctl node first.
- * If mctl node doesnt have the instance, then
- * search in the user's video node */
- if (pmctl->vfe_output_mode == VFE_OUTPUTS_MAIN_AND_THUMB
+ /* Valid image mode. Search the mctl node first.
+ * If mctl node doesnt have the instance, then
+ * search in the user's video node */
+ if (pmctl->vfe_output_mode == VFE_OUTPUTS_MAIN_AND_THUMB
|| pmctl->vfe_output_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
- if (pcam->mctl_node.dev_inst_map[image_mode]
- && is_buffer_queued(pcam, image_mode)) {
- idx =
- pcam->mctl_node.dev_inst_map[image_mode]
- ->my_index;
- pcam_inst = pcam->mctl_node.dev_inst[idx];
- D("%s Found instance %p in mctl node device\n",
- __func__, pcam_inst);
- } else if (pcam->dev_inst_map[image_mode]) {
- idx = pcam->dev_inst_map[image_mode]->my_index;
- pcam_inst = pcam->dev_inst[idx];
- D("%s Found instance %p in video device\n",
+ if (pcam->mctl_node.dev_inst_map[img_mode]
+ && is_buffer_queued(pcam, img_mode)) {
+ idx = pcam->mctl_node.dev_inst_map[img_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ D("%s Found instance %p in mctl node device\n",
__func__, pcam_inst);
- }
- } else {
- if (pcam->mctl_node.dev_inst_map[image_mode]) {
- idx = pcam->mctl_node.dev_inst_map[image_mode]
- ->my_index;
- pcam_inst = pcam->mctl_node.dev_inst[idx];
- D("%s Found instance %p in mctl node device\n",
+ } else if (pcam->dev_inst_map[img_mode]) {
+ idx = pcam->dev_inst_map[img_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ D("%s Found instance %p in video device\n",
__func__, pcam_inst);
- } else if (pcam->dev_inst_map[image_mode]) {
- idx = pcam->dev_inst_map[image_mode]->my_index;
- pcam_inst = pcam->dev_inst[idx];
- D("%s Found instance %p in video device\n",
- __func__, pcam_inst);
- }
}
- } else
- pr_err("%s Invalid image mode %d. Return NULL\n",
- __func__, image_mode);
+ } else {
+ if (pcam->mctl_node.dev_inst_map[img_mode]) {
+ idx = pcam->mctl_node.dev_inst_map[img_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ D("%s Found instance %p in mctl node device\n",
+ __func__, pcam_inst);
+ } else if (pcam->dev_inst_map[img_mode]) {
+ idx = pcam->dev_inst_map[img_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ D("%s Found instance %p in video device\n",
+ __func__, pcam_inst);
+ }
+ }
+ return pcam_inst;
+}
+
+struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
+ struct msm_cam_media_controller *pmctl,
+ struct msm_cam_buf_handle *buf_handle)
+{
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+ struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
+ int idx;
+
+ /* Get the pcam instance on based on the following rules:
+ * If the lookup type is
+ * - By instance handle:
+ * Either mctl_pp inst idx or video inst idx should be set.
+ * Try to get the MCTL_PP inst idx first, if its not set,
+ * fall back to video inst idx. Once we get the inst idx,
+ * get the pcam_inst from the corresponding dev_inst[] map.
+ * If neither are set, its a serious error, trigger a BUG_ON.
+ * - By image mode:(Legacy usecase)
+ * If vfe is in configured in snapshot mode, first check if
+ * mctl pp node has a instance created for this image mode
+ * and if there is a buffer queued for that instance.
+ * If so, return that instance, otherwise get the pcam instance
+ * for this image_mode from the video instance.
+ * If the vfe is configured in any other mode, then first check
+ * if mctl pp node has a instance created for this image mode,
+ * otherwise get the pcam instance for this image mode from the
+ * video instance.
+ */
+ if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_INST_HANDLE) {
+ idx = GET_MCTLPP_INST_IDX(buf_handle->inst_handle);
+ if (idx > MSM_DEV_INST_MAX) {
+ idx = GET_VIDEO_INST_IDX(buf_handle->inst_handle);
+ BUG_ON(idx > MSM_DEV_INST_MAX);
+ pcam_inst = pcam->dev_inst[idx];
+ } else {
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ }
+ } else if ((buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE)
+ && (buf_handle->image_mode >= 0 &&
+ buf_handle->image_mode < MSM_V4L2_EXT_CAPTURE_MODE_MAX)) {
+ pcam_inst = msm_mctl_get_inst_by_img_mode(pmctl,
+ buf_handle->image_mode);
+ } else {
+ pr_err("%s Invalid buffer lookup type %d", __func__,
+ buf_handle->buf_lookup_type);
+ }
return pcam_inst;
}
int msm_mctl_reserve_free_buf(
- struct msm_cam_media_controller *pmctl,
- struct msm_cam_v4l2_dev_inst *pref_pcam_inst,
- int image_mode, struct msm_free_buf *free_buf)
+ struct msm_cam_media_controller *pmctl,
+ struct msm_cam_v4l2_dev_inst *pref_pcam_inst,
+ struct msm_cam_buf_handle *buf_handle,
+ struct msm_free_buf *free_buf)
{
struct msm_cam_v4l2_dev_inst *pcam_inst = pref_pcam_inst;
unsigned long flags = 0;
@@ -568,8 +641,8 @@
int rc = -EINVAL, i;
uint32_t buf_idx, plane_offset = 0;
- if (!free_buf || !pmctl) {
- pr_err("%s: free_buf/pmctl is null\n", __func__);
+ if (!free_buf || !pmctl || !buf_handle) {
+ pr_err("%s: Invalid argument passed\n", __func__);
return rc;
}
memset(free_buf, 0, sizeof(struct msm_free_buf));
@@ -579,7 +652,7 @@
* If the preferred camera instance is NULL, get the
* camera instance using the image mode passed */
if (!pcam_inst)
- pcam_inst = msm_mctl_get_pcam_inst(pmctl, image_mode);
+ pcam_inst = msm_mctl_get_pcam_inst(pmctl, buf_handle);
if (!pcam_inst || !pcam_inst->streamon) {
pr_err("%s: stream is turned off\n", __func__);
@@ -641,7 +714,7 @@
int msm_mctl_release_free_buf(struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst,
- int image_mode, struct msm_free_buf *free_buf)
+ struct msm_free_buf *free_buf)
{
unsigned long flags = 0;
struct msm_frame_buffer *buf = NULL;
@@ -677,20 +750,39 @@
}
int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
- int image_mode, struct msm_free_buf *frame, int dirty, int node_type)
+ struct msm_cam_buf_handle *buf_handle,
+ struct msm_free_buf *frame, int dirty, int node_type)
{
- struct msm_cam_v4l2_dev_inst *pcam_inst;
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
int rc = 0, idx;
- idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode, node_type);
- if (idx < 0) {
- pr_err("%s Invalid instance, buffer not released\n", __func__);
- return idx;
+ if (!pmctl || !buf_handle) {
+ pr_err("%s Invalid argument ", __func__);
+ return -EINVAL;
}
- if (node_type)
- pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
- else
- pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
+
+ if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_INST_HANDLE) {
+ idx = GET_MCTLPP_INST_IDX(buf_handle->inst_handle);
+ if (idx > MSM_DEV_INST_MAX) {
+ idx = GET_VIDEO_INST_IDX(buf_handle->inst_handle);
+ BUG_ON(idx > MSM_DEV_INST_MAX);
+ pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
+ } else {
+ pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
+ }
+ } else if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE) {
+ idx = msm_mctl_img_mode_to_inst_index(pmctl,
+ buf_handle->image_mode, node_type);
+ if (idx < 0) {
+ pr_err("%s Invalid instance, buffer not released\n",
+ __func__);
+ return idx;
+ }
+ if (node_type)
+ pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
+ else
+ pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
+ }
if (!pcam_inst) {
pr_err("%s Invalid instance, cannot send buf to user",
__func__);
@@ -701,121 +793,12 @@
__func__, pcam_inst, frame->ch_paddr[0], dirty);
if (dirty)
/* the frame is dirty, not going to disptach to app */
- rc = msm_mctl_release_free_buf(pmctl, pcam_inst,
- image_mode, frame);
+ rc = msm_mctl_release_free_buf(pmctl, pcam_inst, frame);
else
- rc = msm_mctl_buf_done_proc(pmctl, pcam_inst,
- image_mode, frame, NULL, 0);
+ rc = msm_mctl_buf_done_proc(pmctl, pcam_inst, frame, NULL, 0);
return rc;
}
-struct msm_frame_buffer *msm_mctl_get_free_buf(
- struct msm_cam_media_controller *pmctl,
- int image_mode)
-{
- struct msm_cam_v4l2_dev_inst *pcam_inst;
- unsigned long flags = 0;
- struct msm_frame_buffer *buf = NULL;
- int rc = -EINVAL, idx;
-
- idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode, 0);
- if (idx < 0) {
- pr_err("%s Invalid instance, cant get buffer\n", __func__);
- return NULL;
- }
- pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
- if (!pcam_inst->streamon) {
- D("%s: stream 0x%p is off\n", __func__, pcam_inst);
- return NULL;
- }
- spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
- if (!list_empty(&pcam_inst->free_vq)) {
- list_for_each_entry(buf, &pcam_inst->free_vq, list) {
- if (buf->state == MSM_BUFFER_STATE_QUEUED) {
- buf->state = MSM_BUFFER_STATE_RESERVED;
- rc = 0;
- break;
- }
- }
- }
- if (rc != 0) {
- D("%s:No free buffer available: inst = 0x%p ",
- __func__, pcam_inst);
- buf = NULL;
- }
- spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
- return buf;
-}
-
-int msm_mctl_put_free_buf(
- struct msm_cam_media_controller *pmctl,
- int image_mode, struct msm_frame_buffer *my_buf)
-{
- struct msm_cam_v4l2_dev_inst *pcam_inst;
- unsigned long flags = 0;
- int rc = 0, idx;
- struct msm_frame_buffer *buf = NULL;
-
- idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode, 0);
- if (idx < 0) {
- pr_err("%s Invalid instance, cant put buffer\n", __func__);
- return idx;
- }
- pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
- if (!pcam_inst->streamon) {
- D("%s: stream 0x%p is off\n", __func__, pcam_inst);
- return rc;
- }
- spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
- if (!list_empty(&pcam_inst->free_vq)) {
- list_for_each_entry(buf, &pcam_inst->free_vq, list) {
- if (my_buf == buf) {
- buf->state = MSM_BUFFER_STATE_QUEUED;
- spin_unlock_irqrestore(&pcam_inst->vq_irqlock,
- flags);
- return 0;
- }
- }
- }
- spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
- return rc;
-}
-
-int msm_mctl_buf_del(struct msm_cam_media_controller *pmctl,
- int image_mode,
- struct msm_frame_buffer *my_buf)
-{
- struct msm_cam_v4l2_dev_inst *pcam_inst;
- struct msm_frame_buffer *buf = NULL;
- unsigned long flags = 0;
- int idx;
-
- idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode, 0);
- if (idx < 0) {
- pr_err("%s Invalid instance, cant delete buffer\n", __func__);
- return idx;
- }
- pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
- D("%s: idx = %d, pinst=0x%p", __func__, idx, pcam_inst);
- spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
- if (!list_empty(&pcam_inst->free_vq)) {
- list_for_each_entry(buf, &pcam_inst->free_vq, list) {
- if (my_buf == buf) {
- list_del_init(&buf->list);
- spin_unlock_irqrestore(&pcam_inst->vq_irqlock,
- flags);
- return 0;
- }
- }
- }
- spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
- pr_err("%s: buf 0x%p not found", __func__, my_buf);
- return -EINVAL;
-}
-
int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
int image_mode, struct msm_frame_buffer *rbuf)
{
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index abcee4b..dcb7c51 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -153,61 +153,96 @@
spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
return 0;
}
+
static struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst_for_divert(
- struct msm_cam_media_controller *pmctl,
- int image_mode, struct msm_free_buf *fbuf, int *node_type)
+ struct msm_cam_media_controller *pmctl,
+ struct msm_cam_buf_handle *buf_handle,
+ struct msm_free_buf *fbuf, int *node_type)
{
struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
int idx;
+ uint32_t img_mode;
- if (image_mode >= 0) {
- /* Valid image mode. Search the mctl node first.
- * If mctl node doesnt have the instance, then
- * search in the user's video node */
- if (pcam->mctl_node.dev_inst_map[image_mode]
- && is_buf_in_queue(pcam, fbuf, image_mode)) {
- idx =
- pcam->mctl_node.dev_inst_map[image_mode]->my_index;
- pcam_inst = pcam->mctl_node.dev_inst[idx];
- *node_type = MCTL_NODE;
- D("%s Found instance %p in mctl node device\n",
- __func__, pcam_inst);
- } else if (pcam->dev_inst_map[image_mode]) {
- idx = pcam->dev_inst_map[image_mode]->my_index;
+ if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_INST_HANDLE) {
+ idx = GET_MCTLPP_INST_IDX(buf_handle->inst_handle);
+ if (idx > MSM_DEV_INST_MAX) {
+ idx = GET_VIDEO_INST_IDX(buf_handle->inst_handle);
+ BUG_ON(idx > MSM_DEV_INST_MAX);
pcam_inst = pcam->dev_inst[idx];
*node_type = VIDEO_NODE;
- D("%s Found instance %p in video device",
- __func__, pcam_inst);
- } else
+ } else {
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ *node_type = MCTL_NODE;
+ }
+ } else if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE) {
+ img_mode = buf_handle->image_mode;
+ if (img_mode >= 0 && img_mode < MSM_V4L2_EXT_CAPTURE_MODE_MAX) {
+ /* Valid image mode. Search the mctl node first.
+ * If mctl node doesnt have the instance, then
+ * search in the user's video node */
+ if (pcam->mctl_node.dev_inst_map[img_mode]
+ && is_buf_in_queue(pcam, fbuf, img_mode)) {
+ idx = pcam->mctl_node.
+ dev_inst_map[img_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ *node_type = MCTL_NODE;
+ D("%s Found instance %p in mctl node device\n",
+ __func__, pcam_inst);
+ } else if (pcam->dev_inst_map[img_mode]) {
+ idx = pcam->dev_inst_map[img_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ *node_type = VIDEO_NODE;
+ D("%s Found instance %p in video device",
+ __func__, pcam_inst);
+ } else {
+ pr_err("%s Cannot find instance for %d.\n",
+ __func__, img_mode);
+ }
+ } else {
pr_err("%s Invalid image mode %d. Return NULL\n",
- __func__, image_mode);
+ __func__, buf_handle->image_mode);
+ }
+ } else {
+ pr_err("%s Invalid buffer lookup type ", __func__);
}
- return pcam_inst;
+ return pcam_inst;
}
int msm_mctl_do_pp_divert(
struct msm_cam_media_controller *p_mctl,
- int image_mode, struct msm_free_buf *fbuf,
+ struct msm_cam_buf_handle *buf_handle,
+ struct msm_free_buf *fbuf,
uint32_t frame_id, int pp_type)
{
struct msm_cam_v4l2_dev_inst *pcam_inst;
- int rc = 0, i, buf_idx;
+ int rc = 0, i, buf_idx, node;
int del_buf = 0; /* delete from free queue */
struct msm_cam_evt_divert_frame div;
struct msm_frame_buffer *vb = NULL;
struct videobuf2_contig_pmem *mem;
- int node;
+ uint32_t image_mode;
- pcam_inst = msm_mctl_get_pcam_inst_for_divert
- (p_mctl, image_mode, fbuf, &node);
+ if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE) {
+ image_mode = buf_handle->image_mode;
+ div.frame.inst_handle = 0;
+ } else if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_INST_HANDLE) {
+ image_mode = GET_IMG_MODE(buf_handle->inst_handle);
+ div.frame.inst_handle = buf_handle->inst_handle;
+ } else {
+ pr_err("%s Invalid buffer lookup type %d ", __func__,
+ buf_handle->buf_lookup_type);
+ return -EINVAL;
+ }
+
+ pcam_inst = msm_mctl_get_pcam_inst_for_divert(p_mctl,
+ buf_handle, fbuf, &node);
if (!pcam_inst) {
pr_err("%s Invalid instance. Cannot divert frame.\n",
__func__);
return -EINVAL;
}
- vb = msm_mctl_buf_find(p_mctl, pcam_inst,
- del_buf, image_mode, fbuf);
+ vb = msm_mctl_buf_find(p_mctl, pcam_inst, del_buf, fbuf);
if (!vb)
return -EINVAL;
@@ -392,50 +427,16 @@
struct msm_mctl_pp_cmd *pp_cmd)
{
int rc = 0;
- struct msm_mctl_pp_frame_buffer pp_buffer;
- struct msm_frame_buffer *buf = NULL;
- void __user *argp = (void __user *)pp_cmd->value;
- int img_mode;
unsigned long flags;
switch (pp_cmd->id) {
- case MCTL_CMD_GET_FRAME_BUFFER: {
- if (copy_from_user(&pp_buffer, pp_cmd->value,
- sizeof(pp_buffer)))
- return -EFAULT;
- img_mode = msm_mctl_pp_path_to_img_mode(pp_buffer.path);
- if (img_mode < 0) {
- pr_err("%s Invalid image mode\n", __func__);
- return img_mode;
- }
- buf = msm_mctl_get_free_buf(p_mctl, img_mode);
- pp_buffer.buf_handle = (uint32_t)buf;
- if (copy_to_user((void *)argp,
- &pp_buffer,
- sizeof(struct msm_mctl_pp_frame_buffer))) {
- ERR_COPY_TO_USER();
- rc = -EFAULT;
- }
- break;
- }
- case MCTL_CMD_PUT_FRAME_BUFFER: {
- if (copy_from_user(&pp_buffer, pp_cmd->value,
- sizeof(pp_buffer)))
- return -EFAULT;
- img_mode = msm_mctl_pp_path_to_img_mode(pp_buffer.path);
- if (img_mode < 0) {
- pr_err("%s Invalid image mode\n", __func__);
- return img_mode;
- }
- buf = (struct msm_frame_buffer *)pp_buffer.buf_handle;
- msm_mctl_put_free_buf(p_mctl, img_mode, buf);
- break;
- }
case MCTL_CMD_DIVERT_FRAME_PP_PATH: {
struct msm_mctl_pp_divert_pp divert_pp;
if (copy_from_user(&divert_pp, pp_cmd->value,
- sizeof(divert_pp)))
+ sizeof(divert_pp))) {
+ ERR_COPY_FROM_USER();
return -EFAULT;
+ }
D("%s: PP_PATH, path=%d",
__func__, divert_pp.path);
spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
@@ -490,17 +491,20 @@
struct msm_cam_media_controller *p_mctl,
void __user *arg)
{
- struct msm_cam_evt_divert_frame frame;
+ struct msm_cam_evt_divert_frame div_frame;
int image_mode, rc = 0;
struct msm_free_buf free_buf;
struct msm_cam_v4l2_dev_inst *pcam_inst;
+ struct msm_cam_buf_handle buf_handle;
memset(&free_buf, 0, sizeof(struct msm_free_buf));
- if (copy_from_user(&frame, arg,
- sizeof(struct msm_cam_evt_divert_frame)))
+ if (copy_from_user(&div_frame, arg,
+ sizeof(struct msm_cam_evt_divert_frame))) {
+ ERR_COPY_FROM_USER();
return -EFAULT;
+ }
- image_mode = frame.image_mode;
+ image_mode = div_frame.image_mode;
if (image_mode <= 0) {
pr_err("%s Invalid image mode %d", __func__, image_mode);
return -EINVAL;
@@ -511,17 +515,25 @@
pr_err("%s Instance already closed ", __func__);
return -EINVAL;
}
+ if (div_frame.frame.inst_handle) {
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+ buf_handle.inst_handle = div_frame.frame.inst_handle;
+ } else {
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
+ buf_handle.image_mode = image_mode;
+ }
rc = msm_mctl_reserve_free_buf(p_mctl, pcam_inst,
- image_mode, &free_buf);
+ &buf_handle, &free_buf);
if (rc == 0) {
- msm_mctl_pp_get_phy_addr(pcam_inst, free_buf.vb, &frame.frame);
- if (copy_to_user((void *)arg, &frame, sizeof(frame))) {
+ msm_mctl_pp_get_phy_addr(pcam_inst,
+ free_buf.vb, &div_frame.frame);
+ if (copy_to_user((void *)arg, &div_frame, sizeof(div_frame))) {
ERR_COPY_TO_USER();
rc = -EFAULT;
}
}
D("%s: reserve free buf got buffer %d from %p rc = %d, phy = 0x%x",
- __func__, frame.frame.buf_idx,
+ __func__, div_frame.frame.buf_idx,
pcam_inst, rc, free_buf.ch_paddr[0]);
return rc;
}
@@ -535,10 +547,13 @@
struct msm_pp_frame *frame;
int image_mode, rc = 0;
struct msm_free_buf free_buf;
+ struct msm_cam_buf_handle buf_handle;
if (copy_from_user(&div_frame, arg,
- sizeof(struct msm_cam_evt_divert_frame)))
+ sizeof(struct msm_cam_evt_divert_frame))) {
+ ERR_COPY_FROM_USER();
return -EFAULT;
+ }
image_mode = div_frame.image_mode;
if (image_mode < 0) {
@@ -551,15 +566,21 @@
else
free_buf.ch_paddr[0] = frame->sp.phy_addr;
- pcam_inst = msm_mctl_get_pcam_inst(p_mctl, image_mode);
+ if (div_frame.frame.inst_handle) {
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+ buf_handle.inst_handle = div_frame.frame.inst_handle;
+ } else {
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
+ buf_handle.image_mode = image_mode;
+ }
+ pcam_inst = msm_mctl_get_pcam_inst(p_mctl, &buf_handle);
if (!pcam_inst) {
pr_err("%s Invalid instance. Cannot release frame.\n",
__func__);
return -EINVAL;
}
- rc = msm_mctl_release_free_buf(p_mctl, pcam_inst,
- image_mode, &free_buf);
+ rc = msm_mctl_release_free_buf(p_mctl, pcam_inst, &free_buf);
D("%s: release free buf, rc = %d, phy = 0x%x",
__func__, rc, free_buf.ch_paddr[0]);
@@ -573,11 +594,13 @@
unsigned long flags;
spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
if (copy_from_user(&p_mctl->pp_info.pp_key,
- arg, sizeof(p_mctl->pp_info.pp_key)))
+ arg, sizeof(p_mctl->pp_info.pp_key))) {
+ ERR_COPY_FROM_USER();
rc = -EFAULT;
- else
+ } else {
D("%s: mctl=0x%p, pp_key_setting=0x%x",
__func__, p_mctl, p_mctl->pp_info.pp_key);
+ }
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
return rc;
}
@@ -591,12 +614,24 @@
int dirty = 0;
struct msm_free_buf buf;
unsigned long flags;
+ struct msm_cam_buf_handle buf_handle;
- if (copy_from_user(&frame, arg, sizeof(frame)))
+ if (copy_from_user(&frame, arg, sizeof(frame))) {
+ ERR_COPY_FROM_USER();
return -EFAULT;
+ }
spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
- image_mode = msm_mctl_pp_path_to_img_mode(frame.path);
+ if (frame.inst_handle) {
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+ buf_handle.inst_handle = frame.inst_handle;
+ image_mode = GET_IMG_MODE(frame.inst_handle);
+ } else {
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
+ buf_handle.image_mode =
+ msm_mctl_pp_path_to_img_mode(frame.path);
+ image_mode = buf_handle.image_mode;
+ }
if (image_mode < 0) {
pr_err("%s Invalid image mode\n", __func__);
return image_mode;
@@ -622,8 +657,7 @@
buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off;
}
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
- /* here buf.addr is phy_addr */
- rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty, 0);
+ rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, dirty, 0);
return rc;
}
@@ -636,10 +670,14 @@
int dirty = 0;
struct msm_free_buf buf;
unsigned long flags;
+ struct msm_cam_buf_handle buf_handle;
+
D("%s enter\n", __func__);
- if (copy_from_user(&frame, arg, sizeof(frame)))
+ if (copy_from_user(&frame, arg, sizeof(frame))) {
+ ERR_COPY_FROM_USER();
return -EFAULT;
+ }
spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
D("%s Frame path: %d\n", __func__, frame.path);
@@ -665,6 +703,14 @@
goto err;
}
+ if (frame.inst_handle) {
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE;
+ buf_handle.inst_handle = frame.inst_handle;
+ } else {
+ buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE;
+ buf_handle.image_mode = image_mode;
+ }
+
if (frame.num_planes > 1)
buf.ch_paddr[0] = frame.mp[0].phy_addr +
frame.mp[0].data_offset;
@@ -673,7 +719,7 @@
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
D("%s Frame done id: %d\n", __func__, frame.frame_id);
- rc = msm_mctl_buf_done_pp(p_mctl, image_mode,
+ rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle,
&buf, dirty, frame.node_type);
return rc;
err:
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index 71bce67..18168ee 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -643,7 +643,7 @@
vfe31_ctrl->vfebase + VFE_GLOBAL_RESET);
}
-static void vfe31_subdev_notify(int id, int path, int image_mode)
+static void vfe31_subdev_notify(int id, int path, uint32_t inst_handle)
{
struct msm_vfe_resp rp;
struct msm_frame_info frame_info;
@@ -652,7 +652,7 @@
memset(&rp, 0, sizeof(struct msm_vfe_resp));
CDBG("vfe31_subdev_notify : msgId = %d\n", id);
rp.evt_msg.type = MSM_CAMERA_MSG;
- frame_info.image_mode = image_mode;
+ frame_info.inst_handle = inst_handle;
frame_info.path = path;
rp.evt_msg.data = &frame_info;
rp.type = id;
@@ -663,20 +663,21 @@
static int vfe31_config_axi(int mode, uint32_t *ao)
{
uint32_t *ch_info;
- uint32_t *axi_cfg = ao+V31_AXI_RESERVED;
+ uint32_t *axi_cfg = ao + V31_AXI_RESERVED;
/* Update the corresponding write masters for each output*/
ch_info = axi_cfg + V31_AXI_CFG_LEN;
vfe31_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
vfe31_ctrl->outpath.out0.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
- vfe31_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info;
- vfe31_ctrl->outpath.out0.image_mode = 0x0000FFFF & (*ch_info++ >> 16);
+ vfe31_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
+ vfe31_ctrl->outpath.out0.inst_handle = *ch_info++;
vfe31_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
vfe31_ctrl->outpath.out1.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
- vfe31_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info;
- vfe31_ctrl->outpath.out1.image_mode = 0x0000FFFF & (*ch_info++ >> 16);
+ vfe31_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
+ vfe31_ctrl->outpath.out1.inst_handle = *ch_info++;
vfe31_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
vfe31_ctrl->outpath.out2.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
vfe31_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
+ vfe31_ctrl->outpath.out2.inst_handle = *ch_info++;
switch (mode) {
case OUTPUT_PRIM:
@@ -713,7 +714,7 @@
msm_camera_io_memcpy(vfe31_ctrl->vfebase +
vfe31_cmd[VFE_CMD_AXI_OUT_CFG].offset, axi_cfg,
vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length - V31_AXI_CH_INF_LEN -
- V31_AXI_RESERVED);
+ V31_AXI_RESERVED_LEN);
return 0;
}
@@ -1301,14 +1302,14 @@
{
struct vfe31_output_ch *outch = NULL;
struct msm_free_buf *b = NULL;
- uint32_t image_mode = 0;
+ uint32_t inst_handle = 0;
if (path == VFE_MSG_OUTPUT_PRIMARY)
- image_mode = vfe31_ctrl->outpath.out0.image_mode;
+ inst_handle = vfe31_ctrl->outpath.out0.inst_handle;
else
- image_mode = vfe31_ctrl->outpath.out1.image_mode;
+ inst_handle = vfe31_ctrl->outpath.out1.inst_handle;
- vfe31_subdev_notify(id, path, image_mode);
+ vfe31_subdev_notify(id, path, inst_handle);
outch = vfe31_get_ch(path);
if (outch->free_buf.ch_paddr[0])
b = &outch->free_buf;
@@ -1318,14 +1319,14 @@
{
struct vfe31_output_ch *outch = NULL;
int rc = 0;
- uint32_t image_mode = 0;
+ uint32_t inst_handle = 0;
if (path == VFE_MSG_OUTPUT_PRIMARY)
- image_mode = vfe31_ctrl->outpath.out0.image_mode;
+ inst_handle = vfe31_ctrl->outpath.out0.inst_handle;
else
- image_mode = vfe31_ctrl->outpath.out1.image_mode;
+ inst_handle = vfe31_ctrl->outpath.out1.inst_handle;
- vfe31_subdev_notify(id, path, image_mode);
+ vfe31_subdev_notify(id, path, inst_handle);
outch = vfe31_get_ch(path);
if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
/* Configure Preview Ping Pong */
@@ -1477,16 +1478,26 @@
case VFE_CMD_START_RECORDING:
pr_info("vfe31_proc_general: cmdID = %s\n",
vfe31_general_cmd[cmd->id]);
+ if (copy_from_user(&temp1, (void __user *)(cmd->value),
+ sizeof(uint32_t))) {
+ pr_err("%s Error copying inst_handle for recording\n",
+ __func__);
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
if (vfe31_ctrl->operation_mode ==
- VFE_OUTPUTS_PREVIEW_AND_VIDEO)
+ VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+ vfe31_ctrl->outpath.out1.inst_handle = temp1;
rc = vfe31_configure_pingpong_buffers(
VFE_MSG_V31_START_RECORDING,
VFE_MSG_OUTPUT_SECONDARY);
- else if (vfe31_ctrl->operation_mode ==
- VFE_OUTPUTS_VIDEO_AND_PREVIEW)
+ } else if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+ vfe31_ctrl->outpath.out0.inst_handle = temp1;
rc = vfe31_configure_pingpong_buffers(
VFE_MSG_V31_START_RECORDING,
VFE_MSG_OUTPUT_PRIMARY);
+ }
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
" for video", __func__);
@@ -1916,6 +1927,14 @@
break;
case VFE_CMD_LIVESHOT:
+ if (copy_from_user(&temp1, (void __user *)(cmd->value),
+ sizeof(uint32_t))) {
+ pr_err("%s Error copying inst_handle for liveshot ",
+ __func__);
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ vfe31_ctrl->outpath.out0.inst_handle = temp1;
/* Configure primary channel */
rc = vfe31_configure_pingpong_buffers(VFE_MSG_V31_CAPTURE,
VFE_MSG_OUTPUT_PRIMARY);
@@ -2715,12 +2734,12 @@
}
static void vfe_send_outmsg(struct v4l2_subdev *sd, uint8_t msgid,
uint32_t ch0_paddr, uint32_t ch1_paddr,
- uint32_t ch2_paddr, uint32_t image_mode)
+ uint32_t ch2_paddr, uint32_t inst_handle)
{
struct isp_msg_output msg;
msg.output_id = msgid;
- msg.buf.image_mode = image_mode;
+ msg.buf.inst_handle = inst_handle;
msg.buf.ch_paddr[0] = ch0_paddr;
msg.buf.ch_paddr[1] = ch1_paddr;
msg.buf.ch_paddr[2] = ch2_paddr;
@@ -2803,7 +2822,7 @@
vfe_send_outmsg(&vfe31_ctrl->subdev,
MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
ch1_paddr, ch2_paddr,
- vfe31_ctrl->outpath.out0.image_mode);
+ vfe31_ctrl->outpath.out0.inst_handle);
if (vfe31_ctrl->liveshot_state == VFE_STATE_STOPPED)
vfe31_ctrl->liveshot_state = VFE_STATE_IDLE;
@@ -2876,7 +2895,7 @@
vfe_send_outmsg(&vfe31_ctrl->subdev,
MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
ch1_paddr, ch2_paddr,
- vfe31_ctrl->outpath.out1.image_mode);
+ vfe31_ctrl->outpath.out1.inst_handle);
} else {
vfe31_ctrl->outpath.out1.frame_drop_cnt++;
CDBG("path_irq_1 - no free buffer!\n");
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.h b/drivers/media/video/msm/msm_vfe31_v4l2.h
index 2cba995..6396966 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.h
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.h
@@ -217,10 +217,11 @@
#define V31_OPERATION_CFG_LEN 32
#define V31_AXI_OUT_OFF 0x00000038
-#define V31_AXI_OUT_LEN 212
-#define V31_AXI_CH_INF_LEN 24
+#define V31_AXI_OUT_LEN 240
+#define V31_AXI_CH_INF_LEN 48
#define V31_AXI_CFG_LEN 47
#define V31_AXI_RESERVED 1
+#define V31_AXI_RESERVED_LEN 4
#define V31_FRAME_SKIP_OFF 0x00000504
#define V31_FRAME_SKIP_LEN 32
@@ -696,7 +697,7 @@
struct vfe31_output_ch {
struct list_head free_buf_queue;
spinlock_t free_buf_lock;
- uint16_t image_mode;
+ uint32_t inst_handle;
int8_t ch0;
int8_t ch1;
int8_t ch2;
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index cbe1f15..aa2b19d 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -393,7 +393,7 @@
vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
}
-static void vfe32_subdev_notify(int id, int path, int image_mode,
+static void vfe32_subdev_notify(int id, int path, uint32_t inst_handle,
struct v4l2_subdev *sd, struct vfe_share_ctrl_t *share_ctrl)
{
struct msm_vfe_resp rp;
@@ -403,7 +403,7 @@
CDBG("vfe32_subdev_notify : msgId = %d\n", id);
memset(&rp, 0, sizeof(struct msm_vfe_resp));
rp.evt_msg.type = MSM_CAMERA_MSG;
- frame_info.image_mode = image_mode;
+ frame_info.inst_handle = inst_handle;
frame_info.path = path;
rp.evt_msg.data = &frame_info;
rp.type = id;
@@ -423,27 +423,27 @@
axi_ctrl->share_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
axi_ctrl->share_ctrl->outpath.out0.ch1 =
0x0000FFFF & (*ch_info++ >> 16);
- axi_ctrl->share_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info;
- axi_ctrl->share_ctrl->outpath.out0.image_mode =
- 0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
+ axi_ctrl->share_ctrl->outpath.out0.inst_handle = *ch_info++;
+
axi_ctrl->share_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
axi_ctrl->share_ctrl->outpath.out1.ch1 =
0x0000FFFF & (*ch_info++ >> 16);
- axi_ctrl->share_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info;
- axi_ctrl->share_ctrl->outpath.out1.image_mode =
- 0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
+ axi_ctrl->share_ctrl->outpath.out1.inst_handle = *ch_info++;
+
axi_ctrl->share_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
axi_ctrl->share_ctrl->outpath.out2.ch1 =
0x0000FFFF & (*ch_info++ >> 16);
- axi_ctrl->share_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info;
- axi_ctrl->share_ctrl->outpath.out2.image_mode =
- 0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
+ axi_ctrl->share_ctrl->outpath.out2.inst_handle = *ch_info++;
+
axi_ctrl->share_ctrl->outpath.out3.ch0 = 0x0000FFFF & *ch_info;
axi_ctrl->share_ctrl->outpath.out3.ch1 =
0x0000FFFF & (*ch_info++ >> 16);
- axi_ctrl->share_ctrl->outpath.out3.ch2 = 0x0000FFFF & *ch_info;
- axi_ctrl->share_ctrl->outpath.out3.image_mode =
- 0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.out3.ch2 = 0x0000FFFF & *ch_info++;
+ axi_ctrl->share_ctrl->outpath.out3.inst_handle = *ch_info++;
+
axi_ctrl->share_ctrl->outpath.output_mode = 0;
if (mode & OUTPUT_TERT1)
@@ -1468,18 +1468,18 @@
{
struct vfe32_output_ch *outch = NULL;
struct msm_free_buf *b = NULL;
- uint32_t image_mode = 0;
+ uint32_t inst_handle = 0;
if (path == VFE_MSG_OUTPUT_PRIMARY)
- image_mode = axi_ctrl->share_ctrl->outpath.out0.image_mode;
+ inst_handle = axi_ctrl->share_ctrl->outpath.out0.inst_handle;
else if (path == VFE_MSG_OUTPUT_SECONDARY)
- image_mode = axi_ctrl->share_ctrl->outpath.out1.image_mode;
+ inst_handle = axi_ctrl->share_ctrl->outpath.out1.inst_handle;
else if (path == VFE_MSG_OUTPUT_TERTIARY1)
- image_mode = axi_ctrl->share_ctrl->outpath.out2.image_mode;
+ inst_handle = axi_ctrl->share_ctrl->outpath.out2.inst_handle;
else if (path == VFE_MSG_OUTPUT_TERTIARY2)
- image_mode = axi_ctrl->share_ctrl->outpath.out3.image_mode;
+ inst_handle = axi_ctrl->share_ctrl->outpath.out3.inst_handle;
- vfe32_subdev_notify(id, path, image_mode,
+ vfe32_subdev_notify(id, path, inst_handle,
&axi_ctrl->subdev, axi_ctrl->share_ctrl);
outch = vfe32_get_ch(path, axi_ctrl->share_ctrl);
if (outch->free_buf.ch_paddr[0])
@@ -1491,17 +1491,17 @@
{
struct vfe32_output_ch *outch = NULL;
int rc = 0;
- uint32_t image_mode = 0;
+ uint32_t inst_handle = 0;
if (path == VFE_MSG_OUTPUT_PRIMARY)
- image_mode = vfe32_ctrl->share_ctrl->outpath.out0.image_mode;
+ inst_handle = vfe32_ctrl->share_ctrl->outpath.out0.inst_handle;
else if (path == VFE_MSG_OUTPUT_SECONDARY)
- image_mode = vfe32_ctrl->share_ctrl->outpath.out1.image_mode;
+ inst_handle = vfe32_ctrl->share_ctrl->outpath.out1.inst_handle;
else if (path == VFE_MSG_OUTPUT_TERTIARY1)
- image_mode = vfe32_ctrl->share_ctrl->outpath.out2.image_mode;
+ inst_handle = vfe32_ctrl->share_ctrl->outpath.out2.inst_handle;
else if (path == VFE_MSG_OUTPUT_TERTIARY2)
- image_mode = vfe32_ctrl->share_ctrl->outpath.out3.image_mode;
+ inst_handle = vfe32_ctrl->share_ctrl->outpath.out3.inst_handle;
- vfe32_subdev_notify(id, path, image_mode,
+ vfe32_subdev_notify(id, path, inst_handle,
&vfe32_ctrl->subdev, vfe32_ctrl->share_ctrl);
outch = vfe32_get_ch(path, vfe32_ctrl->share_ctrl);
if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
@@ -1708,18 +1708,30 @@
case VFE_CMD_START_RECORDING:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
+ if (copy_from_user(&temp1, (void __user *)(cmd->value),
+ sizeof(uint32_t))) {
+ pr_err("%s Error copying inst_handle for recording\n",
+ __func__);
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
if (vfe32_ctrl->share_ctrl->operation_mode &
- VFE_OUTPUTS_PREVIEW_AND_VIDEO)
+ VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+ vfe32_ctrl->share_ctrl->outpath.out1.inst_handle =
+ temp1;
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_V32_START_RECORDING,
VFE_MSG_OUTPUT_SECONDARY,
vfe32_ctrl);
- else if (vfe32_ctrl->share_ctrl->operation_mode &
- VFE_OUTPUTS_VIDEO_AND_PREVIEW)
+ } else if (vfe32_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+ vfe32_ctrl->share_ctrl->outpath.out0.inst_handle =
+ temp1;
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_V32_START_RECORDING,
VFE_MSG_OUTPUT_PRIMARY,
vfe32_ctrl);
+ }
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
" for video", __func__);
@@ -2191,6 +2203,14 @@
break;
case VFE_CMD_LIVESHOT:
+ if (copy_from_user(&temp1, (void __user *)(cmd->value),
+ sizeof(uint32_t))) {
+ pr_err("%s Error copying inst_handle for liveshot ",
+ __func__);
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ vfe32_ctrl->share_ctrl->outpath.out0.inst_handle = temp1;
/* Configure primary channel */
rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
VFE_MSG_OUTPUT_PRIMARY, vfe32_ctrl);
@@ -3456,12 +3476,12 @@
static void vfe_send_outmsg(
struct axi_ctrl_t *axi_ctrl, uint8_t msgid,
uint32_t ch0_paddr, uint32_t ch1_paddr,
- uint32_t ch2_paddr, uint32_t image_mode)
+ uint32_t ch2_paddr, uint32_t inst_handle)
{
struct isp_msg_output msg;
msg.output_id = msgid;
- msg.buf.image_mode = image_mode;
+ msg.buf.inst_handle = inst_handle;
msg.buf.ch_paddr[0] = ch0_paddr;
msg.buf.ch_paddr[1] = ch1_paddr;
msg.buf.ch_paddr[2] = ch2_paddr;
@@ -3563,7 +3583,7 @@
vfe_send_outmsg(axi_ctrl,
MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
ch1_paddr, ch2_paddr,
- axi_ctrl->share_ctrl->outpath.out0.image_mode);
+ axi_ctrl->share_ctrl->outpath.out0.inst_handle);
} else {
axi_ctrl->share_ctrl->outpath.out0.frame_drop_cnt++;
@@ -3641,7 +3661,7 @@
vfe_send_outmsg(axi_ctrl,
MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
ch1_paddr, ch2_paddr,
- axi_ctrl->share_ctrl->outpath.out1.image_mode);
+ axi_ctrl->share_ctrl->outpath.out1.inst_handle);
} else {
axi_ctrl->share_ctrl->outpath.out1.frame_drop_cnt++;
@@ -3682,7 +3702,7 @@
vfe_send_outmsg(axi_ctrl,
MSG_ID_OUTPUT_TERTIARY1, ch0_paddr,
0, 0,
- axi_ctrl->share_ctrl->outpath.out2.image_mode);
+ axi_ctrl->share_ctrl->outpath.out2.inst_handle);
} else {
axi_ctrl->share_ctrl->outpath.out2.frame_drop_cnt++;
@@ -3723,7 +3743,7 @@
vfe_send_outmsg(axi_ctrl,
MSG_ID_OUTPUT_TERTIARY2, ch0_paddr,
0, 0,
- axi_ctrl->share_ctrl->outpath.out3.image_mode);
+ axi_ctrl->share_ctrl->outpath.out3.inst_handle);
} else {
axi_ctrl->share_ctrl->outpath.out3.frame_drop_cnt++;
pr_err("path_irq irq - no free buffer for rdi1!\n");
@@ -4734,7 +4754,8 @@
return rc;
clk_enable_failed:
- regulator_disable(axi_ctrl->fs_vfe);
+ if (axi_ctrl->fs_vfe)
+ regulator_disable(axi_ctrl->fs_vfe);
fs_failed:
iounmap(axi_ctrl->share_ctrl->vfebase);
axi_ctrl->share_ctrl->vfebase = NULL;
@@ -4912,12 +4933,14 @@
pr_err("%s: base address unmapped\n", __func__);
return -EFAULT;
}
+ memset(&cfgcmd, 0, sizeof(struct msm_vfe_cfg_cmd));
if (NULL != arg) {
if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) {
ERR_COPY_FROM_USER();
return -EFAULT;
}
}
+ memset(&vfecmd, 0, sizeof(struct msm_isp_cmd));
if (NULL != cfgcmd.value) {
if (copy_from_user(&vfecmd,
(void __user *)(cfgcmd.value),
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 3196eda..9336cfb 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -241,8 +241,8 @@
#define V32_OPERATION_CFG_LEN 44
#define V32_AXI_OUT_OFF 0x00000038
-#define V32_AXI_OUT_LEN 224
-#define V32_AXI_CH_INF_LEN 32
+#define V32_AXI_OUT_LEN 240
+#define V32_AXI_CH_INF_LEN 48
#define V32_AXI_CFG_LEN 47
#define V32_AXI_BUS_FMT_OFF 1
#define V32_AXI_BUS_FMT_LEN 4
@@ -756,7 +756,7 @@
struct vfe32_output_ch {
struct list_head free_buf_queue;
spinlock_t free_buf_lock;
- uint16_t image_mode;
+ uint32_t inst_handle;
int8_t ch0;
int8_t ch1;
int8_t ch2;
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index 3701331..64e0385 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -585,7 +585,7 @@
struct isp_msg_output msg;
msg.output_id = msgid;
- msg.buf.image_mode = -1;
+ msg.buf.inst_handle = 0;
msg.buf.ch_paddr[0] = ch0_paddr;
msg.buf.ch_paddr[1] = ch1_paddr;
msg.frameCounter = vfe2x_ctrl->vfeFrameId;
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 58fc153..5990ca7 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -545,7 +545,8 @@
return rc;
vpe_clk_failed:
- regulator_disable(vpe_ctrl->fs_vpe);
+ if (vpe_ctrl->fs_vpe)
+ regulator_disable(vpe_ctrl->fs_vpe);
vpe_fs_failed:
disable_irq(vpe_ctrl->vpeirq->start);
vpe_ctrl->state = VPE_STATE_IDLE;
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 2dfdd7e..deab77b 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -96,6 +96,19 @@
return -EINVAL;
}
+void msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
+ struct video_device *pvdev)
+{
+ v4l2_fh_init(eventHandle, pvdev);
+ v4l2_fh_add(eventHandle);
+}
+
+void msm_destroy_v4l2_event_queue(struct v4l2_fh *eventHandle)
+{
+ v4l2_fh_del(eventHandle);
+ v4l2_fh_exit(eventHandle);
+}
+
uint32_t msm_cam_server_get_mctl_handle(void)
{
uint32_t i;
@@ -423,6 +436,7 @@
plane_info.buffer_type = pfmt->type;
plane_info.ext_mode = pcam->dev_inst[idx]->image_mode;
plane_info.num_planes = 1;
+ plane_info.inst_handle = pcam->dev_inst[idx]->inst_handle;
D("%s: %d, %d, 0x%x\n", __func__,
pfmt->fmt.pix.width, pfmt->fmt.pix.height,
pfmt->fmt.pix.pixelformat);
@@ -479,6 +493,8 @@
plane_info.buffer_type = pfmt->type;
plane_info.ext_mode = pcam->dev_inst[idx]->image_mode;
plane_info.num_planes = pix_mp->num_planes;
+ plane_info.inst_handle = pcam->dev_inst[idx]->inst_handle;
+
if (plane_info.num_planes <= 0 ||
plane_info.num_planes > VIDEO_MAX_PLANES) {
pr_err("%s Invalid number of planes set %d", __func__,
@@ -1767,7 +1783,7 @@
* the individual irq lookup table.... */
irq_req->irq_idx =
get_irq_idx_from_camhw_idx(irq_req->cam_hw_idx);
- if (irq_req->cam_hw_idx < 0) {
+ if (irq_req->irq_idx < 0) {
pr_err("%s Invalid hw index %d ", __func__,
irq_req->cam_hw_idx);
return -EINVAL;
@@ -2089,16 +2105,10 @@
/*initialize fake video device and event queue*/
g_server_dev.server_command_queue.pvdev = g_server_dev.video_dev;
- rc = msm_setup_v4l2_event_queue(
+ msm_setup_v4l2_event_queue(
&g_server_dev.server_command_queue.eventHandle,
g_server_dev.server_command_queue.pvdev);
- if (rc < 0) {
- pr_err("%s failed to initialize event queue\n", __func__);
- video_device_release(g_server_dev.server_command_queue.pvdev);
- return rc;
- }
-
for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
struct msm_cam_server_queue *queue;
queue = &g_server_dev.server_queue[i];
@@ -2828,14 +2838,12 @@
goto config_setup_fail;
}
- rc = msm_setup_v4l2_event_queue(
+ /* v4l2_fh support */
+ spin_lock_init(&config_cam->config_stat_event_queue.pvdev->fh_lock);
+ INIT_LIST_HEAD(&config_cam->config_stat_event_queue.pvdev->fh_list);
+ msm_setup_v4l2_event_queue(
&config_cam->config_stat_event_queue.eventHandle,
config_cam->config_stat_event_queue.pvdev);
- if (rc < 0) {
- pr_err("%s failed to initialize event queue\n", __func__);
- video_device_release(config_cam->config_stat_event_queue.pvdev);
- goto config_setup_fail;
- }
return rc;
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index 2913d74..76e3592 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -12,6 +12,7 @@
*/
#include <linux/slab.h>
+#include <mach/iommu_domains.h>
#include "msm_smem.h"
struct smem_client {
@@ -19,12 +20,44 @@
void *clnt;
};
+static int get_device_address(struct ion_client *clnt,
+ struct ion_handle *hndl, int domain_num, int partition_num,
+ unsigned long align, unsigned long *iova,
+ unsigned long *buffer_size, unsigned long flags)
+{
+ int rc;
+
+ if (!iova || !buffer_size || !hndl || !clnt) {
+ pr_err("Invalid params: %p, %p, %p, %p\n",
+ clnt, hndl, iova, buffer_size);
+ return -EINVAL;
+ }
+ if (align < 4096)
+ align = 4096;
+ flags |= UNCACHED;
+ rc = ion_map_iommu(clnt, hndl, domain_num, partition_num, align,
+ 0, iova, buffer_size, flags, 0);
+ if (rc)
+ pr_err("ion_map_iommu failed(%d).domain: %d,partition: %d\n",
+ rc, domain_num, partition_num);
+
+ return rc;
+}
+
+static void put_device_address(struct ion_client *clnt,
+ struct ion_handle *hndl, int domain_num)
+{
+ ion_unmap_iommu(clnt, hndl, domain_num, 0);
+}
+
static int ion_user_to_kernel(struct smem_client *client,
- int fd, u32 offset, struct msm_smem *mem)
+ int fd, u32 offset, int domain, int partition,
+ struct msm_smem *mem)
{
struct ion_handle *hndl;
unsigned long ionflag;
- size_t len;
+ unsigned long iova = 0;
+ unsigned long buffer_size = 0;
int rc = 0;
hndl = ion_import_dma_buf(client->clnt, fd);
if (IS_ERR_OR_NULL(hndl)) {
@@ -38,25 +71,29 @@
pr_err("Failed to get ion flags: %d", rc);
goto fail_map;
}
- rc = ion_phys(client->clnt, hndl, &mem->paddr, &len);
- if (rc) {
- pr_err("Failed to get physical address\n");
- goto fail_map;
- }
mem->kvaddr = ion_map_kernel(client->clnt, hndl, ionflag);
if (!mem->kvaddr) {
pr_err("Failed to map shared mem in kernel\n");
rc = -EIO;
goto fail_map;
}
+ mem->domain = domain;
+ mem->partition_num = partition;
+ rc = get_device_address(client->clnt, hndl, mem->domain,
+ mem->partition_num, 4096, &iova, &buffer_size, UNCACHED);
+ if (rc) {
+ pr_err("Failed to get device address: %d\n", rc);
+ goto fail_device_address;
+ }
mem->kvaddr += offset;
- mem->paddr += offset;
mem->mem_type = client->mem_type;
mem->smem_priv = hndl;
- mem->device_addr = mem->paddr;
- mem->size = len;
+ mem->device_addr = iova + offset;
+ mem->size = buffer_size;
return rc;
+fail_device_address:
+ ion_unmap_kernel(client->clnt, hndl);
fail_map:
ion_free(client->clnt, hndl);
fail_import_fd:
@@ -64,14 +101,19 @@
}
static int alloc_ion_mem(struct smem_client *client, size_t size,
- u32 align, u32 flags, struct msm_smem *mem)
+ u32 align, u32 flags, int domain, int partition,
+ struct msm_smem *mem)
{
struct ion_handle *hndl;
- size_t len;
+ unsigned long iova = 0;
+ unsigned long buffer_size = 0;
int rc = 0;
if (size == 0)
goto skip_mem_alloc;
flags = flags | ION_HEAP(ION_CP_MM_HEAP_ID);
+ if (align < 4096)
+ align = 4096;
+ size = (size + 4095) & (~4095);
hndl = ion_alloc(client->clnt, size, align, flags);
if (IS_ERR_OR_NULL(hndl)) {
pr_err("Failed to allocate shared memory = %p, %d, %d, 0x%x\n",
@@ -81,20 +123,27 @@
}
mem->mem_type = client->mem_type;
mem->smem_priv = hndl;
- if (ion_phys(client->clnt, hndl, &mem->paddr, &len)) {
- pr_err("Failed to get physical address\n");
- rc = -EIO;
- goto fail_map;
- }
- mem->device_addr = mem->paddr;
- mem->size = size;
+ mem->domain = domain;
+ mem->partition_num = partition;
mem->kvaddr = ion_map_kernel(client->clnt, hndl, 0);
if (!mem->kvaddr) {
pr_err("Failed to map shared mem in kernel\n");
rc = -EIO;
goto fail_map;
}
+ rc = get_device_address(client->clnt, hndl, mem->domain,
+ mem->partition_num, align, &iova, &buffer_size, UNCACHED);
+ if (rc) {
+ pr_err("Failed to get device address: %d\n", rc);
+ goto fail_device_address;
+ }
+ mem->device_addr = iova;
+ pr_err("device_address = 0x%lx, kvaddr = 0x%p\n",
+ mem->device_addr, mem->kvaddr);
+ mem->size = size;
return rc;
+fail_device_address:
+ ion_unmap_kernel(client->clnt, hndl);
fail_map:
ion_free(client->clnt, hndl);
fail_shared_mem_alloc:
@@ -104,6 +153,8 @@
static void free_ion_mem(struct smem_client *client, struct msm_smem *mem)
{
+ put_device_address(client->clnt,
+ mem->smem_priv, mem->domain);
ion_unmap_kernel(client->clnt, mem->smem_priv);
ion_free(client->clnt, mem->smem_priv);
}
@@ -122,7 +173,8 @@
ion_client_destroy(client->clnt);
}
-struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset)
+struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset,
+ int domain, int partition)
{
struct smem_client *client = clt;
int rc = 0;
@@ -138,7 +190,8 @@
}
switch (client->mem_type) {
case SMEM_ION:
- rc = ion_user_to_kernel(clt, fd, offset, mem);
+ rc = ion_user_to_kernel(clt, fd, offset,
+ domain, partition, mem);
break;
default:
pr_err("Mem type not supported\n");
@@ -177,7 +230,8 @@
return client;
};
-struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags)
+struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
+ int domain, int partition)
{
struct smem_client *client;
int rc = 0;
@@ -195,7 +249,8 @@
}
switch (client->mem_type) {
case SMEM_ION:
- rc = alloc_ion_mem(client, size, align, flags, mem);
+ rc = alloc_ion_mem(client, size, align, flags,
+ domain, partition, mem);
break;
default:
pr_err("Mem type not supported\n");
diff --git a/drivers/media/video/msm_vidc/msm_smem.h b/drivers/media/video/msm_vidc/msm_smem.h
index 84d12cc..b742c79 100644
--- a/drivers/media/video/msm_vidc/msm_smem.h
+++ b/drivers/media/video/msm_vidc/msm_smem.h
@@ -24,15 +24,17 @@
int mem_type;
size_t size;
void *kvaddr;
- unsigned long paddr;
unsigned long device_addr;
- /*Device address and others to follow*/
+ int domain;
+ int partition_num;
void *smem_priv;
};
void *msm_smem_new_client(enum smem_type mtype);
-struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags);
+struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
+ int domain, int partition);
void msm_smem_free(void *clt, struct msm_smem *mem);
void msm_smem_delete_client(void *clt);
-struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset);
+struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset, int
+ domain, int partition);
#endif
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 6cd9e6b..e1a71ce 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -21,7 +21,9 @@
#include <linux/debugfs.h>
#include <linux/version.h>
#include <linux/slab.h>
-
+#include <linux/of.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
#include <media/msm_vidc.h>
#include "msm_vidc_internal.h"
#include "vidc_hal_api.h"
@@ -277,8 +279,10 @@
goto exit;
}
handle = msm_smem_user_to_kernel(v4l2_inst->mem_client,
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1]);
+ b->m.planes[i].reserved[0],
+ b->m.planes[i].reserved[1],
+ vidc_inst->core->resources.io_map[NS_MAP].domain,
+ 0);
if (!handle) {
pr_err("Failed to get device buffer address\n");
kfree(binfo);
@@ -420,11 +424,92 @@
{
}
+static size_t read_u32_array(struct platform_device *pdev,
+ char *name, u32 *arr, size_t size)
+{
+ int len;
+ size_t sz = 0;
+ struct device_node *np = pdev->dev.of_node;
+ if (!of_get_property(np, name, &len)) {
+ pr_err("Failed to read %s from device tree\n",
+ name);
+ goto fail_read;
+ }
+ sz = len / sizeof(u32);
+ if (sz <= 0) {
+ pr_err("%s not specified in device tree\n", name);
+ goto fail_read;
+ }
+ if (sz > size) {
+ pr_err("Not enough memory to store %s values\n", name);
+ goto fail_read;
+ }
+ if (of_property_read_u32_array(np, name, arr, sz)) {
+ pr_err("error while reading %s from device tree\n",
+ name);
+ goto fail_read;
+ }
+ return sz;
+fail_read:
+ sz = 0;
+ return sz;
+}
+
+static int register_iommu_domains(struct platform_device *pdev,
+ struct msm_vidc_core *core)
+{
+ size_t len;
+ struct msm_iova_partition partition;
+ struct msm_iova_layout layout;
+ int rc = 0;
+ int i;
+ struct iommu_info *io_map = core->resources.io_map;
+ strlcpy(io_map[CP_MAP].name, "vidc-cp-map",
+ sizeof(io_map[CP_MAP].name));
+ strlcpy(io_map[CP_MAP].ctx, "venus_cp",
+ sizeof(io_map[CP_MAP].ctx));
+ strlcpy(io_map[NS_MAP].name, "vidc-ns-map",
+ sizeof(io_map[NS_MAP].name));
+ strlcpy(io_map[NS_MAP].ctx, "venus_ns",
+ sizeof(io_map[NS_MAP].ctx));
+
+ for (i = 0; i < MAX_MAP; i++) {
+ len = read_u32_array(pdev, io_map[i].name,
+ io_map[i].addr_range,
+ (sizeof(io_map[i].addr_range)/sizeof(u32)));
+ if (!len) {
+ pr_err("Error in reading cp address range\n");
+ rc = -EINVAL;
+ break;
+ }
+ partition.start = io_map[i].addr_range[0];
+ partition.size = io_map[i].addr_range[1];
+ layout.partitions = &partition;
+ layout.npartitions = 1;
+ layout.client_name = io_map[i].name;
+ layout.domain_flags = 0;
+ pr_debug("Registering domain with: %lx, %lx, %s\n",
+ partition.start, partition.size, layout.client_name);
+ io_map[i].domain = msm_register_domain(&layout);
+ if (io_map[i].domain < 0) {
+ pr_err("Failed to register cp domain\n");
+ rc = -EINVAL;
+ break;
+ }
+ }
+ /* There is no api provided as msm_unregister_domain, so
+ * we are not able to unregister the previously
+ * registered domains if any domain registration fails.*/
+ BUG_ON(i < MAX_MAP);
+ return rc;
+}
+
static int msm_vidc_initialize_core(struct platform_device *pdev,
struct msm_vidc_core *core)
{
struct resource *res;
int i = 0;
+ int rc = 0;
if (!core)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -443,13 +528,19 @@
INIT_LIST_HEAD(&core->instances);
mutex_init(&core->sync_lock);
spin_lock_init(&core->lock);
- core->base_addr = 0x14f00000;
+ core->base_addr = 0x0;
core->state = VIDC_CORE_UNINIT;
for (i = SYS_MSG_INDEX(SYS_MSG_START);
i <= SYS_MSG_INDEX(SYS_MSG_END); i++) {
init_completion(&core->completions[i]);
}
- return 0;
+ rc = register_iommu_domains(pdev, core);
+ if (rc) {
+ pr_err("Failed to register iommu domains: %d\n", rc);
+ goto fail_domain_register;
+ }
+fail_domain_register:
+ return rc;
}
static int __devinit msm_vidc_probe(struct platform_device *pdev)
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index a2e42e6..a8c6428 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -309,8 +309,21 @@
buffer_info.num_buffers = 1;
buffer_info.align_device_addr =
b->m.planes[i].m.userptr;
- buffer_info.extradata_size = 0;
- buffer_info.extradata_addr = 0;
+ if (!inst->extradata_handle) {
+ inst->extradata_handle =
+ msm_smem_alloc(inst->mem_client,
+ 4096 * 1024, 1, 0,
+ inst->core->resources.io_map[NS_MAP].domain,
+ 0);
+ if (!inst->extradata_handle) {
+ pr_err("Failed to allocate extradta memory\n");
+ rc = -ENOMEM;
+ break;
+ }
+ }
+ buffer_info.extradata_addr =
+ inst->extradata_handle->device_addr;
+ buffer_info.extradata_size = 4096 * 1024;
rc = vidc_hal_session_set_buffers((void *)inst->session,
&buffer_info);
if (rc) {
@@ -346,7 +359,8 @@
buffer_info.num_buffers = 1;
buffer_info.align_device_addr =
b->m.planes[i].m.userptr;
- buffer_info.extradata_addr = 0;
+ buffer_info.extradata_addr =
+ inst->extradata_handle->device_addr;
rc = vidc_hal_session_release_buffers(
(void *)inst->session, &buffer_info);
if (rc)
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index e3833ce..72c6685 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -23,11 +23,11 @@
#define MIN_NUM_OUTPUT_BUFFERS 2
#define MAX_NUM_OUTPUT_BUFFERS 8
#define MIN_BIT_RATE 64
-#define MAX_BIT_RATE 20000
+#define MAX_BIT_RATE 160000
#define DEFAULT_BIT_RATE 64
#define BIT_RATE_STEP 1
#define MIN_FRAME_RATE 1
-#define MAX_FRAME_RATE 120
+#define MAX_FRAME_RATE 240
#define DEFAULT_FRAME_RATE 30
#define DEFAULT_IR_MBS 30
#define MAX_SLICE_BYTE_SIZE 1024
@@ -63,6 +63,30 @@
"Model 2",
NULL
};
+
+static const char *const h263_level[] = {
+ "1.0",
+ "2.0",
+ "3.0",
+ "4.0",
+ "4.5",
+ "5.0",
+ "6.0",
+ "7.0",
+};
+
+static const char *const h263_profile[] = {
+ "Baseline",
+ "H320 Coding",
+ "Backward Compatible",
+ "ISWV2",
+ "ISWV3",
+ "High Compression",
+ "Internet",
+ "Interlace",
+ "High Latency",
+};
+
static const struct msm_vidc_ctrl msm_venc_ctrls[] = {
{
.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE,
@@ -212,10 +236,48 @@
.minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
.maximum = V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
.default_value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
- .step = 1,
+ .step = 0,
.menu_skip_mask = 0,
},
{
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE,
+ .name = "H263 Profile",
+ .type = V4L2_CTRL_TYPE_MENU,
+ .minimum = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE,
+ .maximum = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY,
+ .default_value = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE,
+ .menu_skip_mask = ~(
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_H320CODING) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BACKWARDCOMPATIBLE) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV2) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV3) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHCOMPRESSION) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERNET) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERLACE) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY)
+ ),
+ .qmenu = h263_profile,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL,
+ .name = "H263 Level",
+ .type = V4L2_CTRL_TYPE_MENU,
+ .minimum = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0,
+ .maximum = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0,
+ .default_value = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0,
+ .menu_skip_mask = ~(
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_2_0) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_3_0) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_0) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_5_0) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_6_0) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0)
+ ),
+ .qmenu = h263_level,
+ },
+ {
.id = V4L2_CID_MPEG_VIDC_VIDEO_ROTATION,
.name = "Rotation",
.type = V4L2_CTRL_TYPE_MENU,
@@ -410,8 +472,11 @@
venc_h264_profile_level = {HAL_H264_PROFILE_BASELINE,
HAL_H264_LEVEL_1};
static struct hal_profile_level
- venc_mpeg4_profile_level = {HAL_H264_PROFILE_BASELINE,
- HAL_H264_LEVEL_1};
+ venc_mpeg4_profile_level = {HAL_MPEG4_PROFILE_SIMPLE,
+ HAL_MPEG4_LEVEL_0};
+static struct hal_profile_level
+ venc_h263_profile_level = {HAL_H263_PROFILE_BASELINE,
+ HAL_H263_LEVEL_10};
static struct hal_h264_entropy_control
venc_h264_entropy_control = {HAL_H264_ENTROPY_CAVLC,
HAL_H264_CABAC_MODEL_0};
@@ -904,6 +969,84 @@
pr_debug("\nLevel: %d\n",
profile_level.level);
break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE:
+ property_id =
+ HAL_PARAM_PROFILE_LEVEL_CURRENT;
+
+ switch (control.value) {
+ case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE:
+ control.value = HAL_H263_PROFILE_BASELINE;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_H320CODING:
+ control.value = HAL_H263_PROFILE_H320CODING;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BACKWARDCOMPATIBLE:
+ control.value = HAL_H263_PROFILE_BACKWARDCOMPATIBLE;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV2:
+ control.value = HAL_H263_PROFILE_ISWV2;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV3:
+ control.value = HAL_H263_PROFILE_ISWV3;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHCOMPRESSION:
+ control.value = HAL_H263_PROFILE_HIGHCOMPRESSION;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERNET:
+ control.value = HAL_H263_PROFILE_INTERNET;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERLACE:
+ control.value = HAL_H263_PROFILE_INTERLACE;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY:
+ control.value = HAL_H263_PROFILE_HIGHLATENCY;
+ break;
+ default:
+ break;
+ }
+ profile_level.profile = control.value;
+ venc_h263_profile_level.profile = control.value;
+ profile_level.level = venc_h263_profile_level.level;
+ pdata = &profile_level;
+ break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL:
+ property_id =
+ HAL_PARAM_PROFILE_LEVEL_CURRENT;
+
+ switch (control.value) {
+ case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0:
+ control.value = HAL_H263_LEVEL_10;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_2_0:
+ control.value = HAL_H263_LEVEL_20;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_3_0:
+ control.value = HAL_H263_LEVEL_30;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_0:
+ control.value = HAL_H263_LEVEL_40;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_5:
+ control.value = HAL_H263_LEVEL_45;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_5_0:
+ control.value = HAL_H263_LEVEL_50;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_6_0:
+ control.value = HAL_H263_LEVEL_60;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0:
+ control.value = HAL_H263_LEVEL_70;
+ break;
+ default:
+ break;
+ }
+
+ profile_level.level = control.value;
+ venc_h263_profile_level.level = control.value;
+ profile_level.profile = venc_h263_profile_level.profile;
+ pdata = &profile_level;
+ break;
case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION:
property_id =
HAL_CONFIG_VPE_OPERATIONS;
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 28fe2b8..4d4cec5 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -316,6 +316,8 @@
kfree(buf);
}
}
+ if (inst->extradata_handle)
+ msm_smem_free(inst->mem_client, inst->extradata_handle);
spin_unlock_irqrestore(&inst->lock, flags);
msm_smem_delete_client(inst->mem_client);
}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 261879d..cd330316 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -13,6 +13,10 @@
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/iommu.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/peripheral-loader.h>
#include "msm_vidc_common.h"
#include "vidc_hal_api.h"
@@ -52,6 +56,60 @@
return NULL;
}
+static int msm_comm_iommu_attach(struct msm_vidc_core *core)
+{
+ int rc;
+ struct iommu_domain *domain;
+ int i;
+ struct iommu_info *io_map;
+ struct device *dev;
+ for (i = 0; i < MAX_MAP; i++) {
+ io_map = &core->resources.io_map[i];
+ dev = msm_iommu_get_ctx(io_map->ctx);
+ domain = msm_get_iommu_domain(io_map->domain);
+ if (IS_ERR_OR_NULL(domain)) {
+ pr_err("Failed to get domain: %s\n", io_map->name);
+ rc = PTR_ERR(domain);
+ break;
+ }
+ rc = iommu_attach_device(domain, dev);
+ if (rc) {
+ pr_err("IOMMU attach failed: %s\n", io_map->name);
+ break;
+ }
+ }
+ if (i < MAX_MAP) {
+ i--;
+ for (; i >= 0; i--) {
+ io_map = &core->resources.io_map[i];
+ dev = msm_iommu_get_ctx(io_map->ctx);
+ domain = msm_get_iommu_domain(io_map->domain);
+ if (dev && domain)
+ iommu_detach_device(domain, dev);
+ }
+ }
+ return rc;
+}
+
+static void msm_comm_iommu_detach(struct msm_vidc_core *core)
+{
+ struct device *dev;
+ struct iommu_domain *domain;
+ struct iommu_info *io_map;
+ int i;
+ if (!core) {
+ pr_err("Invalid paramter: %p\n", core);
+ return;
+ }
+ for (i = 0; i < MAX_MAP; i++) {
+ io_map = &core->resources.io_map[i];
+ dev = msm_iommu_get_ctx(io_map->ctx);
+ domain = msm_get_iommu_domain(io_map->domain);
+ if (dev && domain)
+ iommu_detach_device(domain, dev);
+ }
+}
+
const struct msm_vidc_format *msm_comm_get_pixel_fmt_index(
const struct msm_vidc_format fmt[], int size, int index, int fmt_type)
{
@@ -454,6 +512,47 @@
break;
}
}
+static int msm_comm_load_fw(struct msm_vidc_core *core)
+{
+ int rc = 0;
+ if (!core) {
+ pr_err("Invalid paramter: %p\n", core);
+ return -EINVAL;
+ }
+
+ if (!core->resources.fw.cookie)
+ core->resources.fw.cookie = pil_get("venus");
+
+ if (IS_ERR_OR_NULL(core->resources.fw.cookie)) {
+ pr_err("Failed to download firmware\n");
+ rc = -ENOMEM;
+ goto fail_pil_get;
+ }
+ rc = msm_comm_iommu_attach(core);
+ if (rc) {
+ pr_err("Failed to attach iommu");
+ goto fail_iommu_attach;
+ }
+ return rc;
+fail_iommu_attach:
+ pil_put(core->resources.fw.cookie);
+ core->resources.fw.cookie = NULL;
+fail_pil_get:
+ return rc;
+}
+
+static void msm_comm_unload_fw(struct msm_vidc_core *core)
+{
+ if (!core) {
+ pr_err("Invalid paramter: %p\n", core);
+ return;
+ }
+ if (core->resources.fw.cookie) {
+ pil_put(core->resources.fw.cookie);
+ core->resources.fw.cookie = NULL;
+ msm_comm_iommu_detach(core);
+ }
+}
static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
{
@@ -499,18 +598,28 @@
core->id, core->state);
goto core_already_inited;
}
+ rc = msm_comm_load_fw(core);
+ if (rc) {
+ pr_err("Failed to load video firmware\n");
+ goto fail_fw_download;
+ }
init_completion(&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)]);
- rc = vidc_hal_core_init(core->device);
+ rc = vidc_hal_core_init(core->device,
+ core->resources.io_map[NS_MAP].domain);
if (rc) {
pr_err("Failed to init core, id = %d\n", core->id);
- goto exit;
+ goto fail_core_init;
}
spin_lock_irqsave(&core->lock, flags);
core->state = VIDC_CORE_INIT;
spin_unlock_irqrestore(&core->lock, flags);
core_already_inited:
change_inst_state(inst, MSM_VIDC_CORE_INIT);
-exit:
+ mutex_unlock(&core->sync_lock);
+ return rc;
+fail_core_init:
+ msm_comm_unload_fw(core);
+fail_fw_download:
mutex_unlock(&core->sync_lock);
return rc;
}
@@ -536,6 +645,7 @@
spin_lock_irqsave(&core->lock, flags);
core->state = VIDC_CORE_UNINIT;
spin_unlock_irqrestore(&core->lock, flags);
+ msm_comm_unload_fw(core);
}
core_already_uninited:
change_inst_state(inst, MSM_VIDC_CORE_UNINIT);
@@ -889,9 +999,16 @@
} else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
frame_data.filled_len = 0;
frame_data.buffer_type = HAL_BUFFER_OUTPUT;
- frame_data.extradata_addr = 0;
- pr_debug("Sending ftb to hal..: Alloc: %d :filled: %d\n",
+ if (inst->extradata_handle) {
+ frame_data.extradata_addr =
+ inst->extradata_handle->device_addr;
+ } else {
+ frame_data.extradata_addr = 0;
+ }
+ pr_debug("Sending ftb to hal..: Alloc: %d :filled: %d",
frame_data.alloc_len, frame_data.filled_len);
+ pr_debug(" extradata_addr: %d\n",
+ frame_data.extradata_addr);
rc = vidc_hal_session_ftb((void *) inst->session,
&frame_data);
} else {
@@ -1020,7 +1137,8 @@
for (i = 0; i < inst->buff_req.buffer[6].buffer_count_actual;
i++) {
handle = msm_smem_alloc(inst->mem_client,
- inst->buff_req.buffer[6].buffer_size, 1, 0);
+ inst->buff_req.buffer[6].buffer_size, 1, 0,
+ inst->core->resources.io_map[NS_MAP].domain, 0);
if (!handle) {
pr_err("Failed to allocate scratch memory\n");
rc = -ENOMEM;
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index fb8fbc4..151fb21 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -106,6 +106,29 @@
struct video_device vdev;
};
+struct msm_vidc_fw {
+ void *cookie;
+};
+
+struct iommu_info {
+ u32 addr_range[2];
+ char name[64];
+ char ctx[64];
+ int domain;
+ int partition;
+};
+
+enum io_maps {
+ CP_MAP,
+ NS_MAP,
+ MAX_MAP
+};
+
+struct msm_vidc_resources {
+ struct msm_vidc_fw fw;
+ struct iommu_info io_map[MAX_MAP];
+};
+
struct msm_vidc_core {
struct list_head list;
struct mutex sync_lock;
@@ -121,6 +144,7 @@
u32 register_size;
u32 irq;
enum vidc_core_state state;
+ struct msm_vidc_resources resources;
struct completion completions[SYS_MSG_END - SYS_MSG_START + 1];
};
@@ -146,6 +170,7 @@
bool in_reconfig;
u32 reconfig_width;
u32 reconfig_height;
+ struct msm_smem *extradata_handle;
};
extern struct msm_vidc_drv *vidc_driver;
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index 0372f90..9052a63 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -23,7 +23,7 @@
#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
/*Workaround for virtio */
-#define HFI_VIRTIO_FW_BIAS 0x14f00000
+#define HFI_VIRTIO_FW_BIAS 0x0
struct hal_device_data hal_ctxt;
@@ -300,7 +300,8 @@
return 0;
}
-static int vidc_hal_alloc(void *mem, void *clnt, u32 size, u32 align, u32 flags)
+static int vidc_hal_alloc(void *mem, void *clnt, u32 size, u32 align, u32 flags,
+ int domain)
{
struct vidc_mem_addr *vmem;
struct msm_smem *alloc;
@@ -312,7 +313,7 @@
vmem = (struct vidc_mem_addr *)mem;
HAL_MSG_HIGH("start to alloc: size:%d, Flags: %d", size, flags);
- alloc = msm_smem_alloc(clnt, size, align, flags);
+ alloc = msm_smem_alloc(clnt, size, align, flags, domain, 0);
HAL_MSG_LOW("Alloc done");
if (!alloc) {
HAL_MSG_HIGH("Alloc fail in %s", __func__);
@@ -503,7 +504,7 @@
device->hal_client = NULL;
}
-static int vidc_hal_interface_queues_init(struct hal_device *dev)
+static int vidc_hal_interface_queues_init(struct hal_device *dev, int domain)
{
struct hfi_queue_table_header *q_tbl_hdr;
struct hfi_queue_header *q_hdr;
@@ -513,7 +514,7 @@
rc = vidc_hal_alloc((void *) &dev->iface_q_table,
dev->hal_client,
- VIDC_IFACEQ_TABLE_SIZE, 1, 0);
+ VIDC_IFACEQ_TABLE_SIZE, 1, 0, domain);
if (rc) {
HAL_MSG_ERROR("%s:iface_q_table_alloc_fail", __func__);
return -ENOMEM;
@@ -533,7 +534,7 @@
iface_q = &dev->iface_queues[i];
rc = vidc_hal_alloc((void *) &iface_q->q_array,
dev->hal_client, VIDC_IFACEQ_QUEUE_SIZE,
- 1, 0);
+ 1, 0, domain);
if (rc) {
HAL_MSG_ERROR("%s:iface_q_table_alloc[%d]_fail",
__func__, i);
@@ -592,7 +593,7 @@
return rc;
}
-int vidc_hal_core_init(void *device)
+int vidc_hal_core_init(void *device, int domain)
{
struct hfi_cmd_sys_init_packet pkt;
int rc = 0;
@@ -619,10 +620,10 @@
HAL_MSG_ERROR("Device_Virt_Address : 0x%x,"
"Register_Virt_Addr: 0x%x",
- (u32) dev->hal_data->device_base_addr,
+ dev->hal_data->device_base_addr,
(u32) dev->hal_data->register_base_addr);
- rc = vidc_hal_interface_queues_init(dev);
+ rc = vidc_hal_interface_queues_init(dev, domain);
if (rc) {
HAL_MSG_ERROR("failed to init queues");
rc = -ENOMEM;
@@ -1989,11 +1990,11 @@
list_for_each_safe(curr, next, &core.dev_head) {
device = list_entry(curr, struct hal_device, list);
if (device && device->hal_data->irq == irq &&
- (CONTAINS((u32)device->hal_data->
+ (CONTAINS(device->hal_data->
device_base_addr,
FIRMWARE_SIZE, fw_addr) ||
CONTAINS(fw_addr, FIRMWARE_SIZE,
- (u32)device->hal_data->
+ device->hal_data->
device_base_addr) ||
CONTAINS((u32)device->hal_data->
register_base_addr,
@@ -2007,12 +2008,12 @@
OVERLAPS(reg_addr, reg_size,
(u32)device->hal_data->
register_base_addr, reg_size) ||
- OVERLAPS((u32)device->hal_data->
+ OVERLAPS(device->hal_data->
device_base_addr,
FIRMWARE_SIZE, fw_addr,
FIRMWARE_SIZE) ||
OVERLAPS(fw_addr, FIRMWARE_SIZE,
- (u32)device->hal_data->
+ device->hal_data->
device_base_addr,
FIRMWARE_SIZE))) {
return 0;
@@ -2062,7 +2063,7 @@
struct hal_data *hal = NULL;
int rc = 0;
- if (device_id || !fw_base_addr || !reg_base || !reg_size ||
+ if (device_id || !reg_base || !reg_size ||
!irq || !callback) {
HAL_MSG_ERROR("Invalid Paramters");
return NULL;
@@ -2080,13 +2081,7 @@
return NULL;
}
hal->irq = irq;
- hal->device_base_addr =
- ioremap_nocache(fw_base_addr, FIRMWARE_SIZE);
- if (!hal->device_base_addr) {
- HAL_MSG_ERROR("could not map fw addr %d of size %d",
- fw_base_addr, FIRMWARE_SIZE);
- goto err_map;
- }
+ hal->device_base_addr = fw_base_addr;
hal->register_base_addr =
ioremap_nocache(reg_base, reg_size);
if (!hal->register_base_addr) {
diff --git a/drivers/media/video/msm_vidc/vidc_hal.h b/drivers/media/video/msm_vidc/vidc_hal.h
index 6c7e5df..8e7c3d3 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.h
+++ b/drivers/media/video/msm_vidc/vidc_hal.h
@@ -834,7 +834,7 @@
struct hal_data {
u32 irq;
- u8 *device_base_addr;
+ u32 device_base_addr;
u8 *register_base_addr;
};
diff --git a/drivers/media/video/msm_vidc/vidc_hal_api.h b/drivers/media/video/msm_vidc/vidc_hal_api.h
index 332bbac..c77ae12 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_api.h
+++ b/drivers/media/video/msm_vidc/vidc_hal_api.h
@@ -943,7 +943,7 @@
};
/* VIDC_HAL CORE API's */
-int vidc_hal_core_init(void *device);
+int vidc_hal_core_init(void *device, int domain);
int vidc_hal_core_release(void *device);
int vidc_hal_core_pc_prep(void *device);
int vidc_hal_core_set_resource(void *device,
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 98e2fd9..01e1201 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -1113,7 +1113,6 @@
{
struct vcap_client_data *c_data = to_client_data(file->private_data);
struct vcap_dev *dev = c_data->dev;
- unsigned long flags;
int rc;
unsigned long rate;
long rate_rc;
@@ -1126,14 +1125,14 @@
switch (c_data->op_mode) {
case VC_VCAP_OP:
- spin_lock_irqsave(&dev->dev_slock, flags);
+ mutex_lock(&dev->dev_mutex);
if (dev->vc_resource) {
pr_err("VCAP Err: %s: VC resource taken", __func__);
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
return -EBUSY;
}
dev->vc_resource = 1;
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
c_data->dev->vc_client = c_data;
@@ -1179,14 +1178,14 @@
goto free_res;
break;
case VP_VCAP_OP:
- spin_lock_irqsave(&dev->dev_slock, flags);
+ mutex_lock(&dev->dev_mutex);
if (dev->vp_resource) {
pr_err("VCAP Err: %s: VP resource taken", __func__);
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
return -EBUSY;
}
dev->vp_resource = 1;
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
c_data->dev->vp_client = c_data;
rate = 160000000;
@@ -1240,16 +1239,16 @@
goto s_on_deinit_nr_buf;
break;
case VC_AND_VP_VCAP_OP:
- spin_lock_irqsave(&dev->dev_slock, flags);
+ mutex_lock(&dev->dev_mutex);
if (dev->vc_resource || dev->vp_resource) {
pr_err("VCAP Err: %s: VC/VP resource taken",
__func__);
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
return -EBUSY;
}
dev->vc_resource = 1;
dev->vp_resource = 1;
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
c_data->dev->vc_client = c_data;
c_data->dev->vp_client = c_data;
@@ -1347,7 +1346,7 @@
s_on_deinit_m_buf:
deinit_motion_buf(c_data);
free_res:
- spin_lock_irqsave(&dev->dev_slock, flags);
+ mutex_lock(&dev->dev_mutex);
if (c_data->op_mode == VC_VCAP_OP) {
dev->vc_resource = 0;
c_data->dev->vc_client = NULL;
@@ -1360,7 +1359,7 @@
dev->vc_resource = 0;
dev->vp_resource = 0;
}
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
return rc;
}
@@ -1381,7 +1380,6 @@
int streamoff_work(struct vcap_client_data *c_data)
{
struct vcap_dev *dev = c_data->dev;
- unsigned long flags;
int rc;
switch (c_data->op_mode) {
case VC_VCAP_OP:
@@ -1390,14 +1388,14 @@
__func__);
return -EBUSY;
}
- spin_lock_irqsave(&dev->dev_slock, flags);
+ mutex_lock(&dev->dev_mutex);
if (!dev->vc_resource) {
pr_err("VCAP Err: %s: VC res not acquired", __func__);
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
return -EBUSY;
}
dev->vc_resource = 0;
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
rc = vb2_streamoff(&c_data->vc_vidq,
V4L2_BUF_TYPE_VIDEO_CAPTURE);
if (rc >= 0) {
@@ -1406,19 +1404,24 @@
}
return rc;
case VP_VCAP_OP:
+ if (!dev->vp_dummy_complete) {
+ pr_err("VCAP Err: %s: VP dummy read not complete",
+ __func__);
+ return -EINVAL;
+ }
if (c_data != dev->vp_client) {
pr_err("VCAP Err: %s: VP held by other client",
__func__);
return -EBUSY;
}
- spin_lock_irqsave(&dev->dev_slock, flags);
+ mutex_lock(&dev->dev_mutex);
if (!dev->vp_resource) {
pr_err("VCAP Err: %s: VP res not acquired", __func__);
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
return -EBUSY;
}
dev->vp_resource = 0;
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
rc = streamoff_validate_q(&c_data->vp_in_vidq);
if (rc < 0)
return rc;
@@ -1444,21 +1447,26 @@
atomic_set(&c_data->dev->vp_enabled, 0);
return rc;
case VC_AND_VP_VCAP_OP:
+ if (!dev->vp_dummy_complete) {
+ pr_err("VCAP Err: %s: VP dummy read not complete",
+ __func__);
+ return -EINVAL;
+ }
if (c_data != dev->vp_client || c_data != dev->vc_client) {
pr_err("VCAP Err: %s: VC/VP held by other client",
__func__);
return -EBUSY;
}
- spin_lock_irqsave(&dev->dev_slock, flags);
+ mutex_lock(&dev->dev_mutex);
if (!(dev->vc_resource || dev->vp_resource)) {
pr_err("VCAP Err: %s: VC or VP res not acquired",
__func__);
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
return -EBUSY;
}
dev->vc_resource = 0;
dev->vp_resource = 0;
- spin_unlock_irqrestore(&dev->dev_slock, flags);
+ mutex_unlock(&dev->dev_mutex);
rc = streamoff_validate_q(&c_data->vc_vidq);
if (rc < 0)
return rc;
@@ -1562,10 +1570,11 @@
struct vcap_dev *dev = video_drvdata(file);
struct vcap_client_data *c_data;
struct vb2_queue *q;
- unsigned long flags;
int ret;
- c_data = kzalloc(sizeof(*c_data), GFP_KERNEL);
if (!dev)
+ return -EINVAL;
+ c_data = kzalloc(sizeof(*c_data), GFP_KERNEL);
+ if (!c_data)
return -ENOMEM;
c_data->dev = dev;
@@ -1619,22 +1628,33 @@
v4l2_fh_init(&c_data->vfh, dev->vfd);
v4l2_fh_add(&c_data->vfh);
- spin_lock_irqsave(&dev->dev_slock, flags);
+ mutex_lock(&dev->dev_mutex);
atomic_inc(&dev->open_clients);
ret = atomic_read(&dev->open_clients);
- spin_unlock_irqrestore(&dev->dev_slock, flags);
if (ret == 1) {
ret = vcap_enable(dev, dev->ddev, 54860000);
if (ret < 0) {
pr_err("Err: %s: Power on vcap failed", __func__);
+ mutex_unlock(&dev->dev_mutex);
+ goto vcap_power_failed;
+ }
+
+ ret = vp_dummy_event(c_data);
+ if (ret < 0) {
+ pr_err("Err: %s: Dummy Event failed", __func__);
+ mutex_unlock(&dev->dev_mutex);
+ vcap_disable(dev);
goto vcap_power_failed;
}
}
+ mutex_unlock(&dev->dev_mutex);
file->private_data = &c_data->vfh;
return 0;
vcap_power_failed:
+ atomic_dec(&dev->open_clients);
+
v4l2_fh_del(&c_data->vfh);
v4l2_fh_exit(&c_data->vfh);
vb2_queue_release(&c_data->vp_out_vidq);
@@ -1651,7 +1671,6 @@
{
struct vcap_dev *dev = video_drvdata(file);
struct vcap_client_data *c_data = to_client_data(file->private_data);
- unsigned long flags;
int ret;
if (c_data == NULL)
@@ -1660,12 +1679,14 @@
if (c_data->streaming)
streamoff_work(c_data);
- spin_lock_irqsave(&dev->dev_slock, flags);
+ mutex_lock(&dev->dev_mutex);
atomic_dec(&dev->open_clients);
ret = atomic_read(&dev->open_clients);
- spin_unlock_irqrestore(&dev->dev_slock, flags);
- if (ret == 0)
+ mutex_unlock(&dev->dev_mutex);
+ if (ret == 0) {
vcap_disable(dev);
+ dev->vp_dummy_complete = false;
+ }
v4l2_fh_del(&c_data->vfh);
v4l2_fh_exit(&c_data->vfh);
vb2_queue_release(&c_data->vp_out_vidq);
@@ -1908,7 +1929,8 @@
atomic_set(&dev->vp_enabled, 0);
atomic_set(&dev->open_clients, 0);
dev->ddev = &pdev->dev;
- spin_lock_init(&dev->dev_slock);
+ mutex_init(&dev->dev_mutex);
+ init_waitqueue_head(&dev->vp_dummy_waitq);
vcap_disable(dev);
dprintk(1, "Exit probe succesfully");
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index be1b4ff..b73185d 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -261,6 +261,12 @@
int rc;
irq = readl_relaxed(VCAP_VP_INT_STATUS);
+ if (dev->vp_dummy_event == true) {
+ writel_relaxed(irq, VCAP_VP_INT_CLEAR);
+ dev->vp_dummy_complete = true;
+ wake_up(&dev->vp_dummy_waitq);
+ return IRQ_HANDLED;
+ }
if (irq & 0x02000000) {
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
@@ -434,6 +440,8 @@
return -ENOEXEC;
}
buf = &c_data->vid_vp_action.bufNR;
+ if (!buf)
+ return -ENOMEM;
frame_size = c_data->vp_in_fmt.width * c_data->vp_in_fmt.height;
if (c_data->vp_in_fmt.pixfmt == V4L2_PIX_FMT_NV16)
@@ -442,7 +450,7 @@
tot_size = frame_size / 2 * 3;
buf->vaddr = kzalloc(tot_size, GFP_KERNEL);
- if (!buf)
+ if (!buf->vaddr)
return -ENOMEM;
buf->paddr = virt_to_phys(buf->vaddr);
@@ -478,6 +486,74 @@
return;
}
+int vp_dummy_event(struct vcap_client_data *c_data)
+{
+ struct vcap_dev *dev = c_data->dev;
+ unsigned int width, height;
+ unsigned long paddr;
+ void *temp;
+ uint32_t reg;
+ int rc = 0;
+
+ dprintk(2, "%s: Start VP dummy event\n", __func__);
+ temp = kzalloc(0x1200, GFP_KERNEL);
+ if (!temp) {
+ pr_err("%s: Failed to alloc mem", __func__);
+ return -ENOMEM;
+ }
+ paddr = virt_to_phys(temp);
+
+ width = c_data->vp_out_fmt.width;
+ height = c_data->vp_out_fmt.height;
+
+ c_data->vp_out_fmt.width = 0x3F;
+ c_data->vp_out_fmt.height = 0x16;
+
+ config_vp_format(c_data);
+ writel_relaxed(paddr, VCAP_VP_T1_Y_BASE_ADDR);
+ writel_relaxed(paddr + 0x2C0, VCAP_VP_T1_C_BASE_ADDR);
+ writel_relaxed(paddr + 0x440, VCAP_VP_T2_Y_BASE_ADDR);
+ writel_relaxed(paddr + 0x700, VCAP_VP_T2_C_BASE_ADDR);
+ writel_relaxed(paddr + 0x880, VCAP_VP_OUT_Y_BASE_ADDR);
+ writel_relaxed(paddr + 0xB40, VCAP_VP_OUT_C_BASE_ADDR);
+ writel_iowmb(paddr + 0x1100, VCAP_VP_MOTION_EST_ADDR);
+ writel_relaxed(4 << 20 | 0x2 << 4, VCAP_VP_IN_CONFIG);
+ writel_relaxed(4 << 20 | 0x1 << 4, VCAP_VP_OUT_CONFIG);
+
+ dev->vp_dummy_event = true;
+
+ writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
+ writel_iowmb(0x00000000, VCAP_VP_CTRL);
+ writel_iowmb(0x00030000, VCAP_VP_CTRL);
+
+ enable_irq(dev->vpirq->start);
+ rc = wait_event_interruptible_timeout(dev->vp_dummy_waitq,
+ dev->vp_dummy_complete, msecs_to_jiffies(50));
+ if (!rc && !dev->vp_dummy_complete) {
+ pr_err("%s: VP dummy event timeout", __func__);
+ rc = -ETIME;
+ writel_iowmb(0x00000000, VCAP_VP_CTRL);
+
+ writel_iowmb(0x00000001, VCAP_VP_SW_RESET);
+ writel_iowmb(0x00000000, VCAP_VP_SW_RESET);
+ dev->vp_dummy_complete = false;
+ }
+
+ writel_relaxed(0x00000000, VCAP_VP_INTERRUPT_ENABLE);
+ disable_irq(dev->vpirq->start);
+ dev->vp_dummy_event = false;
+
+ reg = readl_relaxed(VCAP_OFFSET(0x0D94));
+ writel_relaxed(reg, VCAP_OFFSET(0x0D9C));
+
+ c_data->vp_out_fmt.width = width;
+ c_data->vp_out_fmt.height = height;
+ kfree(temp);
+
+ dprintk(2, "%s: Exit VP dummy event\n", __func__);
+ return rc;
+}
+
int kickoff_vp(struct vcap_client_data *c_data)
{
struct vcap_dev *dev;
diff --git a/drivers/media/video/vcap_vp.h b/drivers/media/video/vcap_vp.h
index 5415e54..5c32903 100644
--- a/drivers/media/video/vcap_vp.h
+++ b/drivers/media/video/vcap_vp.h
@@ -100,5 +100,6 @@
void deinit_nr_buf(struct vcap_client_data *c_data);
int kickoff_vp(struct vcap_client_data *c_data);
int continue_vp(struct vcap_client_data *c_data);
+int vp_dummy_event(struct vcap_client_data *c_data);
#endif
diff --git a/drivers/mfd/pm8821-irq.c b/drivers/mfd/pm8821-irq.c
index 2dcc792..ff68c08 100644
--- a/drivers/mfd/pm8821-irq.c
+++ b/drivers/mfd/pm8821-irq.c
@@ -22,6 +22,7 @@
#include <linux/mfd/pm8xxx/pm8821-irq.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <mach/mpm.h>
#define PM8821_TOTAL_IRQ_MASTERS 2
#define PM8821_BLOCKS_PER_MASTER 7
@@ -31,7 +32,7 @@
#define PM8821_IRQ_MASK_REG_OFFSET 0x08
#define SSBI_REG_ADDR_IRQ_MASTER0 0x30
#define SSBI_REG_ADDR_IRQ_MASTER1 0xB0
-
+#define MPM_PIN_FOR_8821_IRQ 7
#define SSBI_REG_ADDR_IRQ_IT_STATUS(master_base, block) (master_base + block)
/*
@@ -410,8 +411,12 @@
devirq, rc);
kfree(chip);
return ERR_PTR(rc);
- } else
+ } else{
irq_set_irq_wake(devirq, 1);
+ msm_mpm_set_pin_wake(MPM_PIN_FOR_8821_IRQ, 1);
+ msm_mpm_set_pin_type(MPM_PIN_FOR_8821_IRQ,
+ pdata->irq_trigger_flag);
+ }
}
return chip;
diff --git a/drivers/mfd/pm8xxx-spk.c b/drivers/mfd/pm8xxx-spk.c
index 297ddfa..2de70f4 100644
--- a/drivers/mfd/pm8xxx-spk.c
+++ b/drivers/mfd/pm8xxx-spk.c
@@ -162,7 +162,10 @@
val = pm8xxx_spk_read(PM8XXX_SPK_CTL1_REG_OFF);
if (val < 0)
return val;
- val |= (enable << 3);
+ if (enable)
+ val |= (1 << 3);
+ else
+ val &= ~(1 << 3);
ret = pm8xxx_spk_write(PM8XXX_SPK_CTL1_REG_OFF, val);
if (!ret)
ret = pm8xxx_spk_bank_write(addr, 6, PWM_EN_MASK);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index d833707..08f5ab9 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -20,6 +20,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -2092,7 +2093,14 @@
if (mrq->data && (mrq->data->flags & MMC_DATA_WRITE)) {
if (is_auto_prog_done(host)) {
- if (!mrq->stop)
+ /*
+ * Auto-prog done will be enabled for following cases:
+ * mrq->sbc | mrq->stop
+ * _____________|________________
+ * True | Don't care
+ * False | False (CMD24, ACMD25 use case)
+ */
+ if (mrq->sbc || !mrq->stop)
host->curr.wait_for_auto_prog_done = true;
} else {
if ((mrq->cmd->opcode == SD_IO_RW_EXTENDED) ||
@@ -2529,6 +2537,12 @@
curr = host->plat->pin_data->gpio_data;
for (i = 0; i < curr->size; i++) {
+ if (!gpio_is_valid(curr->gpio[i].no)) {
+ rc = -EINVAL;
+ pr_err("%s: Invalid gpio = %d\n",
+ mmc_hostname(host->mmc), curr->gpio[i].no);
+ goto free_gpios;
+ }
if (enable) {
if (curr->gpio[i].is_always_on &&
curr->gpio[i].is_enabled)
@@ -2553,7 +2567,7 @@
goto out;
free_gpios:
- for (; i >= 0; i--) {
+ for (i--; i >= 0; i--) {
gpio_free(curr->gpio[i].no);
curr->gpio[i].is_enabled = false;
}
@@ -4778,6 +4792,298 @@
spin_unlock_irqrestore(&host->lock, flags);
}
+/*
+ * msmsdcc_dt_get_array - Wrapper fn to read an array of 32 bit integers
+ *
+ * @dev: device node from which the property value is to be read.
+ * @prop_name: name of the property to be searched.
+ * @out_array: filled array returned to caller
+ * @len: filled array size returned to caller
+ * @size: expected size of the array
+ *
+ * If expected "size" doesn't match with "len" an error is returned. If
+ * expected size is zero, the length of actual array is returned provided
+ * return value is zero.
+ *
+ * RETURNS:
+ * zero on success, negative error if failed.
+ */
+static int msmsdcc_dt_get_array(struct device *dev, const char *prop_name,
+ u32 **out_array, int *len, int size)
+{
+ int ret = 0;
+ u32 *array = NULL;
+ struct device_node *np = dev->of_node;
+
+ if (of_get_property(np, prop_name, len)) {
+ size_t sz;
+ sz = *len = *len / sizeof(*array);
+
+ if (sz > 0 && !(size > 0 && (sz != size))) {
+ array = devm_kzalloc(dev, sz * sizeof(*array),
+ GFP_KERNEL);
+ if (!array) {
+ dev_err(dev, "%s: no memory\n", prop_name);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = of_property_read_u32_array(np, prop_name,
+ array, sz);
+ if (ret < 0) {
+ dev_err(dev, "%s: error reading array %d\n",
+ prop_name, ret);
+ goto out;
+ }
+ } else {
+ dev_err(dev, "%s invalid size\n", prop_name);
+ ret = -EINVAL;
+ goto out;
+ }
+ } else {
+ dev_err(dev, "%s not specified\n", prop_name);
+ ret = -EINVAL;
+ goto out;
+ }
+ *out_array = array;
+out:
+ if (ret)
+ *len = 0;
+ return ret;
+}
+
+static int msmsdcc_dt_get_pad_pull_info(struct device *dev, int id,
+ struct msm_mmc_pad_pull_data **pad_pull_data)
+{
+ int ret = 0, base = 0, len, i;
+ u32 *tmp;
+ struct msm_mmc_pad_pull_data *pull_data;
+ struct msm_mmc_pad_pull *pull;
+
+ switch (id) {
+ case 1:
+ base = TLMM_PULL_SDC1_CLK;
+ break;
+ case 2:
+ base = TLMM_PULL_SDC2_CLK;
+ break;
+ case 3:
+ base = TLMM_PULL_SDC3_CLK;
+ break;
+ case 4:
+ base = TLMM_PULL_SDC4_CLK;
+ break;
+ default:
+ dev_err(dev, "%s: Invalid slot id\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ pull_data = devm_kzalloc(dev, sizeof(struct msm_mmc_pad_pull_data),
+ GFP_KERNEL);
+ if (!pull_data) {
+ dev_err(dev, "No memory msm_mmc_pad_pull_data\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ pull_data->size = 3; /* array size for clk, cmd, data */
+
+ /* Allocate on, off configs for clk, cmd, data */
+ pull = devm_kzalloc(dev, 2 * pull_data->size *\
+ sizeof(struct msm_mmc_pad_pull), GFP_KERNEL);
+ if (!pull) {
+ dev_err(dev, "No memory for msm_mmc_pad_pull\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ pull_data->on = pull;
+ pull_data->off = pull + pull_data->size;
+
+ ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-pull-on",
+ &tmp, &len, pull_data->size);
+ if (!ret) {
+ for (i = 0; i < len; i++) {
+ pull_data->on[i].no = base + i;
+ pull_data->on[i].val = tmp[i];
+ dev_dbg(dev, "%s: val[%d]=0x%x\n", __func__,
+ i, pull_data->on[i].val);
+ }
+ } else {
+ goto err;
+ }
+
+ ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-pull-off",
+ &tmp, &len, pull_data->size);
+ if (!ret) {
+ for (i = 0; i < len; i++) {
+ pull_data->off[i].no = base + i;
+ pull_data->off[i].val = tmp[i];
+ dev_dbg(dev, "%s: val[%d]=0x%x\n", __func__,
+ i, pull_data->off[i].val);
+ }
+ } else {
+ goto err;
+ }
+
+ *pad_pull_data = pull_data;
+err:
+ return ret;
+}
+
+static int msmsdcc_dt_get_pad_drv_info(struct device *dev, int id,
+ struct msm_mmc_pad_drv_data **pad_drv_data)
+{
+ int ret = 0, base = 0, len, i;
+ u32 *tmp;
+ struct msm_mmc_pad_drv_data *drv_data;
+ struct msm_mmc_pad_drv *drv;
+
+ switch (id) {
+ case 1:
+ base = TLMM_HDRV_SDC1_CLK;
+ break;
+ case 2:
+ base = TLMM_HDRV_SDC2_CLK;
+ break;
+ case 3:
+ base = TLMM_HDRV_SDC3_CLK;
+ break;
+ case 4:
+ base = TLMM_HDRV_SDC4_CLK;
+ break;
+ default:
+ dev_err(dev, "%s: Invalid slot id\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ drv_data = devm_kzalloc(dev, sizeof(struct msm_mmc_pad_drv_data),
+ GFP_KERNEL);
+ if (!drv_data) {
+ dev_err(dev, "No memory for msm_mmc_pad_drv_data\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ drv_data->size = 3; /* array size for clk, cmd, data */
+
+ /* Allocate on, off configs for clk, cmd, data */
+ drv = devm_kzalloc(dev, 2 * drv_data->size *\
+ sizeof(struct msm_mmc_pad_drv), GFP_KERNEL);
+ if (!drv) {
+ dev_err(dev, "No memory msm_mmc_pad_drv\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ drv_data->on = drv;
+ drv_data->off = drv + drv_data->size;
+
+ ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-drv-on",
+ &tmp, &len, drv_data->size);
+ if (!ret) {
+ for (i = 0; i < len; i++) {
+ drv_data->on[i].no = base + i;
+ drv_data->on[i].val = tmp[i];
+ dev_dbg(dev, "%s: val[%d]=0x%x\n", __func__,
+ i, drv_data->on[i].val);
+ }
+ } else {
+ goto err;
+ }
+
+ ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-drv-off",
+ &tmp, &len, drv_data->size);
+ if (!ret) {
+ for (i = 0; i < len; i++) {
+ drv_data->off[i].no = base + i;
+ drv_data->off[i].val = tmp[i];
+ dev_dbg(dev, "%s: val[%d]=0x%x\n", __func__,
+ i, drv_data->off[i].val);
+ }
+ } else {
+ goto err;
+ }
+
+ *pad_drv_data = drv_data;
+err:
+ return ret;
+}
+
+static int msmsdcc_dt_parse_gpio_info(struct device *dev,
+ struct mmc_platform_data *pdata)
+{
+ int ret = 0, id = 0, cnt, i;
+ struct msm_mmc_pin_data *pin_data;
+ struct device_node *np = dev->of_node;
+
+ pin_data = devm_kzalloc(dev, sizeof(*pin_data), GFP_KERNEL);
+ if (!pin_data) {
+ dev_err(dev, "No memory for pin_data\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ cnt = of_gpio_count(np);
+ if (cnt > 0) {
+ pin_data->is_gpio = true;
+
+ pin_data->gpio_data = devm_kzalloc(dev,
+ sizeof(struct msm_mmc_gpio_data), GFP_KERNEL);
+ if (!pin_data->gpio_data) {
+ dev_err(dev, "No memory for gpio_data\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ pin_data->gpio_data->size = cnt;
+ pin_data->gpio_data->gpio = devm_kzalloc(dev,
+ cnt * sizeof(struct msm_mmc_gpio), GFP_KERNEL);
+ if (!pin_data->gpio_data->gpio) {
+ dev_err(dev, "No memory for gpio\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ const char *name = NULL;
+ char result[32];
+ pin_data->gpio_data->gpio[i].no = of_get_gpio(np, i);
+ of_property_read_string_index(np,
+ "qcom,sdcc-gpio-names", i, &name);
+
+ snprintf(result, 32, "%s-%s",
+ dev_name(dev), name ? name : "?");
+ pin_data->gpio_data->gpio[i].name = result;
+ dev_dbg(dev, "%s: gpio[%s] = %d\n", __func__,
+ pin_data->gpio_data->gpio[i].name,
+ pin_data->gpio_data->gpio[i].no);
+ }
+ } else {
+ pin_data->pad_data = devm_kzalloc(dev,
+ sizeof(struct msm_mmc_pad_data), GFP_KERNEL);
+ if (!pin_data->pad_data) {
+ dev_err(dev, "No memory for pin_data->pad_data\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ of_property_read_u32(np, "cell-index", &id);
+
+ ret = msmsdcc_dt_get_pad_pull_info(dev, id,
+ &pin_data->pad_data->pull);
+ if (ret)
+ goto err;
+ ret = msmsdcc_dt_get_pad_drv_info(dev, id,
+ &pin_data->pad_data->drv);
+ if (ret)
+ goto err;
+ }
+
+ pdata->pin_data = pin_data;
+err:
+ if (ret)
+ dev_err(dev, "%s failed with err %d\n", __func__, ret);
+ return ret;
+}
+
#define MAX_PROP_SIZE 32
static int msmsdcc_dt_parse_vreg_info(struct device *dev,
struct msm_mmc_reg_data **vreg_data, const char *vreg_name)
@@ -4867,29 +5173,10 @@
pdata->mmc_bus_width = 0;
}
- if (of_get_property(np, "qcom,sdcc-sup-voltages", &sup_volt_len)) {
- size_t sz;
- sz = sup_volt_len / sizeof(*sup_voltages);
- if (sz > 0) {
- sup_voltages = devm_kzalloc(dev,
- sz * sizeof(*sup_voltages), GFP_KERNEL);
- if (!sup_voltages) {
- dev_err(dev, "No memory for supported voltage\n");
- goto err;
- }
-
- ret = of_property_read_u32_array(np,
- "qcom,sdcc-sup-voltages", sup_voltages, sz);
- if (ret < 0) {
- dev_err(dev, "error while reading voltage"
- "ranges %d\n", ret);
- goto err;
- }
- } else {
- dev_err(dev, "No supported voltages\n");
- goto err;
- }
- for (i = 0; i < sz; i += 2) {
+ ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-sup-voltages",
+ &sup_voltages, &sup_volt_len, 0);
+ if (!ret) {
+ for (i = 0; i < sup_volt_len; i += 2) {
u32 mask;
mask = mmc_vddrange_to_ocrmask(sup_voltages[i],
@@ -4899,37 +5186,13 @@
pdata->ocr_mask |= mask;
}
dev_dbg(dev, "OCR mask=0x%x\n", pdata->ocr_mask);
- } else {
- dev_err(dev, "Supported voltage range not specified\n");
}
- if (of_get_property(np, "qcom,sdcc-clk-rates", &clk_table_len)) {
- size_t sz;
- sz = clk_table_len / sizeof(*clk_table);
-
- if (sz > 0) {
- clk_table = devm_kzalloc(dev, sz * sizeof(*clk_table),
- GFP_KERNEL);
- if (!clk_table) {
- dev_err(dev, "No memory for clock table\n");
- goto err;
- }
-
- ret = of_property_read_u32_array(np,
- "qcom,sdcc-clk-rates", clk_table, sz);
- if (ret < 0) {
- dev_err(dev, "error while reading clk"
- "table %d\n", ret);
- goto err;
- }
- } else {
- dev_err(dev, "clk_table not specified\n");
- goto err;
- }
+ ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-clk-rates",
+ &clk_table, &clk_table_len, 0);
+ if (!ret) {
pdata->sup_clk_table = clk_table;
- pdata->sup_clk_cnt = sz;
- } else {
- dev_err(dev, "Supported clock rates not specified\n");
+ pdata->sup_clk_cnt = clk_table_len;
}
pdata->vreg_data = devm_kzalloc(dev,
@@ -4947,6 +5210,9 @@
&pdata->vreg_data->vdd_io_data, "vdd-io"))
goto err;
+ if (msmsdcc_dt_parse_gpio_info(dev, pdata))
+ goto err;
+
len = of_property_count_strings(np, "qcom,sdcc-bus-speed-mode");
for (i = 0; i < len; i++) {
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index 36414e0..8cef99e 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -2778,6 +2778,9 @@
}
if (slc->def > 0)
slc->def--;
+ /* Disconnect source port to free it up */
+ if (SLIM_HDL_TO_LA(slc->srch) == sb->laddr)
+ slc->srch = 0;
if (slc->def == 0)
ret = add_pending_ch(&sb->mark_removal, chan);
if (ret)
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 083ed19..1904706 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -174,7 +174,7 @@
#define UARTDM_TX_BUF_SIZE UART_XMIT_SIZE
#define UARTDM_RX_BUF_SIZE 512
#define RETRY_TIMEOUT 5
-#define UARTDM_NR 2
+#define UARTDM_NR 5
static struct dentry *debug_base;
static struct msm_hs_port q_uart_port[UARTDM_NR];
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index b6bf47d..9f301fe 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1858,6 +1858,9 @@
/* EDID_BLOCK_SIZE[0x80] Each page size in the EDID ROM */
uint8 edid_buf[0x80 * 4];
+ external_common_state->pt_scan_info = 0;
+ external_common_state->it_scan_info = 0;
+ external_common_state->ce_scan_info = 0;
external_common_state->preferred_video_format = 0;
external_common_state->present_3d = 0;
memset(&external_common_state->disp_mode_list, 0,
@@ -1974,13 +1977,15 @@
bool hdmi_common_get_video_format_from_drv_data(struct msm_fb_data_type *mfd)
{
- uint32 format;
+ uint32 format = HDMI_VFRMT_1920x1080p60_16_9;
struct fb_var_screeninfo *var = &mfd->fbi->var;
bool changed = TRUE;
if (var->reserved[2]) {
format = var->reserved[2]-1;
DEV_DBG("reserved format is %d\n", format);
+ } else if (hdmi_prim_resolution) {
+ format = hdmi_prim_resolution - 1;
} else {
DEV_DBG("detecting resolution from %dx%d use var->reserved[3]"
" to specify mode", mfd->var_xres, mfd->var_yres);
@@ -1995,15 +2000,33 @@
: HDMI_VFRMT_720x576p50_16_9;
break;
case 1280:
- format = HDMI_VFRMT_1280x720p60_16_9;
+ if (mfd->var_frame_rate == 50000)
+ format = HDMI_VFRMT_1280x720p50_16_9;
+ else
+ format = HDMI_VFRMT_1280x720p60_16_9;
break;
case 1440:
- format = (mfd->var_yres == 480)
+ format = (mfd->var_yres == 240) /* interlaced has half
+ of y res.
+ */
? HDMI_VFRMT_1440x480i60_16_9
: HDMI_VFRMT_1440x576i50_16_9;
break;
case 1920:
- format = HDMI_VFRMT_1920x1080p60_16_9;
+ if (mfd->var_yres == 540) {/* interlaced */
+ format = HDMI_VFRMT_1920x1080i60_16_9;
+ } else if (mfd->var_yres == 1080) {
+ if (mfd->var_frame_rate == 50000)
+ format = HDMI_VFRMT_1920x1080p50_16_9;
+ else if (mfd->var_frame_rate == 24000)
+ format = HDMI_VFRMT_1920x1080p24_16_9;
+ else if (mfd->var_frame_rate == 25000)
+ format = HDMI_VFRMT_1920x1080p25_16_9;
+ else if (mfd->var_frame_rate == 30000)
+ format = HDMI_VFRMT_1920x1080p30_16_9;
+ else
+ format = HDMI_VFRMT_1920x1080p60_16_9;
+ }
break;
}
}
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
index 57c0804..43a8794 100644
--- a/drivers/video/msm/external_common.h
+++ b/drivers/video/msm/external_common.h
@@ -112,6 +112,8 @@
#define HDMI_VFRMT_MAX 59
#define HDMI_VFRMT_FORCE_32BIT 0x7FFFFFFF
+extern int ext_resolution;
+
struct hdmi_disp_mode_timing_type {
uint32 video_format;
uint32 active_h;
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index f919ad0..4a1427d 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -4742,7 +4742,14 @@
}
external_common_state = &hdmi_msm_state->common;
- external_common_state->video_resolution = HDMI_VFRMT_1920x1080p30_16_9;
+
+ if (hdmi_prim_display && hdmi_prim_resolution)
+ external_common_state->video_resolution =
+ hdmi_prim_resolution - 1;
+ else
+ external_common_state->video_resolution =
+ HDMI_VFRMT_1920x1080p60_16_9;
+
#ifdef CONFIG_FB_MSM_HDMI_3D
external_common_state->switch_3d = hdmi_msm_switch_3d;
#endif
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 3fd51ba..184c5ce 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -88,6 +88,7 @@
extern struct mdp_ccs mdp_ccs_yuv2rgb ;
extern struct mdp_ccs mdp_ccs_rgb2yuv ;
extern unsigned char hdmi_prim_display;
+extern unsigned char hdmi_prim_resolution;
/*
* MDP Image Structure
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index d045e69..703d65d 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2558,17 +2558,19 @@
struct msm_fb_data_type *mfd, uint32 perf_level)
{
u32 clk_rate = mfd->panel_info.clk_rate;
- u32 pull_mode = 0, use_blt = 0;
+ u32 blt_chq_req = 0, use_blt = 0;
- if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
+ if ((mfd->panel_info.type == MIPI_VIDEO_PANEL) ||
+ (mfd->panel_info.type == MIPI_CMD_PANEL))
clk_rate = (&mfd->panel_info.mipi)->dsi_pclk_rate;
if ((mfd->panel_info.type == LCDC_PANEL) ||
(mfd->panel_info.type == MIPI_VIDEO_PANEL) ||
- (mfd->panel_info.type == DTV_PANEL))
- pull_mode = 1;
+ (mfd->panel_info.type == DTV_PANEL) ||
+ (mfd->panel_info.type == MIPI_CMD_PANEL))
+ blt_chq_req = 1;
- if (pull_mode && (req->src_rect.h > req->dst_rect.h ||
+ if (blt_chq_req && (req->src_rect.h > req->dst_rect.h ||
req->src_rect.w > req->dst_rect.w)) {
if (mdp4_overlay_validate_downscale(req, mfd, perf_level,
clk_rate))
@@ -2798,10 +2800,15 @@
mdp4_mixer_stage_down(pipe);
if (pipe->mixer_num == MDP4_MIXER0) {
+ mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
+ mdp4_overlay_update_blt_mode(mfd);
#ifdef CONFIG_FB_MSM_MIPI_DSI
if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
- if (mfd->panel_power_on)
+ if (mfd->panel_power_on) {
mdp4_dsi_cmd_overlay_restore();
+ mdp4_dsi_cmd_dma_busy_wait(mfd);
+ mdp4_dsi_blt_dmap_busy_wait(mfd);
+ }
} else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
if (mfd->panel_power_on)
@@ -2810,8 +2817,11 @@
}
#else
if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
- if (mfd->panel_power_on)
+ if (mfd->panel_power_on) {
mdp4_mddi_overlay_restore();
+ mdp4_mddi_dma_busy_wait(mfd);
+ mdp4_mddi_blt_dmap_busy_wait(mfd);
+ }
}
#endif
else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
@@ -2819,8 +2829,6 @@
if (mfd->panel_power_on)
mdp4_overlay_lcdc_vsync_push(mfd, pipe);
}
- mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
- mdp4_overlay_update_blt_mode(mfd);
if (!mfd->use_ov0_blt)
mdp4_free_writeback_buf(mfd, MDP4_MIXER0);
} else { /* mixer1, DTV, ATV */
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index b90812f..b9d6037 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -698,11 +698,7 @@
struct mdp4_overlay_pipe *pipe;
if (!mfd->panel_power_on)
return;
- if (!dtv_pipe) {
- pr_debug("%s: no mixer1 base layer pipe allocated!\n",
- __func__);
- return;
- }
+
mutex_lock(&mfd->dma->ov_mutex);
if (dtv_pipe == NULL) {
if (mdp4_overlay_dtv_set(mfd, NULL)) {
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 5f58af7..176f56b 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -193,6 +193,7 @@
static struct msm_fb_platform_data *msm_fb_pdata;
unsigned char hdmi_prim_display;
+unsigned char hdmi_prim_resolution;
int msm_fb_detect_client(const char *name)
{
@@ -213,6 +214,8 @@
if (!strncmp((char *)msm_fb_pdata->prim_panel_name,
"hdmi_msm", len))
hdmi_prim_display = 1;
+ hdmi_prim_resolution =
+ msm_fb_pdata->ext_resolution;
return 0;
} else {
ret = -EPERM;
@@ -639,6 +642,12 @@
struct msm_fb_panel_data *pdata = NULL;
int ret = 0;
+ if (hdmi_prim_display) {
+ MSM_FB_INFO("%s: hdmi primary handles early suspend only\n",
+ __func__);
+ return 0;
+ }
+
if ((!mfd) || (mfd->key != MFD_KEY))
return 0;
@@ -664,6 +673,12 @@
struct msm_fb_panel_data *pdata = NULL;
int ret = 0;
+ if (hdmi_prim_display) {
+ MSM_FB_INFO("%s: hdmi primary handles early resume only\n",
+ __func__);
+ return 0;
+ }
+
if ((!mfd) || (mfd->key != MFD_KEY))
return 0;
@@ -688,7 +703,8 @@
.runtime_suspend = msm_fb_runtime_suspend,
.runtime_resume = msm_fb_runtime_resume,
.runtime_idle = msm_fb_runtime_idle,
-#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL) && \
+ !defined(CONFIG_FB_MSM_HDMI_AS_PRIMARY))
.suspend = msm_fb_ext_suspend,
.resume = msm_fb_ext_resume,
#endif
@@ -722,7 +738,9 @@
static void msmfb_early_suspend(struct early_suspend *h)
{
struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
- early_suspend);
+ early_suspend);
+ struct msm_fb_panel_data *pdata = NULL;
+
#if defined(CONFIG_FB_MSM_MDP303)
/*
* For MDP with overlay, set framebuffer with black pixels
@@ -740,12 +758,37 @@
}
#endif
msm_fb_suspend_sub(mfd);
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+ if (hdmi_prim_display &&
+ (mfd->panel_info.type == HDMI_PANEL ||
+ mfd->panel_info.type == DTV_PANEL)) {
+ /* Turn off the HPD circuitry */
+ if (pdata->power_ctrl) {
+ MSM_FB_INFO("%s: Turning off HPD circuitry\n",
+ __func__);
+ pdata->power_ctrl(FALSE);
+ }
+ }
}
static void msmfb_early_resume(struct early_suspend *h)
{
struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
- early_suspend);
+ early_suspend);
+ struct msm_fb_panel_data *pdata = NULL;
+
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+ if (hdmi_prim_display &&
+ (mfd->panel_info.type == HDMI_PANEL ||
+ mfd->panel_info.type == DTV_PANEL)) {
+ /* Turn on the HPD circuitry */
+ if (pdata->power_ctrl) {
+ MSM_FB_INFO("%s: Turning on HPD circuitry\n", __func__);
+ pdata->power_ctrl(TRUE);
+ }
+ }
+
msm_fb_resume_sub(mfd);
}
#endif
@@ -1432,7 +1475,7 @@
ret = 0;
#ifdef CONFIG_HAS_EARLYSUSPEND
- if (mfd->panel_info.type != DTV_PANEL) {
+ if (hdmi_prim_display || mfd->panel_info.type != DTV_PANEL) {
mfd->early_suspend.suspend = msmfb_early_suspend;
mfd->early_suspend.resume = msmfb_early_resume;
mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8aeadf6..6af2a3e 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -645,6 +645,11 @@
*(.security_initcall.init) \
VMLINUX_SYMBOL(__security_initcall_end) = .;
+#define COMPAT_EXPORTS \
+ VMLINUX_SYMBOL(__compat_exports_start) = .; \
+ *(.exportcompat.init) \
+ VMLINUX_SYMBOL(__compat_exports_end) = .;
+
#ifdef CONFIG_BLK_DEV_INITRD
#define INIT_RAM_FS \
. = ALIGN(4); \
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 80e1bf8..ae81dcd 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -210,6 +210,9 @@
#define MSM_CAM_IOCTL_UNSET_MCTL_SDEV \
_IOW(MSM_CAM_IOCTL_MAGIC, 59, struct msm_mctl_set_sdev_data *)
+#define MSM_CAM_IOCTL_GET_INST_HANDLE \
+ _IOR(MSM_CAM_IOCTL_MAGIC, 60, uint32_t *)
+
struct msm_stats_reqbuf {
int num_buf; /* how many buffers requested */
int stats_type; /* stats type */
@@ -340,6 +343,7 @@
struct msm_pp_frame_mp mp[MAX_PLANES];
};
int node_type;
+ uint32_t inst_handle;
};
struct msm_cam_evt_divert_frame {
@@ -773,7 +777,7 @@
#define MSM_V4L2_PID_CTRL_CMD (V4L2_CID_PRIVATE_BASE+13)
#define MSM_V4L2_PID_EVT_SUB_INFO (V4L2_CID_PRIVATE_BASE+14)
#define MSM_V4L2_PID_STROBE_FLASH (V4L2_CID_PRIVATE_BASE+15)
-#define MSM_V4L2_PID_MMAP_ENTRY (V4L2_CID_PRIVATE_BASE+16)
+#define MSM_V4L2_PID_INST_HANDLE (V4L2_CID_PRIVATE_BASE+16)
#define MSM_V4L2_PID_MMAP_INST (V4L2_CID_PRIVATE_BASE+17)
#define MSM_V4L2_PID_PP_PLANE_INFO (V4L2_CID_PRIVATE_BASE+18)
#define MSM_V4L2_PID_MAX MSM_V4L2_PID_PP_PLANE_INFO
@@ -1629,7 +1633,7 @@
uint8_t num_planes;
struct plane_data plane[MAX_PLANES];
uint32_t sp_y_offset;
- uint8_t vpe_can_use;
+ uint32_t inst_handle;
};
#define QCAMERA_NAME "qcamera"
@@ -1682,6 +1686,9 @@
#define MSM_CAM_V4L2_IOCTL_PRIVATE_S_CTRL \
_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_camera_v4l2_ioctl_t)
+#define MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct msm_camera_v4l2_ioctl_t)
+
#define VIDIOC_MSM_VPE_INIT \
_IO('V', BASE_VIDIOC_PRIVATE + 15)
@@ -1862,4 +1869,38 @@
#define V4L2_EVENT_CPP_FRAME_DONE (V4L2_EVENT_PRIVATE_START + 0)
+/* Instance Handle - inst_handle
+ * Data bundle containing the information about where
+ * to get a buffer for a particular camera instance.
+ * This is a bitmask containing the following data:
+ * Buffer Handle Bitmask:
+ * ------------------------------------
+ * Bits : Purpose
+ * ------------------------------------
+ * 31 - 24 : Reserved.
+ * 23 : is Image mode valid?
+ * 22 - 16 : Image mode.
+ * 15 : is MCTL PP inst idx valid?
+ * 14 - 8 : MCTL PP inst idx.
+ * 7 : is Video inst idx valid?
+ * 6 - 0 : Video inst idx.
+ */
+#define CLR_IMG_MODE(handle) (handle &= 0xFF00FFFF)
+#define SET_IMG_MODE(handle, data) \
+ (handle |= ((0x1 << 23) | ((data & 0x7F) << 16)))
+#define GET_IMG_MODE(handle) \
+ ((handle & 0x800000) ? ((handle & 0x7F0000) >> 16) : 0xFF)
+
+#define CLR_MCTLPP_INST_IDX(handle) (handle &= 0xFFFF00FF)
+#define SET_MCTLPP_INST_IDX(handle, data) \
+ (handle |= ((0x1 << 15) | ((data & 0x7F) << 8)))
+#define GET_MCTLPP_INST_IDX(handle) \
+ ((handle & 0x8000) ? ((handle & 0x7F00) >> 8) : 0xFF)
+
+#define CLR_VIDEO_INST_IDX(handle) (handle &= 0xFFFFFF00)
+#define GET_VIDEO_INST_IDX(handle) \
+ ((handle & 0x80) ? (handle & 0x7F) : 0xFF)
+#define SET_VIDEO_INST_IDX(handle, data) \
+ (handle |= (0x1 << 7) | (data & 0x7F))
+
#endif /* __LINUX_MSM_CAMERA_H */
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 1f3527b..3df6ded 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -336,7 +336,7 @@
#define VFE_OUTPUTS_RDI1 BIT(12)
struct msm_frame_info {
- uint32_t image_mode;
+ uint32_t inst_handle;
uint32_t path;
};
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index f7d1e6b..9719aa6 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -158,10 +158,13 @@
atomic_t vc_enabled;
atomic_t vp_enabled;
- spinlock_t dev_slock;
+ struct mutex dev_mutex;
atomic_t open_clients;
bool vc_resource;
bool vp_resource;
+ bool vp_dummy_event;
+ bool vp_dummy_complete;
+ wait_queue_head_t vp_dummy_waitq;
struct workqueue_struct *vcap_wq;
struct vp_work_t vp_work;
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index c1906e4..d0ec4f3 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -118,10 +118,6 @@
/* lockup suspected: */
if (print_once) {
print_once = 0;
- printk(KERN_EMERG "BUG: spinlock lockup on CPU#%d, "
- "%s/%d, %ps\n",
- raw_smp_processor_id(), current->comm,
- task_pid_nr(current), lock);
spin_dump(lock, "lockup");
#ifdef CONFIG_SMP
trigger_all_cpu_backtrace();
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 6bbb34b..276ff71 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -711,10 +711,6 @@
invalid_key:
hcon->sec_req = FALSE;
- /* Switch to Pairing Connection Parameters */
- hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL, SMP_MAX_CONN_INTERVAL,
- SMP_MAX_CONN_LATENCY, SMP_SUPERVISION_TIMEOUT);
-
skb_pull(skb, sizeof(*rp));
memset(&cp, 0, sizeof(cp));
@@ -776,11 +772,6 @@
if (hcon->link_mode & HCI_LM_MASTER) {
struct smp_cmd_pairing cp;
- /* Switch to Pairing Connection Parameters */
- hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL,
- SMP_MAX_CONN_INTERVAL, SMP_MAX_CONN_LATENCY,
- SMP_SUPERVISION_TIMEOUT);
-
build_pairing_cmd(conn, &cp, NULL, authreq);
hcon->preq[0] = SMP_CMD_PAIRING_REQ;
memcpy(&hcon->preq[1], &cp, sizeof(cp));
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 70d9fa9..bbf1b89 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -848,14 +848,14 @@
if (enable) {
sitar->adc_count++;
- snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS, 0xE0, 0xE0);
-
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL,
+ 0x02, 0x02);
} else {
sitar->adc_count--;
if (!sitar->adc_count) {
if (!sitar->mbhc_polling_active)
- snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS,
- 0xE0, 0x0);
+ snd_soc_update_bits(codec,
+ SITAR_A_CDC_CLK_OTHR_CTL, 0xE0, 0x0);
}
}
}
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 3164a9b..68892c1 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -7312,14 +7312,13 @@
}
EXPORT_SYMBOL_GPL(tabla_hs_detect);
-static unsigned long slimbus_value;
-
static irqreturn_t tabla_slimbus_irq(int irq, void *data)
{
struct tabla_priv *priv = data;
struct snd_soc_codec *codec = priv->codec;
struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
int i, j, port_id, k, ch_mask_temp;
+ unsigned long slimbus_value;
u8 val;
for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
@@ -7352,7 +7351,8 @@
}
}
wcd9xxx_interface_reg_write(codec->control_data,
- TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
+ TABLA_SLIM_PGD_PORT_INT_CLR0 + i, slimbus_value);
+ val = 0x0;
}
return IRQ_HANDLED;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index b110250..9c57161 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -678,6 +678,21 @@
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
},
{
+ .name = "MSM8974 Compr",
+ .stream_name = "COMPR",
+ .cpu_dai_name = "MultiMedia4",
+ .platform_name = "msm-compr-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+ },
+ {
.name = "AUXPCM Hostless",
.stream_name = "AUXPCM Hostless",
.cpu_dai_name = "AUXPCM_HOSTLESS",
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 1cf32aa..3791f24 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -2344,6 +2344,9 @@
/* send stop voice cmd */
voice_send_stop_voice_cmd(v);
+ /* Clear mute setting */
+ v->dev_tx.mute = common.default_mute_val;
+
/* detach VOCPROC and wait for response from mvm */
mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
@@ -3106,7 +3109,9 @@
v->dev_tx.mute = mute;
- if (v->voc_state == VOC_RUN)
+ if ((v->voc_state == VOC_RUN) ||
+ (v->voc_state == VOC_CHANGE) ||
+ (v->voc_state == VOC_STANDBY))
ret = voice_send_mute_cmd(v);
mutex_unlock(&v->lock);
@@ -3312,7 +3317,9 @@
v->dev_rx.volume = vol_idx;
- if (v->voc_state == VOC_RUN)
+ if ((v->voc_state == VOC_RUN) ||
+ (v->voc_state == VOC_CHANGE) ||
+ (v->voc_state == VOC_STANDBY))
ret = voice_send_vol_index_cmd(v);
mutex_unlock(&v->lock);
@@ -3501,6 +3508,15 @@
pr_err("setup voice failed\n");
goto fail;
}
+
+ ret = voice_send_vol_index_cmd(v);
+ if (ret < 0)
+ pr_err("voice volume failed\n");
+
+ ret = voice_send_mute_cmd(v);
+ if (ret < 0)
+ pr_err("voice mute failed\n");
+
ret = voice_send_start_voice_cmd(v);
if (ret < 0) {
pr_err("start voice failed\n");
@@ -3998,7 +4014,7 @@
memset((void *)common.cvs_cal.buf, 0, CVS_CAL_SIZE);
cont:
/* set default value */
- common.default_mute_val = 1; /* default is mute */
+ common.default_mute_val = 0; /* default is un-mute */
common.default_vol_val = 0;
common.default_sample_val = 8000;
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 7723934..360744a 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -621,7 +621,11 @@
static __devinit int msm_compr_probe(struct platform_device *pdev)
{
- pr_info("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
+ if (pdev->dev.of_node)
+ dev_set_name(&pdev->dev, "%s", "msm-compr-dsp");
+
+ dev_info(&pdev->dev, "%s: dev name %s\n",
+ __func__, dev_name(&pdev->dev));
return snd_soc_register_platform(&pdev->dev,
&msm_soc_platform);
}
@@ -632,10 +636,17 @@
return 0;
}
+static const struct of_device_id msm_compr_dt_match[] = {
+ {.compatible = "qcom,msm-compr-dsp"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, msm_compr_dt_match);
+
static struct platform_driver msm_compr_driver = {
.driver = {
.name = "msm-compr-dsp",
.owner = THIS_MODULE,
+ .of_match_table = msm_compr_dt_match,
},
.probe = msm_compr_probe,
.remove = __devexit_p(msm_compr_remove),
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 691ca21..aed6273 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -433,7 +433,7 @@
mmap_regions->hdr.dest_port = 0;
mmap_regions->hdr.token = 0;
mmap_regions->hdr.opcode = ADM_CMD_SHARED_MEM_MAP_REGIONS;
- mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_EBI_POOL & 0x00ff;
+ mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL & 0x00ff;
mmap_regions->num_regions = bufcnt & 0x00ff;
mmap_regions->property_flag = 0x00;
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 5b30e8e..4875a69 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -867,7 +867,7 @@
mregion->hdr.dest_port = 0;
mregion->hdr.token = 0;
mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
- mregion->mem_pool_id = ADSP_MEMORY_MAP_EBI_POOL;
+ mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
mregion->num_regions = 1;
mregion->property_flag = 0x00;
/* Todo */
@@ -946,7 +946,7 @@
mregion->hdr.dest_port = 0;
mregion->hdr.token = 0;
mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
- mregion->mem_pool_id = ADSP_MEMORY_MAP_EBI_POOL;
+ mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
mregion->num_regions = 1;
mregion->property_flag = 0x00;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 0bb88e8..a3af263 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -2265,7 +2265,7 @@
q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size,
TRUE, ((ac->session << 8) | dir));
mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
- mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_EBI_POOL;
+ mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
mmap_regions->num_regions = bufcnt & 0x00ff;
mmap_regions->property_flag = 0x00;
payload = ((u8 *) mmap_region_cmd +
@@ -2408,7 +2408,7 @@
mmap_regions, ((ac->session << 8) | dir));
mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
- mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_EBI_POOL;
+ mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
mmap_regions->num_regions = 1; /*bufcnt & 0x00ff; */
mmap_regions->property_flag = 0x00;
pr_debug("map_regions->nregions = %d\n", mmap_regions->num_regions);