Merge "arm: config: Add smcmod to fsm9xxx targets"
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 3f7e9de..2cef567 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -121,9 +121,6 @@
regulator-min-microvolt = <1300000>;
regulator-max-microvolt = <1300000>;
qcom,init-voltage = <1300000>;
- qcom,init-current = <100>;
- qcom,system-load = <100000>;
- regulator-always-on;
status = "okay";
};
};
@@ -136,14 +133,6 @@
qcom,init-voltage = <2150000>;
status = "okay";
};
- pm8941_s2_ao: regulator-s2-ao {
- regulator-name = "8941_s2_ao";
- qcom,set = <1>;
- regulator-min-microvolt = <2150000>;
- regulator-max-microvolt = <2150000>;
- status = "okay";
- compatible = "qcom,rpm-regulator-smd";
- };
};
rpm-regulator-smpa3 {
@@ -152,9 +141,6 @@
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
qcom,init-voltage = <1800000>;
- qcom,init-current = <100>;
- qcom,system-load = <100000>;
- regulator-always-on;
status = "okay";
};
};
@@ -162,13 +148,9 @@
rpm-regulator-ldoa1 {
status = "okay";
pm8941_l1: regulator-l1 {
- parent-supply = <&pm8941_s1>;
regulator-min-microvolt = <1225000>;
regulator-max-microvolt = <1225000>;
qcom,init-voltage = <1225000>;
- qcom,init-current = <10>;
- qcom,system-load = <10000>;
- regulator-always-on;
status = "okay";
};
};
@@ -176,7 +158,6 @@
rpm-regulator-ldoa2 {
status = "okay";
pm8941_l2: regulator-l2 {
- parent-supply = <&pm8941_s3>;
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
qcom,init-voltage = <1200000>;
@@ -187,7 +168,6 @@
rpm-regulator-ldoa3 {
status = "okay";
pm8941_l3: regulator-l3 {
- parent-supply = <&pm8941_s1>;
regulator-min-microvolt = <1225000>;
regulator-max-microvolt = <1225000>;
qcom,init-voltage = <1225000>;
@@ -198,7 +178,6 @@
rpm-regulator-ldoa4 {
status = "okay";
pm8941_l4: regulator-l4 {
- parent-supply = <&pm8941_s1>;
regulator-min-microvolt = <1225000>;
regulator-max-microvolt = <1225000>;
qcom,init-voltage = <1225000>;
@@ -209,7 +188,6 @@
rpm-regulator-ldoa5 {
status = "okay";
pm8941_l5: regulator-l5 {
- parent-supply = <&pm8941_s2>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
qcom,init-voltage = <1800000>;
@@ -220,7 +198,6 @@
rpm-regulator-ldoa6 {
status = "okay";
pm8941_l6: regulator-l6 {
- parent-supply = <&pm8941_s2>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
qcom,init-voltage = <1800000>;
@@ -231,7 +208,6 @@
rpm-regulator-ldoa7 {
status = "okay";
pm8941_l7: regulator-l7 {
- parent-supply = <&pm8941_s2>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
qcom,init-voltage = <1800000>;
@@ -272,7 +248,6 @@
rpm-regulator-ldoa11 {
status = "okay";
pm8941_l11: regulator-l11 {
- parent-supply = <&pm8941_s1>;
regulator-min-microvolt = <1300000>;
regulator-max-microvolt = <1300000>;
qcom,init-voltage = <1300000>;
@@ -283,14 +258,12 @@
rpm-regulator-ldoa12 {
status = "okay";
pm8941_l12: regulator-l12 {
- parent-supply = <&pm8941_s2>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
status = "okay";
};
pm8941_l12_ao: regulator-l12-ao {
regulator-name = "8941_l12_ao";
- parent-supply = <&pm8941_s2_ao>;
qcom,set = <1>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
@@ -312,7 +285,6 @@
rpm-regulator-ldoa14 {
status = "okay";
pm8941_l14: regulator-l14 {
- parent-supply = <&pm8941_s2>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
qcom,init-voltage = <1800000>;
@@ -323,7 +295,6 @@
rpm-regulator-ldoa15 {
status = "okay";
pm8941_l15: regulator-l15 {
- parent-supply = <&pm8941_s2>;
regulator-min-microvolt = <2050000>;
regulator-max-microvolt = <2050000>;
qcom,init-voltage = <2050000>;
@@ -424,7 +395,6 @@
rpm-regulator-vsa1 {
status = "okay";
pm8941_lvs1: regulator-lvs1 {
- parent-supply = <&pm8941_s3>;
status = "okay";
};
};
@@ -432,7 +402,6 @@
rpm-regulator-vsa2 {
status = "okay";
pm8941_lvs2: regulator-lvs2 {
- parent-supply = <&pm8941_s3>;
status = "okay";
};
};
@@ -440,7 +409,6 @@
rpm-regulator-vsa3 {
status = "okay";
pm8941_lvs3: regulator-lvs3 {
- parent-supply = <&pm8941_s3>;
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index eeb05d4..6a7e81e 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -648,16 +648,11 @@
krait1_dig-supply = <&pm8841_s2_corner_ao>;
krait2_dig-supply = <&pm8841_s2_corner_ao>;
krait3_dig-supply = <&pm8841_s2_corner_ao>;
- krait0_hfpll_a-supply = <&pm8941_s2_ao>;
- krait1_hfpll_a-supply = <&pm8941_s2_ao>;
- krait2_hfpll_a-supply = <&pm8941_s2_ao>;
- krait3_hfpll_a-supply = <&pm8941_s2_ao>;
- l2_hfpll_a-supply = <&pm8941_s2_ao>;
- krait0_hfpll_b-supply = <&pm8941_l12_ao>;
- krait1_hfpll_b-supply = <&pm8941_l12_ao>;
- krait2_hfpll_b-supply = <&pm8941_l12_ao>;
- krait3_hfpll_b-supply = <&pm8941_l12_ao>;
- l2_hfpll_b-supply = <&pm8941_l12_ao>;
+ krait0_hfpll-supply = <&pm8941_l12_ao>;
+ krait1_hfpll-supply = <&pm8941_l12_ao>;
+ krait2_hfpll-supply = <&pm8941_l12_ao>;
+ krait3_hfpll-supply = <&pm8941_l12_ao>;
+ l2_hfpll-supply = <&pm8941_l12_ao>;
};
usb3: qcom,ssusb@f9200000 {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 7462911..cbd93df 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -523,6 +523,57 @@
compatible = "qcom,pil-q6v5-mss";
interrupts = <0 24 1>;
};
+
+ qcom,smem@fa00000 {
+ compatible = "qcom,smem";
+ reg = <0xfa00000 0x200000>,
+ <0xfa006000 0x1000>,
+ <0xfc428000 0x4000>;
+ reg-names = "smem", "irq-reg-base", "aux-mem1";
+
+ qcom,smd-modem {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <0>;
+ qcom,smd-irq-offset = <0x8>;
+ qcom,smd-irq-bitmask = <0x1000>;
+ qcom,pil-string = "modem";
+ interrupts = <0 25 1>;
+ };
+
+ qcom,smsm-modem {
+ compatible = "qcom,smsm";
+ qcom,smsm-edge = <0>;
+ qcom,smsm-irq-offset = <0x8>;
+ qcom,smsm-irq-bitmask = <0x2000>;
+ interrupts = <0 26 1>;
+ };
+
+ qcom,smd-adsp {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <1>;
+ qcom,smd-irq-offset = <0x8>;
+ qcom,smd-irq-bitmask = <0x100>;
+ qcom,pil-string = "adsp";
+ interrupts = <0 156 1>;
+ };
+
+ qcom,smsm-adsp {
+ compatible = "qcom,smsm";
+ qcom,smsm-edge = <1>;
+ qcom,smsm-irq-offset = <0x8>;
+ qcom,smsm-irq-bitmask = <0x200>;
+ interrupts = <0 157 1>;
+ };
+
+ qcom,smd-rpm {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <15>;
+ qcom,smd-irq-offset = <0x8>;
+ qcom,smd-irq-bitmask = <0x1>;
+ interrupts = <0 168 1>;
+ qcom,irq-no-suspend;
+ };
+ };
};
/include/ "msm-pm8019-rpm-regulator.dtsi"
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index d5e15f1..1fe1eaa 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -242,6 +242,7 @@
CONFIG_RFKILL=y
CONFIG_GENLOCK=y
CONFIG_GENLOCK_MISCDEVICE=y
+CONFIG_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_TSPP=m
@@ -466,6 +467,7 @@
CONFIG_MSM_SSBI=y
CONFIG_SPS=y
CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_MSM_AVTIMER=y
CONFIG_MSM_IOMMU=y
CONFIG_MOBICORE_SUPPORT=m
CONFIG_MOBICORE_API=m
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 386f311..01d1934 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -247,6 +247,7 @@
CONFIG_RFKILL=y
CONFIG_GENLOCK=y
CONFIG_GENLOCK_MISCDEVICE=y
+CONFIG_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_TSPP=m
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index bf44665..71e83f6 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -248,6 +248,7 @@
CONFIG_INPUT_EVBUG=m
CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_XPAD=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=y
CONFIG_INPUT_MISC=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index f9dbc85..ffcc83f 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -250,6 +250,7 @@
CONFIG_INPUT_EVBUG=m
CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_XPAD=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=y
CONFIG_INPUT_MISC=y
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 0fbd6dc..b98fcdd 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -56,8 +56,7 @@
.vreg[VREG_CORE] = { "krait0", 1050000 },
.vreg[VREG_MEM] = { "krait0_mem", 1050000 },
.vreg[VREG_DIG] = { "krait0_dig", LVL_HIGH },
- .vreg[VREG_HFPLL_A] = { "krait0_hfpll_a", 2150000 },
- .vreg[VREG_HFPLL_B] = { "krait0_hfpll_b", 1800000 },
+ .vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 },
},
[CPU1] = {
.hfpll_phys_base = 0xF909A000,
@@ -66,8 +65,7 @@
.vreg[VREG_CORE] = { "krait1", 1050000 },
.vreg[VREG_MEM] = { "krait1_mem", 1050000 },
.vreg[VREG_DIG] = { "krait1_dig", LVL_HIGH },
- .vreg[VREG_HFPLL_A] = { "krait1_hfpll_a", 2150000 },
- .vreg[VREG_HFPLL_B] = { "krait1_hfpll_b", 1800000 },
+ .vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 },
},
[CPU2] = {
.hfpll_phys_base = 0xF90AA000,
@@ -76,8 +74,7 @@
.vreg[VREG_CORE] = { "krait2", 1050000 },
.vreg[VREG_MEM] = { "krait2_mem", 1050000 },
.vreg[VREG_DIG] = { "krait2_dig", LVL_HIGH },
- .vreg[VREG_HFPLL_A] = { "krait2_hfpll_a", 2150000 },
- .vreg[VREG_HFPLL_B] = { "krait2_hfpll_b", 1800000 },
+ .vreg[VREG_HFPLL_A] = { "krait2_hfpll", 1800000 },
},
[CPU3] = {
.hfpll_phys_base = 0xF90BA000,
@@ -86,15 +83,13 @@
.vreg[VREG_CORE] = { "krait3", 1050000 },
.vreg[VREG_MEM] = { "krait3_mem", 1050000 },
.vreg[VREG_DIG] = { "krait3_dig", LVL_HIGH },
- .vreg[VREG_HFPLL_A] = { "krait3_hfpll_a", 2150000 },
- .vreg[VREG_HFPLL_B] = { "krait3_hfpll_b", 1800000 },
+ .vreg[VREG_HFPLL_A] = { "krait3_hfpll", 1800000 },
},
[L2] = {
.hfpll_phys_base = 0xF9016000,
.l2cpmr_iaddr = 0x0500,
.sec_clk_sel = 2,
- .vreg[VREG_HFPLL_A] = { "l2_hfpll_a", 2150000 },
- .vreg[VREG_HFPLL_B] = { "l2_hfpll_b", 1800000 },
+ .vreg[VREG_HFPLL_A] = { "l2_hfpll", 1800000 },
},
};
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index e5212a4..f70e41a 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -25,6 +25,7 @@
#include <linux/mfd/pm8xxx/misc.h>
#include <linux/msm_ssbi.h>
#include <linux/spi/spi.h>
+#include <linux/dma-contiguous.h>
#include <linux/dma-mapping.h>
#include <linux/platform_data/qcom_crypto_device.h>
#include <linux/msm_ion.h>
@@ -296,6 +297,7 @@
.reusable = FMEM_ENABLED,
.mem_is_fmem = FMEM_ENABLED,
.fixed_position = FIXED_MIDDLE,
+ .is_cma = 1,
};
static struct ion_cp_heap_pdata cp_mfc_apq8064_ion_pdata = {
@@ -320,6 +322,17 @@
};
#endif
+static u64 msm_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ion_mm_heap_device = {
+ .name = "ion-mm-heap-device",
+ .id = -1,
+ .dev = {
+ .dma_mask = &msm_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
/**
* These heaps are listed in the order they will be allocated. Due to
* video hardware restrictions and content protection the FW heap has to
@@ -345,6 +358,7 @@
.size = MSM_ION_MM_SIZE,
.memory_type = ION_EBI_TYPE,
.extra_data = (void *) &cp_mm_apq8064_ion_pdata,
+ .priv = &ion_mm_heap_device.dev
},
{
.id = ION_MM_FIRMWARE_HEAP_ID,
@@ -454,26 +468,45 @@
{
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
unsigned int i;
+ unsigned int ret;
unsigned int fixed_size = 0;
unsigned int fixed_low_size, fixed_middle_size, fixed_high_size;
unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
+ unsigned long cma_alignment;
+ unsigned int low_use_cma = 0;
+ unsigned int middle_use_cma = 0;
+ unsigned int high_use_cma = 0;
+
fixed_low_size = 0;
fixed_middle_size = 0;
fixed_high_size = 0;
+ cma_alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order);
+
for (i = 0; i < apq8064_ion_pdata.nr; ++i) {
- const struct ion_platform_heap *heap =
+ struct ion_platform_heap *heap =
&(apq8064_ion_pdata.heaps[i]);
+ int use_cma = 0;
+
if (heap->extra_data) {
int fixed_position = NOT_FIXED;
switch ((int)heap->type) {
case ION_HEAP_TYPE_CP:
+ if (((struct ion_cp_heap_pdata *)
+ heap->extra_data)->is_cma) {
+ heap->size = ALIGN(heap->size,
+ cma_alignment);
+ use_cma = 1;
+ }
fixed_position = ((struct ion_cp_heap_pdata *)
heap->extra_data)->fixed_position;
break;
+ case ION_HEAP_TYPE_DMA:
+ use_cma = 1;
+ /* Purposely fall through here */
case ION_HEAP_TYPE_CARVEOUT:
fixed_position = ((struct ion_co_heap_pdata *)
heap->extra_data)->fixed_position;
@@ -487,28 +520,70 @@
else
reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
- if (fixed_position == FIXED_LOW)
+ if (fixed_position == FIXED_LOW) {
fixed_low_size += heap->size;
- else if (fixed_position == FIXED_MIDDLE)
+ low_use_cma = use_cma;
+ } else if (fixed_position == FIXED_MIDDLE) {
fixed_middle_size += heap->size;
- else if (fixed_position == FIXED_HIGH)
+ middle_use_cma = use_cma;
+ } else if (fixed_position == FIXED_HIGH) {
fixed_high_size += heap->size;
+ high_use_cma = use_cma;
+ } else if (use_cma) {
+ /*
+ * Heaps that use CMA but are not part of the
+ * fixed set. Create wherever.
+ */
+ dma_declare_contiguous(
+ heap->priv,
+ heap->size,
+ 0,
+ 0xb0000000);
+
+ }
}
}
if (!fixed_size)
return;
- /* Since the fixed area may be carved out of lowmem,
- * make sure the length is a multiple of 1M.
+ /*
+ * Given the setup for the fixed area, we can't round up all sizes.
+ * Some sizes must be set up exactly and aligned correctly. Incorrect
+ * alignments are considered a configuration issue
*/
- fixed_size = (fixed_size + HOLE_SIZE + SECTION_SIZE - 1)
- & SECTION_MASK;
- apq8064_reserve_fixed_area(fixed_size);
fixed_low_start = APQ8064_FIXED_AREA_START;
+ if (low_use_cma) {
+ BUG_ON(!IS_ALIGNED(fixed_low_size + HOLE_SIZE, cma_alignment));
+ BUG_ON(!IS_ALIGNED(fixed_low_start, cma_alignment));
+ } else {
+ BUG_ON(!IS_ALIGNED(fixed_low_size + HOLE_SIZE, SECTION_SIZE));
+ ret = memblock_remove(fixed_low_start,
+ fixed_low_size + HOLE_SIZE);
+ BUG_ON(ret);
+ }
+
fixed_middle_start = fixed_low_start + fixed_low_size + HOLE_SIZE;
+ if (middle_use_cma) {
+ BUG_ON(!IS_ALIGNED(fixed_middle_start, cma_alignment));
+ BUG_ON(!IS_ALIGNED(fixed_middle_size, cma_alignment));
+ } else {
+ BUG_ON(!IS_ALIGNED(fixed_middle_size, SECTION_SIZE));
+ ret = memblock_remove(fixed_middle_start, fixed_middle_size);
+ BUG_ON(ret);
+ }
+
fixed_high_start = fixed_middle_start + fixed_middle_size;
+ if (high_use_cma) {
+ fixed_high_size = ALIGN(fixed_high_size, cma_alignment);
+ BUG_ON(!IS_ALIGNED(fixed_high_start, cma_alignment));
+ } else {
+ /* This is the end of the fixed area so it's okay to round up */
+ fixed_high_size = ALIGN(fixed_high_size, SECTION_SIZE);
+ ret = memblock_remove(fixed_high_start, fixed_high_size);
+ BUG_ON(ret);
+ }
for (i = 0; i < apq8064_ion_pdata.nr; ++i) {
struct ion_platform_heap *heap = &(apq8064_ion_pdata.heaps[i]);
@@ -524,6 +599,7 @@
fixed_position = pdata->fixed_position;
break;
case ION_HEAP_TYPE_CARVEOUT:
+ case ION_HEAP_TYPE_DMA:
fixed_position = ((struct ion_co_heap_pdata *)
heap->extra_data)->fixed_position;
break;
@@ -537,6 +613,14 @@
break;
case FIXED_MIDDLE:
heap->base = fixed_middle_start;
+ if (middle_use_cma) {
+ ret = dma_declare_contiguous(
+ heap->priv,
+ heap->size,
+ fixed_middle_start,
+ 0xa0000000);
+ WARN_ON(ret);
+ }
pdata->secure_base = fixed_middle_start
- HOLE_SIZE;
pdata->secure_size = HOLE_SIZE + heap->size;
@@ -3162,6 +3246,11 @@
},
};
+static struct platform_device msm_dev_avtimer_device = {
+ .name = "dev_avtimer",
+ .dev = { .platform_data = &dev_avtimer_pdata },
+};
+
/* Sensors DSPS platform data */
#define DSPS_PIL_GENERIC_NAME "dsps"
static void __init apq8064_init_dsps(void)
@@ -3601,6 +3690,9 @@
platform_device_register(&mpq_keypad_device);
} else if (machine_is_mpq8064_hrd())
platform_device_register(&mpq_hrd_keys_pdev);
+ if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
+ machine_is_mpq8064_dtv())
+ platform_device_register(&msm_dev_avtimer_device);
}
MACHINE_START(APQ8064_CDP, "QCT APQ8064 CDP")
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 3e90489..fde82f4 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -64,6 +64,8 @@
CLK_DUMMY("iface_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
CLK_DUMMY("iface_clk", HSUSB_IFACE_CLK, "f9a55000.usb", OFF),
CLK_DUMMY("core_clk", HSUSB_CORE_CLK, "f9a55000.usb", OFF),
+ CLK_DUMMY("dfab_clk", DFAB_CLK, "msm_sps", OFF),
+ CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, "msm_sps", OFF),
CLK_DUMMY("iface_clk", NULL, "msm_sdcc.1", OFF),
CLK_DUMMY("core_clk", NULL, "msm_sdcc.1", OFF),
CLK_DUMMY("bus_clk", NULL, "msm_sdcc.1", OFF),
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index be55031..e35b3c1 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -264,7 +264,7 @@
{
.src = MSM_BUS_MASTER_VFE,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 274406400,
+ .ab = 600000000,
.ib = 2656000000UL,
},
{
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 790afe1..13b16f2 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -29,6 +29,7 @@
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
#endif
+#include <linux/dma-contiguous.h>
#include <linux/dma-mapping.h>
#include <linux/platform_data/qcom_crypto_device.h>
#include <linux/platform_data/qcom_wcnss_device.h>
@@ -341,6 +342,7 @@
.reusable = FMEM_ENABLED,
.mem_is_fmem = FMEM_ENABLED,
.fixed_position = FIXED_MIDDLE,
+ .is_cma = 1,
};
static struct ion_cp_heap_pdata cp_mfc_msm8930_ion_pdata = {
@@ -365,6 +367,18 @@
};
#endif
+
+static u64 msm_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ion_mm_heap_device = {
+ .name = "ion-mm-heap-device",
+ .id = -1,
+ .dev = {
+ .dma_mask = &msm_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
/**
* These heaps are listed in the order they will be allocated. Due to
* video hardware restrictions and content protection the FW heap has to
@@ -390,6 +404,7 @@
.size = MSM_ION_MM_SIZE,
.memory_type = ION_EBI_TYPE,
.extra_data = (void *) &cp_mm_msm8930_ion_pdata,
+ .priv = &ion_mm_heap_device.dev
},
{
.id = ION_MM_FIRMWARE_HEAP_ID,
@@ -500,26 +515,44 @@
{
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
unsigned int i;
+ int ret;
unsigned int fixed_size = 0;
unsigned int fixed_low_size, fixed_middle_size, fixed_high_size;
unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
+ unsigned long cma_alignment;
+ unsigned int low_use_cma = 0;
+ unsigned int middle_use_cma = 0;
+ unsigned int high_use_cma = 0;
fixed_low_size = 0;
fixed_middle_size = 0;
fixed_high_size = 0;
+ cma_alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order);
+
for (i = 0; i < msm8930_ion_pdata.nr; ++i) {
- const struct ion_platform_heap *heap =
+ struct ion_platform_heap *heap =
&(msm8930_ion_pdata.heaps[i]);
+ int use_cma = 0;
+
if (heap->extra_data) {
int fixed_position = NOT_FIXED;
switch ((int) heap->type) {
case ION_HEAP_TYPE_CP:
+ if (((struct ion_cp_heap_pdata *)
+ heap->extra_data)->is_cma) {
+ heap->size = ALIGN(heap->size,
+ cma_alignment);
+ use_cma = 1;
+ }
fixed_position = ((struct ion_cp_heap_pdata *)
heap->extra_data)->fixed_position;
break;
+ case ION_HEAP_TYPE_DMA:
+ use_cma = 1;
+ /* Purposely fall through here */
case ION_HEAP_TYPE_CARVEOUT:
fixed_position = ((struct ion_co_heap_pdata *)
heap->extra_data)->fixed_position;
@@ -533,29 +566,68 @@
else
reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
- if (fixed_position == FIXED_LOW)
+ if (fixed_position == FIXED_LOW) {
fixed_low_size += heap->size;
- else if (fixed_position == FIXED_MIDDLE)
+ low_use_cma = use_cma;
+ } else if (fixed_position == FIXED_MIDDLE) {
fixed_middle_size += heap->size;
- else if (fixed_position == FIXED_HIGH)
+ middle_use_cma = use_cma;
+ } else if (fixed_position == FIXED_HIGH) {
fixed_high_size += heap->size;
-
+ high_use_cma = use_cma;
+ } else if (use_cma) {
+ /*
+ * Heaps that use CMA but are not part of the
+ * fixed set. Create wherever.
+ */
+ dma_declare_contiguous(
+ heap->priv,
+ heap->size,
+ 0,
+ 0xb0000000);
+ }
}
}
if (!fixed_size)
return;
-
- /* Since the fixed area may be carved out of lowmem,
- * make sure the length is a multiple of 1M.
+ /*
+ * Given the setup for the fixed area, we can't round up all sizes.
+ * Some sizes must be set up exactly and aligned correctly. Incorrect
+ * alignments are considered a configuration issue
*/
- fixed_size = (fixed_size + MSM_MM_FW_SIZE + SECTION_SIZE - 1)
- & SECTION_MASK;
- msm8930_reserve_fixed_area(fixed_size);
fixed_low_start = MSM8930_FIXED_AREA_START;
+ if (low_use_cma) {
+ BUG_ON(!IS_ALIGNED(fixed_low_size + HOLE_SIZE, cma_alignment));
+ BUG_ON(!IS_ALIGNED(fixed_low_start, cma_alignment));
+ } else {
+ BUG_ON(!IS_ALIGNED(fixed_low_size + HOLE_SIZE, SECTION_SIZE));
+ ret = memblock_remove(fixed_low_start,
+ fixed_low_size + HOLE_SIZE);
+ BUG_ON(ret);
+ }
+
fixed_middle_start = fixed_low_start + fixed_low_size + HOLE_SIZE;
+ if (middle_use_cma) {
+ BUG_ON(!IS_ALIGNED(fixed_middle_start, cma_alignment));
+ BUG_ON(!IS_ALIGNED(fixed_middle_size, cma_alignment));
+ } else {
+ BUG_ON(!IS_ALIGNED(fixed_middle_size, SECTION_SIZE));
+ ret = memblock_remove(fixed_middle_start, fixed_middle_size);
+ BUG_ON(ret);
+ }
+
fixed_high_start = fixed_middle_start + fixed_middle_size;
+ if (high_use_cma) {
+ fixed_high_size = ALIGN(fixed_high_size, cma_alignment);
+ BUG_ON(!IS_ALIGNED(fixed_high_start, cma_alignment));
+ } else {
+ /* This is the end of the fixed area so it's okay to round up */
+ fixed_high_size = ALIGN(fixed_high_size, SECTION_SIZE);
+ ret = memblock_remove(fixed_high_start, fixed_high_size);
+ BUG_ON(ret);
+ }
for (i = 0; i < msm8930_ion_pdata.nr; ++i) {
struct ion_platform_heap *heap = &(msm8930_ion_pdata.heaps[i]);
@@ -570,6 +642,7 @@
(struct ion_cp_heap_pdata *)heap->extra_data;
fixed_position = pdata->fixed_position;
break;
+ case ION_HEAP_TYPE_DMA:
case ION_HEAP_TYPE_CARVEOUT:
fixed_position = ((struct ion_co_heap_pdata *)
heap->extra_data)->fixed_position;
@@ -584,6 +657,12 @@
break;
case FIXED_MIDDLE:
heap->base = fixed_middle_start;
+ if (middle_use_cma)
+ dma_declare_contiguous(
+ &ion_mm_heap_device.dev,
+ heap->size,
+ fixed_middle_start,
+ 0xa0000000);
pdata->secure_base = fixed_middle_start
- HOLE_SIZE;
pdata->secure_size = HOLE_SIZE + heap->size;
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index adf4ac0..97639d6 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -30,6 +30,7 @@
#include <linux/android_pmem.h>
#endif
#include <linux/cyttsp-qc.h>
+#include <linux/dma-contiguous.h>
#include <linux/dma-mapping.h>
#include <linux/platform_data/qcom_crypto_device.h>
#include <linux/platform_data/qcom_wcnss_device.h>
@@ -364,6 +365,7 @@
.fixed_position = FIXED_MIDDLE,
.iommu_map_all = 1,
.iommu_2x_map_domain = VIDEO_DOMAIN,
+ .is_cma = 1,
};
static struct ion_cp_heap_pdata cp_mfc_msm8960_ion_pdata = {
@@ -388,6 +390,17 @@
};
#endif
+static u64 msm_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ion_mm_heap_device = {
+ .name = "ion-mm-heap-device",
+ .id = -1,
+ .dev = {
+ .dma_mask = &msm_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ }
+};
+
/**
* These heaps are listed in the order they will be allocated. Due to
* video hardware restrictions and content protection the FW heap has to
@@ -413,6 +426,7 @@
.size = MSM_ION_MM_SIZE,
.memory_type = ION_EBI_TYPE,
.extra_data = (void *) &cp_mm_msm8960_ion_pdata,
+ .priv = &ion_mm_heap_device.dev,
},
{
.id = ION_MM_FIRMWARE_HEAP_ID,
@@ -549,21 +563,29 @@
{
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
unsigned int i;
+ int ret;
unsigned int fixed_size = 0;
unsigned int fixed_low_size, fixed_middle_size, fixed_high_size;
unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
+ unsigned long cma_alignment;
+ unsigned int low_use_cma = 0;
+ unsigned int middle_use_cma = 0;
+ unsigned int high_use_cma = 0;
adjust_mem_for_liquid();
fixed_low_size = 0;
fixed_middle_size = 0;
fixed_high_size = 0;
+ cma_alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order);
+
for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
struct ion_platform_heap *heap =
&(msm8960_ion_pdata.heaps[i]);
int align = SZ_4K;
int iommu_map_all = 0;
int adjacent_mem_id = INVALID_HEAP_ID;
+ int use_cma = 0;
if (heap->extra_data) {
int fixed_position = NOT_FIXED;
@@ -577,7 +599,16 @@
iommu_map_all =
((struct ion_cp_heap_pdata *)
heap->extra_data)->iommu_map_all;
+ if (((struct ion_cp_heap_pdata *)
+ heap->extra_data)->is_cma) {
+ heap->size = ALIGN(heap->size,
+ cma_alignment);
+ use_cma = 1;
+ }
break;
+ case ION_HEAP_TYPE_DMA:
+ use_cma = 1;
+ /* Purposely fall through here */
case ION_HEAP_TYPE_CARVEOUT:
fixed_position = ((struct ion_co_heap_pdata *)
heap->extra_data)->fixed_position;
@@ -601,28 +632,71 @@
else
reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
- if (fixed_position == FIXED_LOW)
+ if (fixed_position == FIXED_LOW) {
fixed_low_size += heap->size;
- else if (fixed_position == FIXED_MIDDLE)
+ low_use_cma = use_cma;
+ } else if (fixed_position == FIXED_MIDDLE) {
fixed_middle_size += heap->size;
- else if (fixed_position == FIXED_HIGH)
+ middle_use_cma = use_cma;
+ } else if (fixed_position == FIXED_HIGH) {
fixed_high_size += heap->size;
+ high_use_cma = use_cma;
+ } else if (use_cma) {
+ /*
+ * Heaps that use CMA but are not part of the
+ * fixed set. Create wherever.
+ */
+ dma_declare_contiguous(
+ heap->priv,
+ heap->size,
+ 0,
+ 0xb0000000);
+ }
}
}
if (!fixed_size)
return;
- /* Since the fixed area may be carved out of lowmem,
- * make sure the length is a multiple of 1M.
+ /*
+ * Given the setup for the fixed area, we can't round up all sizes.
+ * Some sizes must be set up exactly and aligned correctly. Incorrect
+ * alignments are considered a configuration issue
*/
- fixed_size = (fixed_size + MSM_MM_FW_SIZE + SECTION_SIZE - 1)
- & SECTION_MASK;
- msm8960_reserve_fixed_area(fixed_size);
fixed_low_start = MSM8960_FIXED_AREA_START;
+ if (low_use_cma) {
+ BUG_ON(!IS_ALIGNED(fixed_low_start, cma_alignment));
+ BUG_ON(!IS_ALIGNED(fixed_low_size + HOLE_SIZE, cma_alignment));
+ } else {
+ BUG_ON(!IS_ALIGNED(fixed_low_size + HOLE_SIZE, SECTION_SIZE));
+ ret = memblock_remove(fixed_low_start,
+ fixed_low_size + HOLE_SIZE);
+ BUG_ON(ret);
+ }
+
fixed_middle_start = fixed_low_start + fixed_low_size + HOLE_SIZE;
+ if (middle_use_cma) {
+ BUG_ON(!IS_ALIGNED(fixed_middle_start, cma_alignment));
+ BUG_ON(!IS_ALIGNED(fixed_middle_size, cma_alignment));
+ } else {
+ BUG_ON(!IS_ALIGNED(fixed_middle_size, SECTION_SIZE));
+ ret = memblock_remove(fixed_middle_start, fixed_middle_size);
+ BUG_ON(ret);
+ }
+
fixed_high_start = fixed_middle_start + fixed_middle_size;
+ if (high_use_cma) {
+ fixed_high_size = ALIGN(fixed_high_size, cma_alignment);
+ BUG_ON(!IS_ALIGNED(fixed_high_start, cma_alignment));
+ } else {
+ /* This is the end of the fixed area so it's okay to round up */
+ fixed_high_size = ALIGN(fixed_high_size, SECTION_SIZE);
+ ret = memblock_remove(fixed_high_start, fixed_high_size);
+ BUG_ON(ret);
+ }
+
+
for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
struct ion_platform_heap *heap = &(msm8960_ion_pdata.heaps[i]);
@@ -638,6 +712,7 @@
fixed_position = pdata->fixed_position;
break;
case ION_HEAP_TYPE_CARVEOUT:
+ case ION_HEAP_TYPE_DMA:
fixed_position = ((struct ion_co_heap_pdata *)
heap->extra_data)->fixed_position;
break;
@@ -651,6 +726,14 @@
break;
case FIXED_MIDDLE:
heap->base = fixed_middle_start;
+ if (middle_use_cma) {
+ ret = dma_declare_contiguous(
+ &ion_mm_heap_device.dev,
+ heap->size,
+ fixed_middle_start,
+ 0xa0000000);
+ WARN_ON(ret);
+ }
pdata->secure_base = fixed_middle_start
- HOLE_SIZE;
pdata->secure_size = HOLE_SIZE + heap->size;
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 42f3f41..f6a354f 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -125,135 +125,6 @@
msm_reserve();
}
-static struct resource smd_resource[] = {
- {
- .name = "modem_smd_in",
- .start = 32 + 25, /* mss_sw_to_kpss_ipc_irq0 */
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "modem_smsm_in",
- .start = 32 + 26, /* mss_sw_to_kpss_ipc_irq1 */
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "adsp_smd_in",
- .start = 32 + 156, /* lpass_to_kpss_ipc_irq0 */
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "adsp_smsm_in",
- .start = 32 + 157, /* lpass_to_kpss_ipc_irq1 */
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "rpm_smd_in",
- .start = 32 + 168, /* rpm_to_kpss_ipc_irq4 */
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct smd_subsystem_config smd_config_list[] = {
- {
- .irq_config_id = SMD_MODEM,
- .subsys_name = "modem",
- .edge = SMD_APPS_MODEM,
-
- .smd_int.irq_name = "modem_smd_in",
- .smd_int.flags = IRQF_TRIGGER_RISING,
- .smd_int.irq_id = -1,
- .smd_int.device_name = "smd_dev",
- .smd_int.dev_id = 0,
- .smd_int.out_bit_pos = 1 << 12,
- .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
- .smd_int.out_offset = 0x8,
-
- .smsm_int.irq_name = "modem_smsm_in",
- .smsm_int.flags = IRQF_TRIGGER_RISING,
- .smsm_int.irq_id = -1,
- .smsm_int.device_name = "smsm_dev",
- .smsm_int.dev_id = 0,
- .smsm_int.out_bit_pos = 1 << 13,
- .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
- .smsm_int.out_offset = 0x8,
- },
- {
- .irq_config_id = SMD_Q6,
- .subsys_name = "adsp",
- .edge = SMD_APPS_QDSP,
-
- .smd_int.irq_name = "adsp_smd_in",
- .smd_int.flags = IRQF_TRIGGER_RISING,
- .smd_int.irq_id = -1,
- .smd_int.device_name = "smd_dev",
- .smd_int.dev_id = 0,
- .smd_int.out_bit_pos = 1 << 8,
- .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
- .smd_int.out_offset = 0x8,
-
- .smsm_int.irq_name = "adsp_smsm_in",
- .smsm_int.flags = IRQF_TRIGGER_RISING,
- .smsm_int.irq_id = -1,
- .smsm_int.device_name = "smsm_dev",
- .smsm_int.dev_id = 0,
- .smsm_int.out_bit_pos = 1 << 9,
- .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
- .smsm_int.out_offset = 0x8,
- },
- {
- .irq_config_id = SMD_RPM,
- .subsys_name = NULL, /* do not use PIL to load RPM */
- .edge = SMD_APPS_RPM,
-
- .smd_int.irq_name = "rpm_smd_in",
- .smd_int.flags = IRQF_TRIGGER_RISING,
- .smd_int.irq_id = -1,
- .smd_int.device_name = "smd_dev",
- .smd_int.dev_id = 0,
- .smd_int.out_bit_pos = 1 << 0,
- .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
- .smd_int.out_offset = 0x8,
-
- .smsm_int.irq_name = NULL, /* RPM does not support SMSM */
- .smsm_int.flags = 0,
- .smsm_int.irq_id = 0,
- .smsm_int.device_name = NULL,
- .smsm_int.dev_id = 0,
- .smsm_int.out_bit_pos = 0,
- .smsm_int.out_base = NULL,
- .smsm_int.out_offset = 0,
- },
-};
-
-static struct smd_smem_regions aux_smem_areas[] = {
- {
- .phys_addr = (void *)(0xfc428000),
- .size = 0x4000,
- },
-};
-
-static struct smd_subsystem_restart_config smd_ssr_cfg = {
- .disable_smsm_reset_handshake = 1,
-};
-
-static struct smd_platform smd_platform_data = {
- .num_ss_configs = ARRAY_SIZE(smd_config_list),
- .smd_ss_configs = smd_config_list,
- .smd_ssr_config = &smd_ssr_cfg,
- .num_smem_areas = ARRAY_SIZE(aux_smem_areas),
- .smd_smem_areas = aux_smem_areas,
-};
-
-struct platform_device msm_device_smd_9625 = {
- .name = "msm_smd",
- .id = -1,
- .resource = smd_resource,
- .num_resources = ARRAY_SIZE(smd_resource),
- .dev = {
- .platform_data = &smd_platform_data,
- }
-};
-
#define BIMC_BASE 0xfc380000
#define BIMC_SIZE 0x0006A000
#define SYS_NOC_BASE 0xfc460000
@@ -345,11 +216,6 @@
ARRAY_SIZE(msm_bus_9625_devices));
}
-void __init msm9625_add_devices(void)
-{
- platform_device_register(&msm_device_smd_9625);
-}
-
/*
* Used to satisfy dependencies for devices that need to be
* run early or in a particular order. Most likely your device doesn't fall
@@ -376,7 +242,6 @@
msm9625_init_gpiomux();
of_platform_populate(NULL, of_default_bus_match_table,
msm9625_auxdata_lookup, NULL);
- msm9625_add_devices();
msm9625_add_drivers();
}
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index 07ff389..5351d41 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -369,6 +369,14 @@
if (!(machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())) {
if (mmc_regulator_init(3, "emmc", 3000000))
return;
+ /*
+ * On 7x25A FFA data CRC errors are seen, which are
+ * probably due to the proximity of SIM card and eMMC.
+ * Hence, reducing the clock to 24.7Mhz from 49Mhz.
+ */
+ if (machine_is_msm7625a_ffa())
+ sdc3_plat_data.msmsdcc_fmax =
+ sdc3_plat_data.msmsdcc_fmid;
msm_add_sdcc(3, &sdc3_plat_data);
}
#endif
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 8d10d6a..0bfaa71 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -19,6 +19,7 @@
#include <linux/clkdev.h>
#include <linux/dma-mapping.h>
#include <linux/coresight.h>
+#include <linux/avtimer.h>
#include <mach/irqs-8064.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
@@ -103,6 +104,9 @@
#define MSM8064_PC_CNTR_PHYS (APQ8064_IMEM_PHYS + 0x664)
#define MSM8064_PC_CNTR_SIZE 0x40
#define MSM8064_RPM_MASTER_STATS_BASE 0x10BB00
+/* avtimer */
+#define AVTIMER_MSW_PHYSICAL_ADDRESS 0x2800900C
+#define AVTIMER_LSW_PHYSICAL_ADDRESS 0x28009008
static struct resource msm8064_resources_pccntr[] = {
{
@@ -3292,3 +3296,8 @@
.platform_data = &apq8064_cache_dump_pdata,
},
};
+
+struct dev_avtimer_data dev_avtimer_pdata = {
+ .avtimer_msw_phy_addr = AVTIMER_MSW_PHYSICAL_ADDRESS,
+ .avtimer_lsw_phy_addr = AVTIMER_LSW_PHYSICAL_ADDRESS,
+};
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index c59461a..2421646 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -2485,6 +2485,17 @@
.bus_port0 = MSM_BUS_MASTER_GRAPHICS_3D,
};
+static struct fs_driver_data gfx3d_fs_data_8960ab = {
+ .clks = (struct fs_clk_data[]){
+ { .name = "core_clk", .reset_rate = 27000000 },
+ { .name = "iface_clk" },
+ { .name = "bus_clk" },
+ { 0 }
+ },
+ .bus_port0 = MSM_BUS_MASTER_GRAPHICS_3D,
+ .bus_port1 = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+};
+
static struct fs_driver_data ijpeg_fs_data = {
.clks = (struct fs_clk_data[]){
{ .name = "core_clk" },
@@ -2583,7 +2594,7 @@
FS_8X60(FS_IJPEG, "vdd", "msm_gemini.0", &ijpeg_fs_data),
FS_8X60(FS_VFE, "vdd", "msm_vfe.0", &vfe_fs_data),
FS_8X60(FS_VPE, "vdd", "msm_vpe.0", &vpe_fs_data),
- FS_8X60(FS_GFX3D, "vdd", "kgsl-3d0.0", &gfx3d_fs_data),
+ FS_8X60(FS_GFX3D, "vdd", "kgsl-3d0.0", &gfx3d_fs_data_8960ab),
FS_8X60(FS_VED, "vdd", "msm_vidc.0", &ved_fs_data_8960ab),
};
unsigned msm8960ab_num_footswitch __initdata = ARRAY_SIZE(msm8960ab_footswitch);
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index c0d73c2..b676518 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -471,4 +471,5 @@
extern struct platform_device apq_cpudai_mi2s;
extern struct platform_device apq_cpudai_i2s_rx;
extern struct platform_device apq_cpudai_i2s_tx;
+extern struct dev_avtimer_data dev_avtimer_pdata;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
index 70bb406..d079e77 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
@@ -447,10 +447,8 @@
static int mport_mdp1[] = {MSM_BUS_MASTER_PORT_MDP_PORT1,};
static int mport_rotator[] = {MSM_BUS_MASTER_PORT_ROTATOR,};
static int mport_graphics_3d[] = {MSM_BUS_MASTER_PORT_GRAPHICS_3D,};
-static int pro_mport_graphics_3d[] = {
- MSM_BUS_MASTER_PORT_GRAPHICS_3D_PORT0,
- MSM_BUS_MASTER_PORT_GRAPHICS_3D,
-};
+static int pro_mport_graphics_3d[] = {MSM_BUS_MASTER_PORT_GRAPHICS_3D_PORT0,};
+static int pro_mport_graphics_3d_p1[] = {MSM_BUS_MASTER_PORT_GRAPHICS_3D,};
static int mport_jpeg_dec[] = {MSM_BUS_MASTER_PORT_JPEG_DEC,};
static int mport_graphics_2d_core0[] = {MSM_BUS_MASTER_PORT_GRAPHICS_2D_CORE0,};
static int mport_vfe[] = {MSM_BUS_MASTER_PORT_VFE,};
@@ -627,6 +625,13 @@
.num_tiers = ARRAY_SIZE(tier2),
},
{
+ .id = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+ .masterp = pro_mport_graphics_3d_p1,
+ .num_mports = ARRAY_SIZE(pro_mport_graphics_3d_p1),
+ .tier = tier2,
+ .num_tiers = ARRAY_SIZE(tier2),
+ },
+ {
.id = MSM_BUS_MASTER_JPEG_DEC,
.masterp = mport_jpeg_dec,
.num_mports = ARRAY_SIZE(mport_jpeg_dec),
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c b/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c
index 84f136a..5faee21 100644
--- a/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_in_proxy.c
@@ -72,31 +72,36 @@
if (pcm->start) {
if (pcm->dsp_idx == pcm->buffer_count)
pcm->dsp_idx = 0;
- rc = wait_event_timeout(pcm->wait,
- (pcm->dma_buf[pcm->dsp_idx].used == 0) ||
- atomic_read(&pcm->in_stopped), 1 * HZ);
- if (!rc) {
- pr_err("%s: wait_event_timeout failed\n", __func__);
- goto fail;
+ if (pcm->dma_buf[pcm->dsp_idx].used == 0) {
+ if (atomic_read(&pcm->in_stopped)) {
+ pr_err("%s: Driver closed - return\n",
+ __func__);
+ return HRTIMER_NORESTART;
+ }
+ rc = afe_rt_proxy_port_read(
+ pcm->dma_buf[pcm->dsp_idx].addr,
+ pcm->buffer_size);
+ if (rc < 0) {
+ pr_err("%s afe_rt_proxy_port_read fail\n",
+ __func__);
+ goto fail;
+ }
+ pcm->dma_buf[pcm->dsp_idx].used = 1;
+ pcm->dsp_idx++;
+ pr_debug("sending frame rec to DSP: poll_time: %d\n",
+ pcm->poll_time);
+ } else {
+ pr_err("Qcom: Used flag not reset retry after %d msec\n",
+ (pcm->poll_time/10));
+ goto fail_timer;
}
- if (atomic_read(&pcm->in_stopped)) {
- pr_err("%s: Driver closed - return\n", __func__);
- return HRTIMER_NORESTART;
- }
- rc = afe_rt_proxy_port_read(
- pcm->dma_buf[pcm->dsp_idx].addr,
- pcm->buffer_size);
- if (rc < 0) {
- pr_err("%s afe_rt_proxy_port_read fail\n", __func__);
- goto fail;
- }
- pcm->dma_buf[pcm->dsp_idx].used = 1;
- pcm->dsp_idx++;
- pr_debug("%s: sending frame rec to DSP: poll_time: %d\n",
- __func__, pcm->poll_time);
fail:
hrtimer_forward_now(hrt, ns_to_ktime(pcm->poll_time
* 1000));
+ return HRTIMER_RESTART;
+fail_timer:
+ hrtimer_forward_now(hrt, ns_to_ktime((pcm->poll_time/10)
+ * 1000));
return HRTIMER_RESTART;
} else {
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 4b03cfd..8f3c107 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -92,6 +92,8 @@
unsigned int freq_lo_jiffies;
unsigned int freq_hi_jiffies;
unsigned int rate_mult;
+ unsigned int prev_load;
+ unsigned int max_load;
int cpu;
unsigned int sample_type:1;
/*
@@ -125,17 +127,27 @@
static struct dbs_tuners {
unsigned int sampling_rate;
unsigned int up_threshold;
+ unsigned int up_threshold_multi_core;
unsigned int down_differential;
+ unsigned int down_differential_multi_core;
+ unsigned int optimal_freq;
+ unsigned int up_threshold_any_cpu_load;
+ unsigned int sync_freq;
unsigned int ignore_nice;
unsigned int sampling_down_factor;
int powersave_bias;
unsigned int io_is_busy;
} dbs_tuners_ins = {
+ .up_threshold_multi_core = DEF_FREQUENCY_UP_THRESHOLD,
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
.down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
+ .down_differential_multi_core = MICRO_FREQUENCY_DOWN_DIFFERENTIAL,
+ .up_threshold_any_cpu_load = DEF_FREQUENCY_UP_THRESHOLD,
.ignore_nice = 0,
.powersave_bias = 0,
+ .sync_freq = 0,
+ .optimal_freq = 0,
};
static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
@@ -293,9 +305,13 @@
show_one(sampling_rate, sampling_rate);
show_one(io_is_busy, io_is_busy);
show_one(up_threshold, up_threshold);
+show_one(up_threshold_multi_core, up_threshold_multi_core);
show_one(down_differential, down_differential);
show_one(sampling_down_factor, sampling_down_factor);
show_one(ignore_nice_load, ignore_nice);
+show_one(optimal_freq, optimal_freq);
+show_one(up_threshold_any_cpu_load, up_threshold_any_cpu_load);
+show_one(sync_freq, sync_freq);
static ssize_t show_powersave_bias
(struct kobject *kobj, struct attribute *attr, char *buf)
@@ -371,6 +387,19 @@
return count;
}
+static ssize_t store_sync_freq(struct kobject *a, struct attribute *b,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+
+ ret = sscanf(buf, "%u", &input);
+ if (ret != 1)
+ return -EINVAL;
+ dbs_tuners_ins.sync_freq = input;
+ return count;
+}
+
static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b,
const char *buf, size_t count)
{
@@ -384,6 +413,19 @@
return count;
}
+static ssize_t store_optimal_freq(struct kobject *a, struct attribute *b,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+
+ ret = sscanf(buf, "%u", &input);
+ if (ret != 1)
+ return -EINVAL;
+ dbs_tuners_ins.optimal_freq = input;
+ return count;
+}
+
static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
const char *buf, size_t count)
{
@@ -399,6 +441,36 @@
return count;
}
+static ssize_t store_up_threshold_multi_core(struct kobject *a,
+ struct attribute *b, const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+ ret = sscanf(buf, "%u", &input);
+
+ if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
+ input < MIN_FREQUENCY_UP_THRESHOLD) {
+ return -EINVAL;
+ }
+ dbs_tuners_ins.up_threshold_multi_core = input;
+ return count;
+}
+
+static ssize_t store_up_threshold_any_cpu_load(struct kobject *a,
+ struct attribute *b, const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+ ret = sscanf(buf, "%u", &input);
+
+ if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
+ input < MIN_FREQUENCY_UP_THRESHOLD) {
+ return -EINVAL;
+ }
+ dbs_tuners_ins.up_threshold_any_cpu_load = input;
+ return count;
+}
+
static ssize_t store_down_differential(struct kobject *a, struct attribute *b,
const char *buf, size_t count)
{
@@ -581,6 +653,10 @@
define_one_global_rw(sampling_down_factor);
define_one_global_rw(ignore_nice_load);
define_one_global_rw(powersave_bias);
+define_one_global_rw(up_threshold_multi_core);
+define_one_global_rw(optimal_freq);
+define_one_global_rw(up_threshold_any_cpu_load);
+define_one_global_rw(sync_freq);
static struct attribute *dbs_attributes[] = {
&sampling_rate_min.attr,
@@ -591,6 +667,10 @@
&ignore_nice_load.attr,
&powersave_bias.attr,
&io_is_busy.attr,
+ &up_threshold_multi_core.attr,
+ &optimal_freq.attr,
+ &up_threshold_any_cpu_load.attr,
+ &sync_freq.attr,
NULL
};
@@ -619,7 +699,7 @@
unsigned int max_load_freq;
/* Current load across this CPU */
unsigned int cur_load = 0;
-
+ unsigned int max_load_other_cpu = 0;
struct cpufreq_policy *policy;
unsigned int j;
@@ -696,7 +776,8 @@
continue;
cur_load = 100 * (wall_time - idle_time) / wall_time;
-
+ j_dbs_info->max_load = max(cur_load, j_dbs_info->prev_load);
+ j_dbs_info->prev_load = cur_load;
freq_avg = __cpufreq_driver_getavg(policy, j);
if (freq_avg <= 0)
freq_avg = policy->cur;
@@ -705,11 +786,37 @@
if (load_freq > max_load_freq)
max_load_freq = load_freq;
}
+
+ for_each_online_cpu(j) {
+ struct cpu_dbs_info_s *j_dbs_info;
+ j_dbs_info = &per_cpu(od_cpu_dbs_info, j);
+
+ if (j == policy->cpu)
+ continue;
+
+ if (max_load_other_cpu < j_dbs_info->max_load)
+ max_load_other_cpu = j_dbs_info->max_load;
+ /*
+ * The other cpu could be running at higher frequency
+ * but may not have completed it's sampling_down_factor.
+ * For that case consider other cpu is loaded so that
+ * frequency imbalance does not occur.
+ */
+
+ if ((j_dbs_info->cur_policy != NULL)
+ && (j_dbs_info->cur_policy->cur ==
+ j_dbs_info->cur_policy->max)) {
+
+ if (policy->cur >= dbs_tuners_ins.optimal_freq)
+ max_load_other_cpu =
+ dbs_tuners_ins.up_threshold_any_cpu_load;
+ }
+ }
+
/* calculate the scaled load across CPU */
load_at_max_freq = (cur_load * policy->cur)/policy->cpuinfo.max_freq;
cpufreq_notify_utilization(policy, load_at_max_freq);
-
/* Check for frequency increase */
if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
/* If switching to max speed, apply sampling_down_factor */
@@ -720,6 +827,25 @@
return;
}
+ if (num_online_cpus() > 1) {
+
+ if (max_load_other_cpu >
+ dbs_tuners_ins.up_threshold_any_cpu_load) {
+ if (policy->cur < dbs_tuners_ins.sync_freq)
+ dbs_freq_increase(policy,
+ dbs_tuners_ins.sync_freq);
+ return;
+ }
+
+ if (max_load_freq > dbs_tuners_ins.up_threshold_multi_core *
+ policy->cur) {
+ if (policy->cur < dbs_tuners_ins.optimal_freq)
+ dbs_freq_increase(policy,
+ dbs_tuners_ins.optimal_freq);
+ return;
+ }
+ }
+
/* Check for frequency decrease */
/* if we cannot reduce the frequency anymore, break out early */
if (policy->cur == policy->min)
@@ -744,6 +870,20 @@
if (freq_next < policy->min)
freq_next = policy->min;
+ if (num_online_cpus() > 1) {
+ if (max_load_other_cpu >
+ (dbs_tuners_ins.up_threshold_multi_core -
+ dbs_tuners_ins.down_differential) &&
+ freq_next < dbs_tuners_ins.sync_freq)
+ freq_next = dbs_tuners_ins.sync_freq;
+
+ if (max_load_freq >
+ (dbs_tuners_ins.up_threshold_multi_core -
+ dbs_tuners_ins.down_differential_multi_core) *
+ policy->cur)
+ freq_next = dbs_tuners_ins.optimal_freq;
+
+ }
if (!dbs_tuners_ins.powersave_bias) {
__cpufreq_driver_target(policy, freq_next,
CPUFREQ_RELATION_L);
@@ -997,6 +1137,12 @@
max(min_sampling_rate,
latency * LATENCY_MULTIPLIER);
dbs_tuners_ins.io_is_busy = should_io_be_busy();
+
+ if (dbs_tuners_ins.optimal_freq == 0)
+ dbs_tuners_ins.optimal_freq = policy->min;
+
+ if (dbs_tuners_ins.sync_freq == 0)
+ dbs_tuners_ins.sync_freq = policy->min;
}
if (!cpu)
rc = input_register_handler(&dbs_input_handler);
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 345c07d..0b691f3 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
#include <linux/vmalloc.h>
#include <linux/iommu.h>
#include <linux/pfn.h>
+#include <linux/dma-mapping.h>
#include "ion_priv.h"
#include <asm/mach/map.h>
@@ -80,8 +81,13 @@
goto err3;
sg_set_page(sg, data->pages[i], PAGE_SIZE, 0);
+ sg_dma_address(sg) = sg_phys(sg);
}
+ if (!ION_IS_CACHED(flags))
+ dma_sync_sg_for_device(NULL, table->sgl, table->nents,
+ DMA_BIDIRECTIONAL);
+
buffer->priv_virt = data;
return 0;
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index ad2ef83..8b63216 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -518,14 +518,26 @@
return ret;
}
+void *ion_system_contig_heap_map_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ return buffer->priv_virt;
+}
+
+void ion_system_contig_heap_unmap_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ return;
+}
+
static struct ion_heap_ops kmalloc_ops = {
.allocate = ion_system_contig_heap_allocate,
.free = ion_system_contig_heap_free,
.phys = ion_system_contig_heap_phys,
.map_dma = ion_system_contig_heap_map_dma,
.unmap_dma = ion_system_heap_unmap_dma,
- .map_kernel = ion_system_heap_map_kernel,
- .unmap_kernel = ion_system_heap_unmap_kernel,
+ .map_kernel = ion_system_contig_heap_map_kernel,
+ .unmap_kernel = ion_system_contig_heap_unmap_kernel,
.map_user = ion_system_contig_heap_map_user,
.cache_op = ion_system_contig_heap_cache_ops,
.print_debug = ion_system_contig_print_debug,
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index e422fd26..697587b 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -777,19 +777,6 @@
if (pdata_needs_to_be_freed)
free_pdata(pdata);
- /* Check if each heap has been removed from the memblock */
- for (i = 0; i < num_heaps; i++) {
- struct ion_platform_heap *heap_data = &pdata->heaps[i];
- if (!heap_data->base)
- continue;
- err = memblock_overlaps_memory(heap_data->base,
- heap_data->size);
- if (err) {
- panic("ION heap %s not removed from memblock\n",
- heap_data->name);
- }
- }
-
check_for_heap_overlap(pdata->heaps, num_heaps);
platform_set_drvdata(pdev, idev);
return 0;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 060e89a..cced7ef 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -29,6 +29,7 @@
#include "kgsl_cffdump.h"
#include "kgsl_sharedmem.h"
#include "kgsl_iommu.h"
+#include "kgsl_trace.h"
#include "adreno.h"
#include "adreno_pm4types.h"
@@ -2067,6 +2068,8 @@
if (!in_interrupt())
kgsl_pre_hwaccess(device);
+ trace_kgsl_regwrite(device, offsetwords, value);
+
kgsl_cffdump_regwrite(device->id, offsetwords << 2, value);
reg = (unsigned int *)(device->reg_virt + (offsetwords << 2));
@@ -2157,7 +2160,6 @@
int status;
unsigned int ref_ts, enableflag;
unsigned int context_id;
- struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
mutex_lock(&device->mutex);
context_id = _get_context_id(context);
@@ -2204,13 +2206,9 @@
cmds[0] = cp_type3_packet(CP_NOP, 1);
cmds[1] = 0;
- if (adreno_dev->drawctxt_active)
+ if (context)
adreno_ringbuffer_issuecmds_intr(device,
context, &cmds[0], 2);
- else
- /* We would never call this function if there
- * was no active contexts running */
- BUG();
}
}
unlock:
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 1bccd4d..31491d5 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -897,8 +897,6 @@
kgsl_regwrite(mmu->device, MH_MMU_MPU_END,
mh->mpu_base + mh->mpu_range);
- } else {
- kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
}
mmu->hwpagetable = mmu->defaultpagetable;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index f04fae1..4919c24 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -688,6 +688,9 @@
clkstats->on_time_old = on_time;
clkstats->elapsed_old = clkstats->elapsed;
clkstats->elapsed = 0;
+
+ trace_kgsl_gpubusy(device, clkstats->on_time_old,
+ clkstats->elapsed_old);
}
/* Track the amount of time the gpu is on vs the total system time. *
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 9662fce..bbef139 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -274,6 +274,32 @@
)
);
+TRACE_EVENT(kgsl_gpubusy,
+ TP_PROTO(struct kgsl_device *device, unsigned int busy,
+ unsigned int elapsed),
+
+ TP_ARGS(device, busy, elapsed),
+
+ TP_STRUCT__entry(
+ __string(device_name, device->name)
+ __field(unsigned int, busy)
+ __field(unsigned int, elapsed)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, device->name);
+ __entry->busy = busy;
+ __entry->elapsed = elapsed;
+ ),
+
+ TP_printk(
+ "d_name=%s busy=%d elapsed=%d",
+ __get_str(device_name),
+ __entry->busy,
+ __entry->elapsed
+ )
+);
+
DECLARE_EVENT_CLASS(kgsl_pwrstate_template,
TP_PROTO(struct kgsl_device *device, unsigned int state),
@@ -608,6 +634,31 @@
)
);
+TRACE_EVENT(kgsl_regwrite,
+
+ TP_PROTO(struct kgsl_device *device, unsigned int offset,
+ unsigned int value),
+
+ TP_ARGS(device, offset, value),
+
+ TP_STRUCT__entry(
+ __string(device_name, device->name)
+ __field(unsigned int, offset)
+ __field(unsigned int, value)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, device->name);
+ __entry->offset = offset;
+ __entry->value = value;
+ ),
+
+ TP_printk(
+ "d_name=%s reg=%x value=%x",
+ __get_str(device_name), __entry->offset, __entry->value
+ )
+);
+
#endif /* _KGSL_TRACE_H */
/* This part must be outside protection */
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index e0a341a..711b3007 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -430,7 +430,15 @@
core);
goto exit;
}
-
+ if (!inst->in_reconfig) {
+ rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to move inst: %p to relase res done\n",
+ inst);
+ goto exit;
+ }
+ }
switch (b->type) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
break;
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index f436cf3..41518d7 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -1552,7 +1552,13 @@
int rc = 0;
int i;
struct vidc_buffer_addr_info buffer_info;
-
+ rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to move inst: %p to release res done state\n",
+ inst);
+ goto exit;
+ }
switch (b->type) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
break;
@@ -1581,6 +1587,7 @@
dprintk(VIDC_ERR, "Buffer type not recognized: %d\n", b->type);
break;
}
+exit:
return rc;
}
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 64897c7..6ecea30 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -559,6 +559,8 @@
if (inst->state != MSM_VIDC_CORE_INVALID &&
core->state != VIDC_CORE_INVALID)
rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
+ else
+ rc = msm_comm_force_cleanup(inst);
if (rc)
dprintk(VIDC_ERR,
"Failed to move video instance to uninit state\n");
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 46a88c2..d797ba7 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -1125,6 +1125,11 @@
dprintk(VIDC_ERR, "Invalid params, core:%p\n", core);
return -EINVAL;
}
+ if (core->state == VIDC_CORE_INVALID) {
+ dprintk(VIDC_ERR,
+ "Core is in bad state. Cannot unset ocmem\n");
+ return -EIO;
+ }
rhdr.resource_id = VIDC_RESOURCE_OCMEM;
rhdr.resource_handle = (u32) &core->resources.ocmem;
init_completion(
@@ -1345,6 +1350,11 @@
return rc;
}
+int msm_comm_force_cleanup(struct msm_vidc_inst *inst)
+{
+ return msm_vidc_deinit_core(inst);
+}
+
static enum hal_domain get_hal_domain(int session_type)
{
enum hal_domain domain;
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.h b/drivers/media/video/msm_vidc/msm_vidc_common.h
index 916a3ca..d225a51 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.h
@@ -41,6 +41,7 @@
enum instance_state state);
int msm_comm_unset_ocmem(struct msm_vidc_core *core);
int msm_comm_free_ocmem(struct msm_vidc_core *core);
+int msm_comm_force_cleanup(struct msm_vidc_inst *inst);
enum hal_extradata_id msm_comm_get_hal_extradata_index(
enum v4l2_mpeg_vidc_extradata index);
#define IS_PRIV_CTRL(idx) (\
diff --git a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c b/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
index 3bedb92..333bad9 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
+++ b/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
@@ -149,7 +149,6 @@
static void hal_process_sys_error(struct hal_device *device)
{
struct msm_vidc_cb_cmd_done cmd_done;
- disable_irq_nosync(device->hal_data->irq);
memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
cmd_done.device_id = device->device_id;
device->callback(SYS_ERROR, &cmd_done);
@@ -177,11 +176,12 @@
switch (pkt->event_id) {
case HFI_EVENT_SYS_ERROR:
- dprintk(VIDC_INFO, "HFI_EVENT_SYS_ERROR");
+ dprintk(VIDC_ERR, "HFI_EVENT_SYS_ERROR: %d\n",
+ pkt->event_data1);
hal_process_sys_error(device);
break;
case HFI_EVENT_SESSION_ERROR:
- dprintk(VIDC_INFO, "HFI_EVENT_SESSION_ERROR");
+ dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR");
hal_process_session_error(device, pkt);
break;
case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
@@ -192,7 +192,7 @@
dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED");
break;
default:
- dprintk(VIDC_INFO, "hal_process_event_notify:unkown_event_id");
+ dprintk(VIDC_WARN, "hal_process_event_notify:unkown_event_id");
break;
}
}
diff --git a/drivers/media/video/msm_wfd/enc-mfc-subdev.c b/drivers/media/video/msm_wfd/enc-mfc-subdev.c
index 21fc719..aadf5ed 100644
--- a/drivers/media/video/msm_wfd/enc-mfc-subdev.c
+++ b/drivers/media/video/msm_wfd/enc-mfc-subdev.c
@@ -903,25 +903,13 @@
struct vcd_property_req_i_frame vcd_property_req_i_frame;
struct vcd_property_hdr vcd_property_hdr;
- int rc = 0;
- switch (type) {
- case V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED:
- /*So...nothing to do?*/
- break;
- case V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME:
- vcd_property_hdr.prop_id = VCD_I_REQ_IFRAME;
- vcd_property_hdr.sz = sizeof(struct vcd_property_req_i_frame);
- vcd_property_req_i_frame.req_i_frame = 1;
+ vcd_property_hdr.prop_id = VCD_I_REQ_IFRAME;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_req_i_frame);
+ vcd_property_req_i_frame.req_i_frame = 1;
- rc = vcd_set_property(client_ctx->vcd_handle,
- &vcd_property_hdr, &vcd_property_req_i_frame);
- break;
- case V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED:
- default:
- rc = -ENOTSUPP;
- }
+ return vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_req_i_frame);
- return rc;
}
static long venc_set_bitrate(struct video_client_ctx *client_ctx,
@@ -1348,10 +1336,10 @@
int level = 0;
switch (value) {
- case V4L2_CID_MPEG_QCOM_PERF_LEVEL_PERFORMANCE:
+ case V4L2_CID_MPEG_VIDC_PERF_LEVEL_PERFORMANCE:
level = VCD_PERF_LEVEL2;
break;
- case V4L2_CID_MPEG_QCOM_PERF_LEVEL_TURBO:
+ case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
level = VCD_PERF_LEVEL_TURBO;
break;
default:
@@ -2304,7 +2292,7 @@
case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
rc = venc_set_codec_profile(client_ctx, ctrl->id, ctrl->value);
break;
- case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+ case V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME:
rc = venc_request_frame(client_ctx, ctrl->value);
break;
case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
@@ -2335,7 +2323,7 @@
rc = venc_set_multislicing_mode(client_ctx, ctrl->id,
ctrl->value);
break;
- case V4L2_CID_MPEG_QCOM_SET_PERF_LEVEL:
+ case V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL:
rc = venc_set_max_perf_level(client_ctx, ctrl->value);
break;
case V4L2_CID_MPEG_VIDC_VIDEO_H264_AU_DELIMITER:
diff --git a/drivers/media/video/msm_wfd/enc-venus-subdev.c b/drivers/media/video/msm_wfd/enc-venus-subdev.c
index 64c18da..480fe35 100644
--- a/drivers/media/video/msm_wfd/enc-venus-subdev.c
+++ b/drivers/media/video/msm_wfd/enc-venus-subdev.c
@@ -136,7 +136,7 @@
msm_vidc_dqevent(inst->vidc_context, &event);
if (event.type == V4L2_EVENT_MSM_VIDC_CLOSE_DONE) {
- WFD_MSG_ERR("enc callback thread shutting " \
+ WFD_MSG_DBG("enc callback thread shutting " \
"down normally\n");
bail_out = true;
} else {
diff --git a/drivers/media/video/msm_wfd/wfd-ioctl.c b/drivers/media/video/msm_wfd/wfd-ioctl.c
index bb2e606..74194ff 100644
--- a/drivers/media/video/msm_wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm_wfd/wfd-ioctl.c
@@ -536,7 +536,7 @@
struct mem_region mregion;
if (minfo == NULL) {
- WFD_MSG_ERR("not freeing buffers since allocation failed");
+ WFD_MSG_DBG("not freeing buffers since allocation failed");
return;
}
diff --git a/drivers/media/video/msm_wfd/wfd-util.c b/drivers/media/video/msm_wfd/wfd-util.c
index 5c00e5c..28a6084 100644
--- a/drivers/media/video/msm_wfd/wfd-util.c
+++ b/drivers/media/video/msm_wfd/wfd-util.c
@@ -198,7 +198,7 @@
int wfd_stats_deinit(struct wfd_stats *stats)
{
- WFD_MSG_ERR("Latencies: avg enc. latency %d",
+ WFD_MSG_DBG("Latencies: avg enc. latency %d",
stats->enc_avg_latency);
/* Delete all debugfs files in one shot :) */
if (stats->d_parent)
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 3715417..c415952 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -235,6 +235,8 @@
uint32_t user_virt_sb_base;
size_t sb_length;
struct ion_handle *ihandle; /* Retrieve phy addr */
+ bool perf_enabled;
+ bool fast_load_enabled;
};
struct qseecom_listener_handle {
@@ -266,8 +268,8 @@
};
/* Function proto types */
-static int qsee_vote_for_clock(int32_t);
-static void qsee_disable_clock_vote(int32_t);
+static int qsee_vote_for_clock(struct qseecom_dev_handle *, int32_t);
+static void qsee_disable_clock_vote(struct qseecom_dev_handle *, int32_t);
static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
struct qseecom_register_listener_req *svc)
@@ -701,7 +703,7 @@
return -EFAULT;
}
/* Vote for the SFPB clock */
- ret = qsee_vote_for_clock(CLK_SFPB);
+ ret = qsee_vote_for_clock(data, CLK_SFPB);
if (ret)
pr_warning("Unable to vote for SFPB clock");
req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
@@ -734,7 +736,7 @@
load_img_req.ifd_data_fd);
if (IS_ERR_OR_NULL(ihandle)) {
pr_err("Ion client could not retrieve the handle\n");
- qsee_disable_clock_vote(CLK_SFPB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
return -ENOMEM;
}
@@ -762,7 +764,7 @@
pr_err("scm_call rsp.result is QSEOS_RESULT_FAILURE\n");
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
- qsee_disable_clock_vote(CLK_SFPB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
return -EFAULT;
}
@@ -773,7 +775,7 @@
ret);
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
- qsee_disable_clock_vote(CLK_SFPB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
return ret;
}
}
@@ -783,7 +785,7 @@
resp.result);
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
- qsee_disable_clock_vote(CLK_SFPB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
return -EFAULT;
}
@@ -792,7 +794,7 @@
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
pr_err("kmalloc failed\n");
- qsee_disable_clock_vote(CLK_SFPB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
return -ENOMEM;
}
entry->app_id = app_id;
@@ -815,10 +817,10 @@
if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {
pr_err("copy_to_user failed\n");
kzfree(entry);
- qsee_disable_clock_vote(CLK_SFPB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
return -EFAULT;
}
- qsee_disable_clock_vote(CLK_SFPB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
return 0;
}
@@ -1411,7 +1413,7 @@
/* Populate the remaining parameters */
load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
memcpy(load_req.app_name, appname, MAX_APP_NAME_SIZE);
- ret = qsee_vote_for_clock(CLK_SFPB);
+ ret = qsee_vote_for_clock(data, CLK_SFPB);
if (ret) {
kzfree(img_data);
pr_warning("Unable to vote for SFPB clock");
@@ -1425,7 +1427,7 @@
kzfree(img_data);
if (ret) {
pr_err("scm_call to load failed : ret %d\n", ret);
- qsee_disable_clock_vote(CLK_SFPB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
return -EIO;
}
@@ -1448,7 +1450,7 @@
ret = -EINVAL;
break;
}
- qsee_disable_clock_vote(CLK_SFPB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
return ret;
}
@@ -1713,6 +1715,10 @@
pr_err("Unable to find the handle, exiting\n");
else
ret = qseecom_unload_app(data);
+ if (data->client.fast_load_enabled == true)
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ if (data->client.perf_enabled == true)
+ qsee_disable_clock_vote(data, CLK_DFAB);
if (ret == 0) {
kzfree(data);
kzfree(*handle);
@@ -1770,9 +1776,9 @@
return -EINVAL;
}
if (high)
- return qsee_vote_for_clock(CLK_DFAB);
+ return qsee_vote_for_clock(handle->dev, CLK_DFAB);
else {
- qsee_disable_clock_vote(CLK_DFAB);
+ qsee_disable_clock_vote(handle->dev, CLK_DFAB);
return 0;
}
}
@@ -1802,7 +1808,8 @@
return 0;
}
-static int qsee_vote_for_clock(int32_t clk_type)
+static int qsee_vote_for_clock(struct qseecom_dev_handle *data,
+ int32_t clk_type)
{
int ret = 0;
@@ -1826,10 +1833,13 @@
if (ret)
pr_err("DFAB Bandwidth req failed (%d)\n",
ret);
- else
+ else {
qsee_bw_count++;
+ data->client.perf_enabled = true;
+ }
} else {
qsee_bw_count++;
+ data->client.perf_enabled = true;
}
mutex_unlock(&qsee_bw_mutex);
break;
@@ -1850,10 +1860,13 @@
if (ret)
pr_err("SFPB Bandwidth req failed (%d)\n",
ret);
- else
+ else {
qsee_sfpb_bw_count++;
+ data->client.fast_load_enabled = true;
+ }
} else {
qsee_sfpb_bw_count++;
+ data->client.fast_load_enabled = true;
}
mutex_unlock(&qsee_bw_mutex);
break;
@@ -1864,7 +1877,8 @@
return ret;
}
-static void qsee_disable_clock_vote(int32_t clk_type)
+static void qsee_disable_clock_vote(struct qseecom_dev_handle *data,
+ int32_t clk_type)
{
int32_t ret = 0;
@@ -1880,7 +1894,7 @@
return;
}
- if ((qsee_bw_count > 0) && (qsee_bw_count-- == 1)) {
+ if (qsee_bw_count == 1) {
if (qsee_sfpb_bw_count > 0)
ret = msm_bus_scale_client_update_request(
qsee_perf_client, 2);
@@ -1894,6 +1908,13 @@
if (ret)
pr_err("SFPB Bandwidth req fail (%d)\n",
ret);
+ else {
+ qsee_bw_count--;
+ data->client.perf_enabled = false;
+ }
+ } else {
+ qsee_bw_count--;
+ data->client.perf_enabled = false;
}
mutex_unlock(&qsee_bw_mutex);
break;
@@ -1904,7 +1925,7 @@
mutex_unlock(&qsee_bw_mutex);
return;
}
- if ((qsee_sfpb_bw_count > 0) && (qsee_sfpb_bw_count-- == 1)) {
+ if (qsee_sfpb_bw_count == 1) {
if (qsee_bw_count > 0)
ret = msm_bus_scale_client_update_request(
qsee_perf_client, 1);
@@ -1918,6 +1939,13 @@
if (ret)
pr_err("SFPB Bandwidth req fail (%d)\n",
ret);
+ else {
+ qsee_sfpb_bw_count--;
+ data->client.fast_load_enabled = false;
+ }
+ } else {
+ qsee_sfpb_bw_count--;
+ data->client.fast_load_enabled = false;
}
mutex_unlock(&qsee_bw_mutex);
break;
@@ -2246,7 +2274,7 @@
}
case QSEECOM_IOCTL_PERF_ENABLE_REQ:{
atomic_inc(&data->ioctl_count);
- ret = qsee_vote_for_clock(CLK_DFAB);
+ ret = qsee_vote_for_clock(data, CLK_DFAB);
if (ret)
pr_err("Failed to vote for DFAB clock%d\n", ret);
atomic_dec(&data->ioctl_count);
@@ -2254,7 +2282,7 @@
}
case QSEECOM_IOCTL_PERF_DISABLE_REQ:{
atomic_inc(&data->ioctl_count);
- qsee_disable_clock_vote(CLK_DFAB);
+ qsee_disable_clock_vote(data, CLK_DFAB);
atomic_dec(&data->ioctl_count);
break;
}
@@ -2356,6 +2384,11 @@
return ret;
}
}
+ if (data->client.fast_load_enabled == true)
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ if (data->client.perf_enabled == true)
+ qsee_disable_clock_vote(data, CLK_DFAB);
+
if (qseecom.qseos_version == QSEOS_VERSION_13) {
mutex_lock(&pil_access_lock);
if (pil_ref_cnt == 1)
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 872a9b5..9394986 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -85,5 +85,11 @@
for the IPA core.
Kernel and user-space processes can call the IPA driver
to configure IPA core.
+config MSM_AVTIMER
+ tristate "Avtimer Driver"
+ depends on ARCH_MSM8960
+ help
+ This driver gets the Q6 out of power collapsed state and
+ exposes ioctl control to read avtimer tick.
endmenu
diff --git a/drivers/platform/msm/Makefile b/drivers/platform/msm/Makefile
index 0a755d3..919c07f 100644
--- a/drivers/platform/msm/Makefile
+++ b/drivers/platform/msm/Makefile
@@ -8,3 +8,4 @@
obj-$(CONFIG_QPNP_PWM) += qpnp-pwm.o
obj-$(CONFIG_QPNP_POWER_ON) += qpnp-power-on.o
obj-$(CONFIG_QPNP_CLKDIV) += qpnp-clkdiv.o
+obj-$(CONFIG_MSM_AVTIMER) += avtimer.o
diff --git a/drivers/platform/msm/avtimer.c b/drivers/platform/msm/avtimer.c
new file mode 100644
index 0000000..f513ceb
--- /dev/null
+++ b/drivers/platform/msm/avtimer.c
@@ -0,0 +1,369 @@
+
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/avtimer.h>
+#include <mach/qdsp6v2/apr.h>
+
+#define DEVICE_NAME "avtimer"
+
+
+#define ADSP_CMD_SET_POWER_COLLAPSE_STATE 0x0001115C
+
+static int major; /* Major number assigned to our device driver */
+struct avtimer_t {
+ struct cdev myc;
+ struct class *avtimer_class;
+ struct mutex avtimer_lock;
+ int avtimer_open_cnt;
+ struct dev_avtimer_data *avtimer_pdata;
+};
+static struct avtimer_t avtimer;
+
+static struct apr_svc *core_handle;
+
+struct adsp_power_collapse {
+ struct apr_hdr hdr;
+ uint32_t power_collapse;
+};
+
+static int32_t avcs_core_callback(struct apr_client_data *data, void *priv)
+{
+ uint32_t *payload;
+
+ pr_debug("core msg: payload len = %u, apr resp opcode = 0x%X\n",
+ data->payload_size, data->opcode);
+
+ switch (data->opcode) {
+
+ case APR_BASIC_RSP_RESULT:{
+
+ if (data->payload_size == 0) {
+ pr_err("%s: APR_BASIC_RSP_RESULT No Payload ",
+ __func__);
+ return 0;
+ }
+
+ payload = data->payload;
+
+ switch (payload[0]) {
+
+ case ADSP_CMD_SET_POWER_COLLAPSE_STATE:
+ pr_debug("CMD_SET_POWER_COLLAPSE_STATE status[0x%x]\n",
+ payload[1]);
+ break;
+ default:
+ pr_err("Invalid cmd rsp[0x%x][0x%x]\n",
+ payload[0], payload[1]);
+ break;
+ }
+ break;
+ }
+ case RESET_EVENTS:{
+ pr_debug("Reset event received in Core service");
+ apr_reset(core_handle);
+ core_handle = NULL;
+ break;
+ }
+
+ default:
+ pr_err("Message id from adsp core svc: %d\n", data->opcode);
+ break;
+ }
+
+ return 0;
+}
+
+int avcs_core_open(void)
+{
+ if (core_handle == NULL)
+ core_handle = apr_register("ADSP", "CORE",
+ avcs_core_callback, 0xFFFFFFFF, NULL);
+
+ pr_debug("Open_q %p\n", core_handle);
+ if (core_handle == NULL) {
+ pr_err("%s: Unable to register CORE\n", __func__);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+int avcs_core_disable_power_collapse(int disable)
+{
+ struct adsp_power_collapse pc;
+ int rc = 0;
+
+ if (core_handle) {
+ pc.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ pc.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(uint32_t));
+ pc.hdr.src_port = 0;
+ pc.hdr.dest_port = 0;
+ pc.hdr.token = 0;
+ pc.hdr.opcode = ADSP_CMD_SET_POWER_COLLAPSE_STATE;
+ /*
+ * When power_collapse set to 1 -- If the aDSP is in the power
+ * collapsed state when this command is received, it is awakened
+ * from this state. The aDSP does not power collapse again until
+ * the client revokes this command
+ * When power_collapse set to 0 -- This indicates to the aDSP
+ * that the remote client does not need it to be out of power
+ * collapse any longer. This may not always put the aDSP into
+ * power collapse; the aDSP must honor an internal client's
+ * power requirements as well.
+ */
+ pc.power_collapse = disable;
+ rc = apr_send_pkt(core_handle, (uint32_t *)&pc);
+ if (rc < 0) {
+ pr_debug("disable power collapse = %d failed\n",
+ disable);
+ return rc;
+ }
+ pr_debug("disable power collapse = %d\n", disable);
+ }
+ return 0;
+}
+
+static int avtimer_open(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+ struct avtimer_t *pavtimer = &avtimer;
+
+ pr_debug("avtimer_open\n");
+ mutex_lock(&pavtimer->avtimer_lock);
+
+ if (pavtimer->avtimer_open_cnt != 0) {
+ pavtimer->avtimer_open_cnt++;
+ pr_debug("%s: opened avtimer open count=%d\n",
+ __func__, pavtimer->avtimer_open_cnt);
+ mutex_unlock(&pavtimer->avtimer_lock);
+ return 0;
+ }
+ try_module_get(THIS_MODULE);
+
+ rc = avcs_core_open();
+ if (core_handle)
+ rc = avcs_core_disable_power_collapse(1);
+
+ pavtimer->avtimer_open_cnt++;
+ pr_debug("%s: opened avtimer open count=%d\n",
+ __func__, pavtimer->avtimer_open_cnt);
+ mutex_unlock(&pavtimer->avtimer_lock);
+ pr_debug("avtimer_open leave rc=%d\n", rc);
+
+ return rc;
+}
+
+static int avtimer_release(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+ struct avtimer_t *pavtimer = &avtimer;
+
+ mutex_lock(&pavtimer->avtimer_lock);
+ pavtimer->avtimer_open_cnt--;
+
+ if (core_handle && pavtimer->avtimer_open_cnt == 0)
+ rc = avcs_core_disable_power_collapse(0);
+
+ pr_debug("device_release(%p,%p) open count=%d\n",
+ inode, file, pavtimer->avtimer_open_cnt);
+
+ module_put(THIS_MODULE);
+
+ mutex_unlock(&pavtimer->avtimer_lock);
+
+ return rc;
+}
+
+/*
+ * ioctl call provides GET_AVTIMER
+ */
+static long avtimer_ioctl(struct file *file, unsigned int ioctl_num,
+ unsigned long ioctl_param)
+{
+ struct avtimer_t *pavtimer = &avtimer;
+ pr_debug("avtimer_ioctl: ioctlnum=%d,param=%lx\n",
+ ioctl_num, ioctl_param);
+
+ switch (ioctl_num) {
+ case IOCTL_GET_AVTIMER_TICK:
+ {
+ void __iomem *p_avtimer_msw = NULL, *p_avtimer_lsw = NULL;
+ uint32_t avtimer_msw_1st = 0, avtimer_lsw = 0;
+ uint32_t avtimer_msw_2nd = 0;
+ uint64_t avtimer_tick;
+
+ if (pavtimer->avtimer_pdata) {
+ p_avtimer_lsw = ioremap(
+ pavtimer->avtimer_pdata->avtimer_lsw_phy_addr, 4);
+ p_avtimer_msw = ioremap(
+ pavtimer->avtimer_pdata->avtimer_msw_phy_addr, 4);
+ }
+ if (!p_avtimer_lsw || !p_avtimer_msw) {
+ pr_err("ioremap failed\n");
+ return -EIO;
+ }
+ do {
+ avtimer_msw_1st = ioread32(p_avtimer_msw);
+ avtimer_lsw = ioread32(p_avtimer_lsw);
+ avtimer_msw_2nd = ioread32(p_avtimer_msw);
+ } while (avtimer_msw_1st != avtimer_msw_2nd);
+
+ avtimer_tick =
+ ((uint64_t) avtimer_msw_1st << 32) | avtimer_lsw;
+
+ pr_debug("AV Timer tick: msw: %d, lsw: %d\n", avtimer_msw_1st,
+ avtimer_lsw);
+ if (copy_to_user((void *) ioctl_param, &avtimer_tick,
+ sizeof(avtimer_tick))) {
+ pr_err("copy_to_user failed\n");
+ iounmap(p_avtimer_lsw);
+ iounmap(p_avtimer_msw);
+ return -EFAULT;
+ }
+ iounmap(p_avtimer_lsw);
+ iounmap(p_avtimer_msw);
+ }
+ break;
+
+ default:
+ pr_err("invalid cmd\n");
+ break;
+ }
+
+ return 0;
+}
+
+static const struct file_operations avtimer_fops = {
+ .unlocked_ioctl = avtimer_ioctl,
+ .open = avtimer_open,
+ .release = avtimer_release
+};
+
+static int dev_avtimer_probe(struct platform_device *pdev)
+{
+ int result;
+ dev_t dev = MKDEV(major, 0);
+ struct device *device_handle;
+ struct avtimer_t *pavtimer = &avtimer;
+
+ /* get the device number */
+ if (major)
+ result = register_chrdev_region(dev, 1, DEVICE_NAME);
+ else {
+ result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
+ major = MAJOR(dev);
+ }
+
+ if (result < 0) {
+ pr_err("Registering avtimer device failed\n");
+ return result;
+ }
+
+ pavtimer->avtimer_class = class_create(THIS_MODULE, "avtimer");
+ if (IS_ERR(pavtimer->avtimer_class)) {
+ result = PTR_ERR(pavtimer->avtimer_class);
+ pr_err("Error creating avtimer class: %d\n", result);
+ goto unregister_chrdev_region;
+ }
+ pavtimer->avtimer_pdata = pdev->dev.platform_data;
+
+ cdev_init(&pavtimer->myc, &avtimer_fops);
+ result = cdev_add(&pavtimer->myc, dev, 1);
+
+ if (result < 0) {
+ pr_err("Registering file operations failed\n");
+ goto class_destroy;
+ }
+
+ device_handle = device_create(pavtimer->avtimer_class,
+ NULL, pavtimer->myc.dev, NULL, "avtimer");
+ if (IS_ERR(device_handle)) {
+ result = PTR_ERR(device_handle);
+ pr_err("device_create failed: %d\n", result);
+ goto class_destroy;
+ }
+
+ mutex_init(&pavtimer->avtimer_lock);
+ core_handle = NULL;
+ pavtimer->avtimer_open_cnt = 0;
+
+ pr_debug("Device create done for avtimer major=%d\n", major);
+
+ return 0;
+
+class_destroy:
+ class_destroy(pavtimer->avtimer_class);
+unregister_chrdev_region:
+ unregister_chrdev_region(MKDEV(major, 0), 1);
+ return result;
+
+}
+
+static int __devexit dev_avtimer_remove(struct platform_device *pdev)
+{
+ struct avtimer_t *pavtimer = &avtimer;
+
+ pr_debug("dev_avtimer_remove\n");
+
+ device_destroy(pavtimer->avtimer_class, pavtimer->myc.dev);
+ cdev_del(&pavtimer->myc);
+ class_destroy(pavtimer->avtimer_class);
+ unregister_chrdev_region(MKDEV(major, 0), 1);
+
+ return 0;
+}
+
+static struct platform_driver dev_avtimer_driver = {
+ .probe = dev_avtimer_probe,
+ .remove = __exit_p(dev_avtimer_remove),
+ .driver = {.name = "dev_avtimer"}
+};
+
+static int __init avtimer_init(void)
+{
+ s32 rc;
+ rc = platform_driver_register(&dev_avtimer_driver);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("platform_driver_register failed.\n");
+ goto error_platform_driver;
+ }
+ pr_debug("dev_avtimer_init : done\n");
+
+ return 0;
+error_platform_driver:
+
+ pr_err("encounterd error\n");
+ return -ENODEV;
+}
+
+static void __exit avtimer_exit(void)
+{
+ pr_debug("avtimer_exit\n");
+ platform_driver_unregister(&dev_avtimer_driver);
+}
+
+module_init(avtimer_init);
+module_exit(avtimer_exit);
+
+MODULE_DESCRIPTION("avtimer driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 6623d81..12b186d 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -1254,6 +1254,34 @@
return soc;
}
+static int clamp_soc_based_on_voltage(struct qpnp_bms_chip *chip, int soc)
+{
+ int rc, vbat_uv;
+ struct qpnp_vadc_result result;
+
+ rc = qpnp_vadc_read(VBAT_SNS, &result);
+ if (rc) {
+ pr_err("error reading vbat_sns adc channel = %d, rc = %d\n",
+ VBAT_SNS, rc);
+ return rc;
+ }
+
+ vbat_uv = (int)result.physical;
+ if (soc == 0 && vbat_uv > chip->v_cutoff_uv) {
+ pr_debug("clamping soc to 1, vbat (%d) > cutoff (%d)\n",
+ vbat_uv, chip->v_cutoff_uv);
+ return 1;
+ } else if (soc > 0 && vbat_uv < chip->v_cutoff_uv) {
+ pr_debug("forcing soc to 0, vbat (%d) < cutoff (%d)\n",
+ vbat_uv, chip->v_cutoff_uv);
+ return 0;
+ } else {
+ pr_debug("not clamping, using soc = %d, vbat = %d and cutoff = %d\n",
+ soc, vbat_uv, chip->v_cutoff_uv);
+ return soc;
+ }
+}
+
static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
struct raw_soc_params *raw,
int batt_temp)
@@ -1348,6 +1376,11 @@
pr_debug("SOC before adjustment = %d\n", soc);
new_calculated_soc = adjust_soc(chip, ¶ms, soc, batt_temp);
+ /* clamp soc due to BMS HW inaccuracies in pm8941v2.0 */
+ if (chip->revision1 == 0 && chip->revision2 == 0)
+ new_calculated_soc = clamp_soc_based_on_voltage(chip,
+ new_calculated_soc);
+
if (new_calculated_soc != chip->calculated_soc
&& chip->bms_psy.name != NULL) {
power_supply_changed(&chip->bms_psy);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index b5559db..a0d84df 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -71,6 +71,7 @@
#define CHGR_CHG_WDOG_EN 0x65
#define CHGR_USB_IUSB_MAX 0x44
#define CHGR_USB_USB_SUSP 0x47
+#define CHGR_USB_USB_OTG_CTL 0x48
#define CHGR_USB_ENUM_T_STOP 0x4E
#define CHGR_CHG_TEMP_THRESH 0x66
#define CHGR_BAT_IF_PRES_STATUS 0x08
@@ -271,6 +272,27 @@
return 0;
}
+#define USB_OTG_EN_BIT BIT(0)
+static int
+qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
+{
+ u8 usb_otg_en;
+ int rc;
+
+ rc = qpnp_chg_read(chip, &usb_otg_en,
+ chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
+ 1);
+
+ if (rc) {
+ pr_err("spmi read failed: addr=%03X, rc=%d\n",
+ chip->usb_chgpth_base + CHGR_STATUS, rc);
+ return rc;
+ }
+ pr_debug("usb otg en 0x%x\n", usb_otg_en);
+
+ return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
+}
+
#define USB_VALID_BIT BIT(7)
static int
qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
@@ -380,10 +402,16 @@
qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
{
struct qpnp_chg_chip *chip = _chip;
- int usb_present;
+ int usb_present, host_mode;
usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
- pr_debug("usbin-valid triggered: %d\n", usb_present);
+ host_mode = qpnp_chg_is_otg_en_set(chip);
+ pr_debug("usbin-valid triggered: %d host_mode: %d\n",
+ usb_present, host_mode);
+
+ /* In host mode notifications cmoe from USB supply */
+ if (host_mode)
+ return IRQ_HANDLED;
if (chip->usb_present ^ usb_present) {
chip->usb_present = usb_present;
@@ -436,6 +464,80 @@
return 0;
}
+static int
+qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
+{
+ return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
+ CHGR_CHG_EN,
+ enable ? CHGR_CHG_EN : 0, 1);
+}
+
+static int
+qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
+{
+ /* This bit forces the charger to run off of the battery rather
+ * than a connected charger */
+ return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
+ CHGR_ON_BAT_FORCE_BIT,
+ disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
+}
+
+static
+int switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
+{
+ int rc;
+
+ pr_debug("switch to charge mode\n");
+ if (!qpnp_chg_is_otg_en_set(chip))
+ return 0;
+
+ /* enable usb ovp fet */
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
+ USB_OTG_EN_BIT,
+ 0, 1);
+ if (rc) {
+ pr_err("Failed to turn on usb ovp rc = %d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
+ if (rc) {
+ pr_err("Failed re-enable charging rc = %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static
+int switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
+{
+ int rc;
+
+ pr_debug("switch to host mode\n");
+ if (qpnp_chg_is_otg_en_set(chip))
+ return 0;
+
+ rc = qpnp_chg_force_run_on_batt(chip, 1);
+ if (rc) {
+ pr_err("Failed to disable charging rc = %d\n", rc);
+ return rc;
+ }
+
+ /* force usb ovp fet off */
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
+ USB_OTG_EN_BIT,
+ USB_OTG_EN_BIT, 1);
+ if (rc) {
+ pr_err("Failed to turn off usb ovp rc = %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
static enum power_supply_property pm_power_props_mains[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
@@ -682,6 +784,21 @@
chip->bms_psy = power_supply_get_by_name("bms");
chip->usb_psy->get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_SCOPE, &ret);
+ if (ret.intval) {
+ if ((ret.intval == POWER_SUPPLY_SCOPE_SYSTEM)
+ && !qpnp_chg_is_otg_en_set(chip)) {
+ switch_usb_to_host_mode(chip);
+ return;
+ }
+ if ((ret.intval == POWER_SUPPLY_SCOPE_DEVICE)
+ && qpnp_chg_is_otg_en_set(chip)) {
+ switch_usb_to_charge_mode(chip);
+ return;
+ }
+ }
+
+ chip->usb_psy->get_property(chip->usb_psy,
POWER_SUPPLY_PROP_ONLINE, &ret);
if (ret.intval && qpnp_chg_is_usb_chg_plugged_in(chip)) {
@@ -702,24 +819,6 @@
}
static int
-qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
-{
- /* This bit forces the charger to run off of the battery rather
- * than a connected charger */
- return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
- CHGR_ON_BAT_FORCE_BIT,
- disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
-}
-
-static int
-qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
-{
- return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
- CHGR_CHG_EN,
- enable ? CHGR_CHG_EN : 0, 1);
-}
-
-static int
qpnp_batt_power_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 02e1952..78e8a6f 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -172,13 +172,16 @@
u8 *tid, struct completion *done)
{
struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
+ mutex_lock(&ctrl->m_ctrl);
if (ctrl->last_tid <= 255) {
ctrl->txnt = krealloc(ctrl->txnt,
(ctrl->last_tid + 1) *
sizeof(struct slim_msg_txn *),
GFP_KERNEL);
- if (!ctrl->txnt)
+ if (!ctrl->txnt) {
+ mutex_unlock(&ctrl->m_ctrl);
return -ENOMEM;
+ }
dev->msg_cnt = ctrl->last_tid;
ctrl->last_tid++;
} else {
@@ -190,6 +193,7 @@
}
if (i >= 256) {
dev_err(&ctrl->dev, "out of TID");
+ mutex_unlock(&ctrl->m_ctrl);
return -ENOMEM;
}
}
@@ -197,6 +201,7 @@
txn->tid = dev->msg_cnt;
txn->comp = done;
*tid = dev->msg_cnt;
+ mutex_unlock(&ctrl->m_ctrl);
return 0;
}
static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
@@ -369,6 +374,9 @@
pr_err("connect/disc :0x%x, tid:%d timed out", txn->mc,
txn->tid);
ret = -ETIMEDOUT;
+ mutex_lock(&ctrl->m_ctrl);
+ ctrl->txnt[txn->tid] = NULL;
+ mutex_unlock(&ctrl->m_ctrl);
} else {
ret = txn->ec;
}
@@ -394,6 +402,9 @@
pr_err("master req:0x%x, tid:%d timed out", txn->mc,
txn->tid);
ret = -ETIMEDOUT;
+ mutex_lock(&ctrl->m_ctrl);
+ ctrl->txnt[txn->tid] = NULL;
+ mutex_unlock(&ctrl->m_ctrl);
} else {
ret = txn->ec;
}
@@ -526,10 +537,8 @@
txn.dt = SLIM_MSG_DEST_LOGICALADDR;
txn.la = SLIM_LA_MGR;
txn.ec = 0;
- mutex_lock(&ctrl->m_ctrl);
ret = ngd_get_tid(ctrl, &txn, &wbuf[0], &done);
if (ret) {
- mutex_unlock(&ctrl->m_ctrl);
return ret;
}
memcpy(&wbuf[1], ea, elen);
@@ -543,7 +552,6 @@
ret = -ENXIO;
else if (!ret)
*laddr = txn.la;
- mutex_unlock(&ctrl->m_ctrl);
return ret;
}
@@ -606,20 +614,33 @@
}
if (mc == SLIM_USR_MC_ADDR_REPLY &&
mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
- struct slim_msg_txn *txn = dev->ctrl.txnt[buf[3]];
+ struct slim_msg_txn *txn;
u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
- if (!txn)
+ mutex_lock(&dev->ctrl.m_ctrl);
+ txn = dev->ctrl.txnt[buf[3]];
+ if (!txn) {
+ pr_err("LADDR response after timeout, tid:0x%x",
+ buf[3]);
+ mutex_unlock(&dev->ctrl.m_ctrl);
return;
+ }
if (memcmp(&buf[4], failed_ea, 6))
txn->la = buf[10];
dev->ctrl.txnt[buf[3]] = NULL;
+ mutex_unlock(&dev->ctrl.m_ctrl);
complete(txn->comp);
}
if (mc == SLIM_USR_MC_GENERIC_ACK &&
mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
- struct slim_msg_txn *txn = dev->ctrl.txnt[buf[3]];
- if (!txn)
+ struct slim_msg_txn *txn;
+ mutex_lock(&dev->ctrl.m_ctrl);
+ txn = dev->ctrl.txnt[buf[3]];
+ if (!txn) {
+ pr_err("ACK received after timeout, tid:0x%x",
+ buf[3]);
+ mutex_unlock(&dev->ctrl.m_ctrl);
return;
+ }
dev_dbg(dev->dev, "got response:tid:%d, response:0x%x",
(int)buf[3], buf[4]);
if (!(buf[4] & MSM_SAT_SUCCSS)) {
@@ -628,6 +649,7 @@
txn->ec = -EIO;
}
dev->ctrl.txnt[buf[3]] = NULL;
+ mutex_unlock(&dev->ctrl.m_ctrl);
complete(txn->comp);
}
}
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index d5d6e0c..c320e46 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1216,7 +1216,7 @@
if (flow != SLIM_SRC)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
if (slc->state == SLIM_CH_FREE) {
ret = -ENOTCONN;
@@ -1238,7 +1238,7 @@
slc->srch = srch;
connect_src_err:
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return ret;
}
EXPORT_SYMBOL_GPL(slim_connect_src);
@@ -1265,7 +1265,7 @@
if (!sinkh || !nsink)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
/*
* Once channel is removed, its ports can be considered disconnected
@@ -1303,7 +1303,7 @@
slc->nsink += nsink;
connect_sink_err:
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return ret;
}
EXPORT_SYMBOL_GPL(slim_connect_sink);
@@ -1320,11 +1320,11 @@
struct slim_controller *ctrl = sb->ctrl;
int i;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
for (i = 0; i < nph; i++)
disconnect_port_ch(ctrl, ph[i]);
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return 0;
}
EXPORT_SYMBOL_GPL(slim_disconnect_ports);
@@ -1660,13 +1660,13 @@
if (!ctrl)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
for (i = 0; i < ctrl->nchans; i++) {
if (ctrl->chans[i].state == SLIM_CH_FREE)
break;
}
if (i >= ctrl->nchans) {
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return -EXFULL;
}
*chanh = i;
@@ -1674,7 +1674,7 @@
ctrl->chans[i].state = SLIM_CH_ALLOCATED;
ctrl->chans[i].chan = (u8)(ctrl->reserved + i);
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return 0;
}
EXPORT_SYMBOL_GPL(slim_alloc_ch);
@@ -1698,7 +1698,7 @@
int ret = 0;
if (!ctrl || !chanh)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
/* start with modulo number */
i = ch % ctrl->nchans;
@@ -1729,7 +1729,7 @@
i = (i + 1) % ctrl->nchans;
}
query_out:
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
dev_dbg(&ctrl->dev, "query ch:%d,hdl:%d,ref:%d,ret:%d",
ch, i, ctrl->chans[i].ref, ret);
return ret;
@@ -1751,26 +1751,26 @@
if (!ctrl)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
if (slc->state == SLIM_CH_FREE) {
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return -ENOTCONN;
}
if (slc->ref > 1) {
slc->ref--;
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
dev_dbg(&ctrl->dev, "remove chan:%d,hdl:%d,ref:%d",
slc->chan, chanh, slc->ref);
return 0;
}
if (slc->state >= SLIM_CH_PENDING_ACTIVE) {
dev_err(&ctrl->dev, "Channel:%d should be removed first", chan);
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return -EISCONN;
}
slc->ref--;
slc->state = SLIM_CH_FREE;
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
dev_dbg(&ctrl->dev, "remove chan:%d,hdl:%d,ref:%d",
slc->chan, chanh, slc->ref);
return 0;
@@ -1812,7 +1812,7 @@
if (!ctrl || !chanh || !prop || !nchan)
return -EINVAL;
- mutex_lock(&ctrl->m_ctrl);
+ mutex_lock(&ctrl->sched.m_reconf);
for (i = 0; i < nchan; i++) {
u8 chan = SLIM_HDL_TO_CHIDX(chanh[i]);
struct slim_ich *slc = &ctrl->chans[chan];
@@ -1856,7 +1856,7 @@
}
err_define_ch:
dev_dbg(&ctrl->dev, "define_ch: ch:%d, ret:%d", *chanh, ret);
- mutex_unlock(&ctrl->m_ctrl);
+ mutex_unlock(&ctrl->sched.m_reconf);
return ret;
}
EXPORT_SYMBOL_GPL(slim_define_ch);
@@ -2607,7 +2607,6 @@
struct slim_pending_ch *pch;
mutex_lock(&ctrl->sched.m_reconf);
- mutex_lock(&ctrl->m_ctrl);
/*
* If there are no pending changes from this client, avoid sending
* the reconfiguration sequence
@@ -2631,7 +2630,6 @@
}
}
if (list_empty(&sb->mark_removal)) {
- mutex_unlock(&ctrl->m_ctrl);
mutex_unlock(&ctrl->sched.m_reconf);
pr_info("SLIM_CL: skip reconfig sequence");
return 0;
@@ -2820,7 +2818,6 @@
ctrl->sched.msgsl = ctrl->sched.pending_msgsl;
sb->cur_msgsl = sb->pending_msgsl;
slim_chan_changes(sb, false);
- mutex_unlock(&ctrl->m_ctrl);
mutex_unlock(&ctrl->sched.m_reconf);
return 0;
}
@@ -2828,7 +2825,6 @@
revert_reconfig:
/* Revert channel changes */
slim_chan_changes(sb, true);
- mutex_unlock(&ctrl->m_ctrl);
mutex_unlock(&ctrl->sched.m_reconf);
return ret;
}
@@ -2876,7 +2872,6 @@
return -EINVAL;
mutex_lock(&sb->sldev_reconf);
- mutex_lock(&ctrl->m_ctrl);
do {
struct slim_pending_ch *pch;
u8 add_mark_removal = true;
@@ -2935,7 +2930,6 @@
if (nchan < SLIM_GRP_TO_NCHAN(chanh))
chan = SLIM_HDL_TO_CHIDX(slc->nextgrp);
} while (nchan < SLIM_GRP_TO_NCHAN(chanh));
- mutex_unlock(&ctrl->m_ctrl);
if (!ret && commit == true)
ret = slim_reconfigure_now(sb);
mutex_unlock(&sb->sldev_reconf);
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index c67b75b..7b8788d 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -62,65 +62,6 @@
printk(x); \
} while (0)
-static int nr_free_zone_mtype_pages(struct zone *zone, int mtype)
-{
- int order;
- int sum = 0;
-
- for (order = 0; order < MAX_ORDER; ++order) {
- unsigned long freecount = 0;
- struct free_area *area;
- struct list_head *curr;
-
- area = &(zone->free_area[order]);
-
- list_for_each(curr, &area->free_list[mtype])
- freecount++;
-
- sum += freecount << order;
- }
- return sum;
-}
-
-static int nr_free_zone_pages(struct zone *zone, gfp_t gfp_mask)
-{
- int sum = 0;
- int mtype = allocflags_to_migratetype(gfp_mask);
- int i = 0;
- int *mtype_fallbacks = get_migratetype_fallbacks(mtype);
-
- sum = nr_free_zone_mtype_pages(zone, mtype);
-
- /*
- * Also count the fallback pages
- */
- for (i = 0;; i++) {
- int fallbacktype = mtype_fallbacks[i];
- sum += nr_free_zone_mtype_pages(zone, fallbacktype);
-
- if (fallbacktype == MIGRATE_RESERVE)
- break;
- }
-
- return sum;
-}
-
-static int nr_free_pages(gfp_t gfp_mask)
-{
- struct zoneref *z;
- struct zone *zone;
- int sum = 0;
-
- struct zonelist *zonelist = node_zonelist(numa_node_id(), gfp_mask);
-
- for_each_zone_zonelist(zone, z, zonelist, gfp_zone(gfp_mask)) {
- sum += nr_free_zone_pages(zone, gfp_mask);
- }
-
- return sum;
-}
-
-
static int test_task_flag(struct task_struct *p, int flag)
{
struct task_struct *t = p;
@@ -152,15 +93,6 @@
int other_file = global_page_state(NR_FILE_PAGES) -
global_page_state(NR_SHMEM);
- if (sc->nr_to_scan > 0 && other_free > other_file) {
- /*
- * If the number of free pages is going to affect the decision
- * of which process is selected then ensure only free pages
- * which can satisfy the request are considered.
- */
- other_free = nr_free_pages(sc->gfp_mask);
- }
-
if (lowmem_adj_size < array_size)
array_size = lowmem_adj_size;
if (lowmem_minfree_size < array_size)
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 7430e5a..d416904 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -114,6 +114,12 @@
#define ALT_INTERRUPT_EN_REG (QSCRATCH_REG_OFFSET + 0x20)
#define HS_PHY_IRQ_STAT_REG (QSCRATCH_REG_OFFSET + 0x24)
#define SS_PHY_CTRL_REG (QSCRATCH_REG_OFFSET + 0x30)
+#define SS_CR_PROTOCOL_DATA_IN_REG (QSCRATCH_REG_OFFSET + 0x3C)
+#define SS_CR_PROTOCOL_DATA_OUT_REG (QSCRATCH_REG_OFFSET + 0x40)
+#define SS_CR_PROTOCOL_CAP_ADDR_REG (QSCRATCH_REG_OFFSET + 0x44)
+#define SS_CR_PROTOCOL_CAP_DATA_REG (QSCRATCH_REG_OFFSET + 0x48)
+#define SS_CR_PROTOCOL_READ_REG (QSCRATCH_REG_OFFSET + 0x4C)
+#define SS_CR_PROTOCOL_WRITE_REG (QSCRATCH_REG_OFFSET + 0x50)
struct dwc3_msm_req_complete {
struct list_head list_item;
@@ -280,6 +286,54 @@
}
/**
+ *
+ * Write SSPHY register with debug info.
+ *
+ * @base - DWC3 base virtual address.
+ * @addr - SSPHY address to write.
+ * @val - value to write.
+ *
+ */
+static void dwc3_msm_ssusb_write_phycreg(void *base, u32 addr, u32 val)
+{
+ iowrite32(addr, base + SS_CR_PROTOCOL_DATA_IN_REG);
+ iowrite32(0x1, base + SS_CR_PROTOCOL_CAP_ADDR_REG);
+ while (ioread32(base + SS_CR_PROTOCOL_CAP_ADDR_REG))
+ cpu_relax();
+
+ iowrite32(val, base + SS_CR_PROTOCOL_DATA_IN_REG);
+ iowrite32(0x1, base + SS_CR_PROTOCOL_CAP_DATA_REG);
+ while (ioread32(base + SS_CR_PROTOCOL_CAP_DATA_REG))
+ cpu_relax();
+
+ iowrite32(0x1, base + SS_CR_PROTOCOL_WRITE_REG);
+ while (ioread32(base + SS_CR_PROTOCOL_WRITE_REG))
+ cpu_relax();
+}
+
+/**
+ *
+ * Read SSPHY register with debug info.
+ *
+ * @base - DWC3 base virtual address.
+ * @addr - SSPHY address to read.
+ *
+ */
+static u32 dwc3_msm_ssusb_read_phycreg(void *base, u32 addr)
+{
+ iowrite32(addr, base + SS_CR_PROTOCOL_DATA_IN_REG);
+ iowrite32(0x1, base + SS_CR_PROTOCOL_CAP_ADDR_REG);
+ while (ioread32(base + SS_CR_PROTOCOL_CAP_ADDR_REG))
+ cpu_relax();
+
+ iowrite32(0x1, base + SS_CR_PROTOCOL_READ_REG);
+ while (ioread32(base + SS_CR_PROTOCOL_READ_REG))
+ cpu_relax();
+
+ return ioread32(base + SS_CR_PROTOCOL_DATA_OUT_REG);
+}
+
+/**
* Return DBM EP number according to usb endpoint number.
*
*/
@@ -1608,6 +1662,7 @@
int ret = 0;
int len = 0;
u32 tmp[3];
+ u32 data = 0;
msm = devm_kzalloc(&pdev->dev, sizeof(*msm), GFP_KERNEL);
if (!msm) {
@@ -1851,6 +1906,20 @@
/* Disable (bypass) VBUS and ID filters */
dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
+ /*
+ * WORKAROUND: There is SSPHY suspend bug due to which USB enumerates
+ * in HS mode instead of SS mode. Workaround it by asserting
+ * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode
+ */
+ data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x102D);
+ data |= (1 << 7);
+ dwc3_msm_ssusb_write_phycreg(msm->base, 0x102D, data);
+
+ data = dwc3_msm_ssusb_read_phycreg(msm->base, 0x1010);
+ data &= ~0xFF0;
+ data |= 0x40;
+ dwc3_msm_ssusb_write_phycreg(msm->base, 0x1010, data);
+
pm_runtime_set_active(msm->dev);
pm_runtime_enable(msm->dev);
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index f363206..581ec17 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -317,7 +317,8 @@
return 0;
}
-static inline int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd, int e)
+static inline int mdss_fb_send_panel_event(
+ struct msm_fb_data_type *mfd, int e, void *arg)
{
struct mdss_panel_data *pdata;
@@ -330,7 +331,7 @@
pr_debug("sending event=%d for fb%d\n", e, mfd->index);
if (pdata->event_handler)
- return pdata->event_handler(pdata, e, NULL);
+ return pdata->event_handler(pdata, e, arg);
return 0;
}
@@ -344,7 +345,7 @@
pr_debug("mdss_fb suspend index=%d\n", mfd->index);
- ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_SUSPEND);
+ ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_SUSPEND, NULL);
if (ret) {
pr_warn("unable to suspend fb%d (%d)\n", mfd->index, ret);
return ret;
@@ -375,7 +376,7 @@
pr_debug("mdss_fb resume index=%d\n", mfd->index);
- ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_RESUME);
+ ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_RESUME, NULL);
if (ret) {
pr_warn("unable to resume fb%d (%d)\n", mfd->index, ret);
return ret;
@@ -854,10 +855,6 @@
var->hsync_len = panel_info->lcdc.h_pulse_width;
var->pixclock = panel_info->clk_rate / 1000;
- mfd->var_xres = var->xres;
- mfd->var_yres = var->yres;
- mfd->var_pixclock = var->pixclock;
-
if (panel_info->type == MIPI_VIDEO_PANEL) {
var->reserved[4] = panel_info->mipi.frame_rate;
} else {
@@ -1004,6 +1001,22 @@
return 0;
}
+static void mdss_fb_var_to_panelinfo(struct fb_var_screeninfo *var,
+ struct mdss_panel_info *pinfo)
+{
+ pinfo->xres = var->xres;
+ pinfo->yres = var->yres;
+ pinfo->lcdc.v_front_porch = var->upper_margin;
+ pinfo->lcdc.v_back_porch = var->lower_margin;
+ pinfo->lcdc.v_pulse_width = var->vsync_len;
+ pinfo->lcdc.h_front_porch = var->left_margin;
+ pinfo->lcdc.h_back_porch = var->right_margin;
+ pinfo->lcdc.h_pulse_width = var->hsync_len;
+ pinfo->clk_rate = var->pixclock;
+ /* todo: find how to pass CEA vic through framebuffer APIs */
+ pinfo->vic = var->reserved[3];
+}
+
static int mdss_fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
@@ -1096,16 +1109,25 @@
if ((var->xres == 0) || (var->yres == 0))
return -EINVAL;
- if ((var->xres > mfd->panel_info->xres) ||
- (var->yres > mfd->panel_info->yres))
- return -EINVAL;
-
if (var->xoffset > (var->xres_virtual - var->xres))
return -EINVAL;
if (var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL;
+ if (mfd->panel_info) {
+ struct mdss_panel_info panel_info;
+ int rc;
+
+ memcpy(&panel_info, mfd->panel_info, sizeof(panel_info));
+ mdss_fb_var_to_panelinfo(var, &panel_info);
+ rc = mdss_fb_send_panel_event(mfd, MDSS_EVENT_CHECK_PARAMS,
+ &panel_info);
+ if (IS_ERR_VALUE(rc))
+ return rc;
+ mfd->panel_reconfig = rc;
+ }
+
return 0;
}
@@ -1114,7 +1136,6 @@
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct fb_var_screeninfo *var = &info->var;
int old_imgType;
- int blank = 0;
old_imgType = mfd->fb_imgType;
switch (var->bits_per_pixel) {
@@ -1146,22 +1167,14 @@
return -EINVAL;
}
- if ((mfd->var_pixclock != var->pixclock) ||
- (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) ||
- (mfd->var_pixclock != var->pixclock) ||
- (mfd->var_xres != var->xres) ||
- (mfd->var_yres != var->yres)))) {
- mfd->var_xres = var->xres;
- mfd->var_yres = var->yres;
- mfd->var_pixclock = var->pixclock;
- blank = 1;
- }
mfd->fbi->fix.line_length = mdss_fb_line_length(mfd->index, var->xres,
var->bits_per_pixel / 8);
- if (blank) {
+ if (mfd->panel_reconfig || (mfd->fb_imgType != old_imgType)) {
mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
+ mdss_fb_var_to_panelinfo(var, mfd->panel_info);
mdss_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
+ mfd->panel_reconfig = false;
}
return 0;
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index b7bd4e6..11bb859 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -62,6 +62,8 @@
int op_enable;
u32 fb_imgType;
+ int panel_reconfig;
+
u32 dst_format;
int vsync_pending;
ktime_t vsync_time;
@@ -100,10 +102,6 @@
struct platform_device *pdev;
- u32 var_xres;
- u32 var_yres;
- u32 var_pixclock;
-
u32 mdp_fb_page_protection;
struct mdss_mdp_ctl *ctl;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 539cd49..37bbbdf 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -163,6 +163,66 @@
}
} /* hdmi_tx_io_name */
+static int hdmi_tx_get_vic_from_panel_info(struct hdmi_tx_ctrl *hdmi_ctrl,
+ struct mdss_panel_info *pinfo)
+{
+ int new_vic = -1;
+ u32 h_total, v_total;
+ struct hdmi_disp_mode_timing_type timing;
+
+ if (!hdmi_ctrl || !pinfo) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ if (pinfo->vic) {
+ if (hdmi_get_supported_mode(pinfo->vic - 1)) {
+ new_vic = pinfo->vic - 1;
+ DEV_DBG("%s: %s is supported\n", __func__,
+ hdmi_get_video_fmt_2string(new_vic));
+ } else {
+ DEV_ERR("%s: invalid or not supported vic\n",
+ __func__);
+ return -EPERM;
+ }
+ } else {
+ timing.active_h = pinfo->xres;
+ timing.back_porch_h = pinfo->lcdc.h_back_porch;
+ timing.front_porch_h = pinfo->lcdc.h_front_porch;
+ timing.pulse_width_h = pinfo->lcdc.h_pulse_width;
+ h_total = timing.active_h + timing.back_porch_h +
+ timing.front_porch_h + timing.pulse_width_h;
+ DEV_DBG("%s: ah=%d bph=%d fph=%d pwh=%d ht=%d\n", __func__,
+ timing.active_h, timing.back_porch_h,
+ timing.front_porch_h, timing.pulse_width_h, h_total);
+
+ timing.active_v = pinfo->yres;
+ timing.back_porch_v = pinfo->lcdc.v_back_porch;
+ timing.front_porch_v = pinfo->lcdc.v_front_porch;
+ timing.pulse_width_v = pinfo->lcdc.v_pulse_width;
+ v_total = timing.active_v + timing.back_porch_v +
+ timing.front_porch_v + timing.pulse_width_v;
+ DEV_DBG("%s: av=%d bpv=%d fpv=%d pwv=%d vt=%d\n", __func__,
+ timing.active_v, timing.back_porch_v,
+ timing.front_porch_v, timing.pulse_width_v, v_total);
+
+ timing.pixel_freq = pinfo->clk_rate / 1000;
+ if (h_total && v_total) {
+ timing.refresh_rate = ((timing.pixel_freq * 1000) /
+ (h_total * v_total)) * 1000;
+ } else {
+ DEV_ERR("%s: cannot cal refresh rate\n", __func__);
+ return -EPERM;
+ }
+ DEV_DBG("%s: pixel_freq=%d refresh_rate=%d\n", __func__,
+ timing.pixel_freq, timing.refresh_rate);
+
+ new_vic = hdmi_get_video_id_code(&timing);
+ }
+
+ return new_vic;
+} /* hdmi_tx_get_vic_from_panel_info */
+
static struct hdmi_tx_ctrl *hdmi_tx_get_drvdata_from_panel_data(
struct mdss_panel_data *mpd)
{
@@ -170,14 +230,8 @@
if (mpd) {
hdmi_ctrl = container_of(mpd, struct hdmi_tx_ctrl, panel_data);
- if (hdmi_ctrl) {
- hdmi_ctrl->pixel_clk =
- mpd->panel_info.fbi->var.pixclock;
- hdmi_ctrl->xres = mpd->panel_info.fbi->var.xres;
- hdmi_ctrl->yres = mpd->panel_info.fbi->var.yres;
- } else {
+ if (!hdmi_ctrl)
DEV_ERR("%s: hdmi_ctrl = NULL\n", __func__);
- }
} else {
DEV_ERR("%s: mdss_panel_data = NULL\n", __func__);
}
@@ -546,90 +600,40 @@
return 0;
} /* hdmi_tx_check_capability */
-static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl)
+static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl,
+ struct mdss_panel_info *pinfo)
{
- int rc = 0;
+ int new_vic = -1;
const struct hdmi_disp_mode_timing_type *timing = NULL;
- struct hdmi_tx_platform_data *pdata = NULL;
- u32 format = DEFAULT_VIDEO_RESOLUTION;
- if (!hdmi_ctrl) {
+ if (!hdmi_ctrl || !pinfo) {
DEV_ERR("%s: invalid input\n", __func__);
- rc = -EINVAL;
- goto end;
+ return -EINVAL;
}
- pdata = &hdmi_ctrl->pdata;
-
- DEV_DBG("%s: Resolution wanted=%dx%d\n", __func__, hdmi_ctrl->xres,
- hdmi_ctrl->yres);
- switch (hdmi_ctrl->xres) {
- default:
- case 640:
- format = HDMI_VFRMT_640x480p60_4_3;
- break;
- case 720:
- format = (hdmi_ctrl->yres == 480)
- ? HDMI_VFRMT_720x480p60_16_9
- : HDMI_VFRMT_720x576p50_16_9;
- break;
- case 1280:
- if (hdmi_ctrl->frame_rate == 50000)
- format = HDMI_VFRMT_1280x720p50_16_9;
- else
- format = HDMI_VFRMT_1280x720p60_16_9;
- break;
- case 1440:
- /* interlaced has half of y res. */
- format = (hdmi_ctrl->yres == 240)
- ? HDMI_VFRMT_1440x480i60_16_9
- : HDMI_VFRMT_1440x576i50_16_9;
- break;
- case 1920:
- if (hdmi_ctrl->yres == 540) {/* interlaced */
- format = HDMI_VFRMT_1920x1080i60_16_9;
- } else if (hdmi_ctrl->yres == 1080) {
- if (hdmi_ctrl->frame_rate == 50000)
- format = HDMI_VFRMT_1920x1080p50_16_9;
- else if (hdmi_ctrl->frame_rate == 24000)
- format = HDMI_VFRMT_1920x1080p24_16_9;
- else if (hdmi_ctrl->frame_rate == 25000)
- format = HDMI_VFRMT_1920x1080p25_16_9;
- else if (hdmi_ctrl->frame_rate == 30000)
- format = HDMI_VFRMT_1920x1080p30_16_9;
- else
- format = HDMI_VFRMT_1920x1080p60_16_9;
- }
- break;
+ new_vic = hdmi_tx_get_vic_from_panel_info(hdmi_ctrl, pinfo);
+ if ((new_vic < 0) || (new_vic > HDMI_VFRMT_MAX)) {
+ DEV_ERR("%s: invalid or not supported vic\n", __func__);
+ return -EPERM;
}
- if (hdmi_ctrl->video_resolution != format)
- DEV_DBG("%s: switching %s => %s", __func__,
- hdmi_get_video_fmt_2string(
- hdmi_ctrl->video_resolution),
- hdmi_get_video_fmt_2string(format));
- else
- DEV_DBG("resolution %s", hdmi_get_video_fmt_2string(
- hdmi_ctrl->video_resolution));
+ DEV_DBG("%s: switching from %s => %s", __func__,
+ hdmi_get_video_fmt_2string(hdmi_ctrl->video_resolution),
+ hdmi_get_video_fmt_2string(new_vic));
- timing = hdmi_get_supported_mode(format);
- if (!timing) {
- DEV_ERR("%s: invalid video fmt=%d\n", __func__,
- hdmi_ctrl->video_resolution);
- rc = -EPERM;
- goto end;
- }
+ hdmi_ctrl->video_resolution = (u32)new_vic;
+
+ timing = hdmi_get_supported_mode(hdmi_ctrl->video_resolution);
/* todo: find a better way */
hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM].clk_config[0].rate =
timing->pixel_freq * 1000;
- hdmi_ctrl->video_resolution = format;
hdmi_edid_set_video_resolution(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID], format);
+ hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID],
+ hdmi_ctrl->video_resolution);
-end:
- return rc;
+ return 0;
} /* hdmi_tx_set_video_fmt */
static void hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
@@ -1710,8 +1714,6 @@
if (hdmi_ctrl->hpd_off_pending) {
hdmi_tx_hpd_off(hdmi_ctrl);
hdmi_ctrl->hpd_off_pending = false;
- } else {
- hdmi_tx_hpd_polarity_setup(hdmi_ctrl, HPD_CONNECT_POLARITY);
}
DEV_INFO("%s: HDMI Core: OFF\n", __func__);
@@ -1764,15 +1766,15 @@
/* If a power down is already underway, wait for it to finish */
flush_work_sync(&hdmi_ctrl->power_off_work);
- DEV_INFO("power: ON (%dx%d %ld)\n", hdmi_ctrl->xres, hdmi_ctrl->yres,
- hdmi_ctrl->pixel_clk);
-
- rc = hdmi_tx_set_video_fmt(hdmi_ctrl);
+ rc = hdmi_tx_set_video_fmt(hdmi_ctrl, &panel_data->panel_info);
if (rc) {
DEV_ERR("%s: cannot set video_fmt.rc=%d\n", __func__, rc);
return rc;
}
+ DEV_INFO("power: ON (%s)\n", hdmi_get_video_fmt_2string(
+ hdmi_ctrl->video_resolution));
+
rc = hdmi_tx_core_on(hdmi_ctrl);
if (rc) {
DEV_ERR("%s: hdmi_msm_core_on failed\n", __func__);
@@ -2044,7 +2046,7 @@
static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data,
int event, void *arg)
{
- int rc = 0;
+ int rc = 0, new_vic = -1;
struct hdmi_tx_ctrl *hdmi_ctrl =
hdmi_tx_get_drvdata_from_panel_data(panel_data);
@@ -2057,6 +2059,25 @@
event, hdmi_ctrl->panel_suspend, hdmi_ctrl->hpd_feature_on);
switch (event) {
+ case MDSS_EVENT_CHECK_PARAMS:
+ new_vic = hdmi_tx_get_vic_from_panel_info(hdmi_ctrl,
+ (struct mdss_panel_info *)arg);
+ if ((new_vic < 0) || (new_vic > HDMI_VFRMT_MAX)) {
+ DEV_ERR("%s: invalid or not supported vic\n", __func__);
+ return -EPERM;
+ }
+
+ /*
+ * return value of 1 lets mdss know that panel
+ * needs a reconfig due to new resolution and
+ * it will issue close and open subsequently.
+ */
+ if (new_vic != hdmi_ctrl->video_resolution)
+ rc = 1;
+ else
+ DEV_DBG("%s: no res change.\n", __func__);
+ break;
+
case MDSS_EVENT_RESUME:
if (hdmi_ctrl->hpd_feature_on) {
INIT_COMPLETION(hdmi_ctrl->hpd_done);
@@ -2104,8 +2125,6 @@
if (!hdmi_ctrl->panel_power_on) {
if (hdmi_ctrl->hpd_feature_on)
hdmi_tx_hpd_off(hdmi_ctrl);
- else
- DEV_ERR("%s: invalid state\n", __func__);
hdmi_ctrl->panel_suspend = false;
} else {
@@ -2131,6 +2150,12 @@
if (hdmi_ctrl->panel_suspend)
flush_work_sync(&hdmi_ctrl->power_off_work);
break;
+
+ case MDSS_EVENT_CLOSE:
+ if (hdmi_ctrl->hpd_feature_on)
+ hdmi_tx_hpd_polarity_setup(hdmi_ctrl,
+ HPD_CONNECT_POLARITY);
+ break;
}
return rc;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 2d431b7..5f8094f 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -50,6 +50,7 @@
struct workqueue_struct *workq;
uint32_t video_resolution;
+
u32 panel_power_on;
u32 panel_suspend;
@@ -62,11 +63,6 @@
struct work_struct power_off_work;
- unsigned long pixel_clk;
- u32 xres;
- u32 yres;
- u32 frame_rate;
-
u32 present_hdcp;
u8 spd_vendor_name[8];
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index e7ea8c9..a3d76be 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -98,6 +98,57 @@
return ret;
} /* hdmi_get_supported_mode */
+int hdmi_get_video_id_code(struct hdmi_disp_mode_timing_type *timing_in)
+{
+ int i, vic = -1;
+
+ if (!timing_in) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ goto exit;
+ }
+
+ /* active_low_h, active_low_v and interlaced are not checked against */
+ for (i = 0; i < HDMI_VFRMT_MAX; i++) {
+ struct hdmi_disp_mode_timing_type *supported_timing =
+ &hdmi_supported_video_mode_lut[i];
+
+ if (!supported_timing->supported)
+ continue;
+ if (timing_in->active_h != supported_timing->active_h)
+ continue;
+ if (timing_in->front_porch_h != supported_timing->front_porch_h)
+ continue;
+ if (timing_in->pulse_width_h != supported_timing->pulse_width_h)
+ continue;
+ if (timing_in->back_porch_h != supported_timing->back_porch_h)
+ continue;
+ if (timing_in->active_v != supported_timing->active_v)
+ continue;
+ if (timing_in->front_porch_v != supported_timing->front_porch_v)
+ continue;
+ if (timing_in->pulse_width_v != supported_timing->pulse_width_v)
+ continue;
+ if (timing_in->back_porch_v != supported_timing->back_porch_v)
+ continue;
+ if (timing_in->pixel_freq != supported_timing->pixel_freq)
+ continue;
+ if (timing_in->refresh_rate != supported_timing->refresh_rate)
+ continue;
+
+ vic = (int)supported_timing->video_format;
+ break;
+ }
+
+ if (vic < 0)
+ DEV_ERR("%s: timing asked is not yet supported\n", __func__);
+
+exit:
+ DEV_DBG("%s: vic = %d timing = %s\n", __func__, vic,
+ hdmi_get_video_fmt_2string((u32)vic));
+
+ return vic;
+} /* hdmi_get_video_id_code */
+
void hdmi_set_supported_mode(u32 mode)
{
switch (mode) {
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.h b/drivers/video/msm/mdss/mdss_hdmi_util.h
index 852a93c..c970ebe 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.h
@@ -397,6 +397,7 @@
int retry;
};
+int hdmi_get_video_id_code(struct hdmi_disp_mode_timing_type *timing_in);
const struct hdmi_disp_mode_timing_type *hdmi_get_supported_mode(u32 mode);
void hdmi_set_supported_mode(u32 mode);
const char *hdmi_get_video_fmt_2string(u32 format);
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 157a7eb..d273201 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -243,7 +243,9 @@
unsigned long smp[MAX_PLANES];
- struct mdss_mdp_data buffers[2];
+ struct mdss_mdp_data back_buf;
+ struct mdss_mdp_data front_buf;
+
struct list_head used_list;
struct list_head cleanup_list;
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index bd7371b..31cc527 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -391,8 +391,8 @@
return -ENODEV;
}
- width = mfd->fbi->var.xres;
- height = mfd->fbi->var.yres;
+ width = pdata->panel_info.xres;
+ height = pdata->panel_info.yres;
if (width > (2 * MAX_MIXER_WIDTH)) {
pr_err("unsupported resolution\n");
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 61c1e9f..5b6d009 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -430,35 +430,24 @@
{
struct mdss_mdp_pipe *pipe, *tmp;
LIST_HEAD(destroy_pipes);
- int i;
- mutex_lock(&mfd->ov_lock);
mutex_lock(&mfd->lock);
list_for_each_entry_safe(pipe, tmp, &mfd->pipes_cleanup, cleanup_list) {
list_move(&pipe->cleanup_list, &destroy_pipes);
- for (i = 0; i < ARRAY_SIZE(pipe->buffers); i++)
- mdss_mdp_overlay_free_buf(&pipe->buffers[i]);
+ mdss_mdp_overlay_free_buf(&pipe->back_buf);
+ mdss_mdp_overlay_free_buf(&pipe->front_buf);
}
- if (!list_empty(&mfd->pipes_used)) {
- struct mdss_mdp_data *data;
- int buf_ndx;
-
- list_for_each_entry(pipe, &mfd->pipes_used, used_list) {
- buf_ndx = (pipe->play_cnt - 1) & 1; /* prev buffer */
- data = &pipe->buffers[buf_ndx];
-
- if (data->num_planes) {
- pr_debug("free buffer ndx=%d pnum=%d\n",
- buf_ndx, pipe->num);
- mdss_mdp_overlay_free_buf(data);
- }
+ list_for_each_entry(pipe, &mfd->pipes_used, used_list) {
+ if (pipe->back_buf.num_planes) {
+ /* make back buffer active */
+ mdss_mdp_overlay_free_buf(&pipe->front_buf);
+ swap(pipe->back_buf, pipe->front_buf);
}
}
mutex_unlock(&mfd->lock);
list_for_each_entry_safe(pipe, tmp, &destroy_pipes, cleanup_list)
mdss_mdp_pipe_destroy(pipe);
- mutex_unlock(&mfd->ov_lock);
return 0;
}
@@ -468,12 +457,16 @@
struct msm_fb_data_type *mfd = ctl->mfd;
int ret;
+ mutex_lock(&mfd->ov_lock);
+
if (mfd->kickoff_fnc)
ret = mfd->kickoff_fnc(ctl);
else
ret = mdss_mdp_display_commit(ctl, NULL);
- if (IS_ERR_VALUE(ret))
+ if (IS_ERR_VALUE(ret)) {
+ mutex_unlock(&mfd->ov_lock);
return ret;
+ }
complete(&mfd->update.comp);
mutex_lock(&mfd->no_update.lock);
@@ -486,6 +479,8 @@
ret = mdss_mdp_overlay_cleanup(mfd);
+ mutex_unlock(&mfd->ov_lock);
+
return ret;
}
@@ -630,7 +625,7 @@
struct mdss_mdp_ctl *ctl;
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_data *src_data;
- int ret, buf_ndx;
+ int ret;
u32 flags;
pipe = mdss_mdp_pipe_get_locked(req->id);
@@ -643,9 +638,12 @@
flags = (pipe->flags & MDP_SECURE_OVERLAY_SESSION);
- buf_ndx = (pipe->play_cnt + 1) & 1; /* next buffer */
- src_data = &pipe->buffers[buf_ndx];
- mdss_mdp_overlay_free_buf(src_data);
+ src_data = &pipe->back_buf;
+ if (src_data->num_planes) {
+ pr_warn("dropped buffer pnum=%d play=%d addr=0x%x\n",
+ pipe->num, pipe->play_cnt, src_data->p[0].addr);
+ mdss_mdp_overlay_free_buf(src_data);
+ }
ret = mdss_mdp_overlay_get_buf(mfd, src_data, &req->data, 1, flags);
if (IS_ERR_VALUE(ret)) {
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 28d7051..d807493 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -64,6 +64,7 @@
MDSS_EVENT_CLOSE,
MDSS_EVENT_SUSPEND,
MDSS_EVENT_RESUME,
+ MDSS_EVENT_CHECK_PARAMS,
};
/* panel info type */
@@ -179,6 +180,7 @@
u32 frame_count;
u32 is_3d_panel;
u32 out_format;
+ u32 vic; /* video identification code */
struct lcd_panel_info lcd;
struct lcdc_panel_info lcdc;
diff --git a/drivers/video/msm/mdss/mdss_wb.c b/drivers/video/msm/mdss/mdss_wb.c
index c3dc06b..47dc2c8 100644
--- a/drivers/video/msm/mdss/mdss_wb.c
+++ b/drivers/video/msm/mdss/mdss_wb.c
@@ -25,11 +25,49 @@
#include "mdss_panel.h"
+/**
+ * mdss_wb_check_params - check new panel info params
+ * @pdata: current panel information
+ * @new: updates to panel info
+ *
+ * Checks if there are any changes that require panel reconfiguration
+ * in order to be reflected on writeback buffer.
+ *
+ * Return negative errno if invalid input, zero if there is no panel reconfig
+ * needed and non-zero if reconfiguration is needed.
+ */
+static int mdss_wb_check_params(struct mdss_panel_data *pdata,
+ struct mdss_panel_info *new)
+{
+ struct mdss_panel_info *old;
+
+ if (!pdata || !new) {
+ pr_err("%s: Invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ old = &pdata->panel_info;
+
+ if ((old->xres != new->xres) || (old->yres != new->yres))
+ return 1;
+
+ return 0;
+}
+
static int mdss_wb_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
- pr_debug("%s: event=%d\n", __func__, event);
- return 0;
+ int rc = 0;
+
+ switch (event) {
+ case MDSS_EVENT_CHECK_PARAMS:
+ rc = mdss_wb_check_params(pdata, (struct mdss_panel_info *)arg);
+ break;
+ default:
+ pr_debug("%s: panel event (%d) not handled\n", __func__, event);
+ break;
+ }
+ return rc;
}
static int mdss_wb_parse_dt(struct platform_device *pdev,
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index 2711c1a..d4d7288 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -264,7 +264,8 @@
typedef void (*fxn)(u32 data);
#define CMD_REQ_RX 0x0001
-#define CMD_REQ_COMMIT 0x0002
+#define CMD_REQ_COMMIT 0x0002
+#define CMD_CLK_CTRL 0x0004
#define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
struct dcs_cmd_req {
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index bea6b4e..96bfb9f 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -1580,7 +1580,6 @@
void mipi_dsi_cmdlist_commit(int from_mdp)
{
struct dcs_cmd_req *req;
- int video;
u32 dsi_ctrl;
mutex_lock(&cmd_mutex);
@@ -1592,12 +1591,6 @@
if (req == NULL)
goto need_lock;
- video = MIPI_INP(MIPI_DSI_BASE + 0x0000);
- video &= 0x02; /* VIDEO_MODE */
-
- if (!video)
- mipi_dsi_clk_cfg(1);
-
pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000);
@@ -1619,9 +1612,6 @@
else
mipi_dsi_cmdlist_tx(req);
- if (!video)
- mipi_dsi_clk_cfg(0);
-
need_lock:
if (from_mdp) /* from pipe_commit */
@@ -1655,9 +1645,15 @@
pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
cmdlist.tot, cmdlist.put, cmdlist.get);
+ if (req->flags & CMD_CLK_CTRL)
+ mipi_dsi_clk_cfg(1);
+
if (req->flags & CMD_REQ_COMMIT)
mipi_dsi_cmdlist_commit(0);
+ if (req->flags & CMD_CLK_CTRL)
+ mipi_dsi_clk_cfg(0);
+
return ret;
}
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index ecac82d..68bc65e 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -476,7 +476,7 @@
cmdreq.cmds = &backlight_cmd;
cmdreq.cmds_cnt = 1;
- cmdreq.flags = CMD_REQ_COMMIT;
+ cmdreq.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL;
cmdreq.rlen = 0;
cmdreq.cb = NULL;
diff --git a/fs/buffer.c b/fs/buffer.c
index ad5938c..35ac651 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1399,12 +1399,49 @@
return 0;
}
+static void __evict_bh_lru(void *arg)
+{
+ struct bh_lru *b = &get_cpu_var(bh_lrus);
+ struct buffer_head *bh = arg;
+ int i;
+
+ for (i = 0; i < BH_LRU_SIZE; i++) {
+ if (b->bhs[i] == bh) {
+ brelse(b->bhs[i]);
+ b->bhs[i] = NULL;
+ goto out;
+ }
+ }
+out:
+ put_cpu_var(bh_lrus);
+}
+
+static bool bh_exists_in_lru(int cpu, void *arg)
+{
+ struct bh_lru *b = per_cpu_ptr(&bh_lrus, cpu);
+ struct buffer_head *bh = arg;
+ int i;
+
+ for (i = 0; i < BH_LRU_SIZE; i++) {
+ if (b->bhs[i] == bh)
+ return 1;
+ }
+
+ return 0;
+
+}
void invalidate_bh_lrus(void)
{
on_each_cpu_cond(has_bh_in_lru, invalidate_bh_lru, NULL, 1, GFP_KERNEL);
}
EXPORT_SYMBOL_GPL(invalidate_bh_lrus);
+void evict_bh_lrus(struct buffer_head *bh)
+{
+ on_each_cpu_cond(bh_exists_in_lru, __evict_bh_lru, bh, 1, GFP_ATOMIC);
+}
+EXPORT_SYMBOL_GPL(evict_bh_lrus);
+
void set_bh_page(struct buffer_head *bh,
struct page *page, unsigned long offset)
{
@@ -3054,8 +3091,15 @@
do {
if (buffer_write_io_error(bh) && page->mapping)
set_bit(AS_EIO, &page->mapping->flags);
- if (buffer_busy(bh))
- goto failed;
+ if (buffer_busy(bh)) {
+ /*
+ * Check if the busy failure was due to an
+ * outstanding LRU reference
+ */
+ evict_bh_lrus(bh);
+ if (buffer_busy(bh))
+ goto failed;
+ }
bh = bh->b_this_page;
} while (bh != head);
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 29546b7..46ae59f 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -447,3 +447,4 @@
header-y += coresight-stm.h
header-y += ci-bridge-spi.h
header-y += msm_audio_amrwbplus.h
+header-y += avtimer.h
diff --git a/include/linux/avtimer.h b/include/linux/avtimer.h
new file mode 100644
index 0000000..e68da6a
--- /dev/null
+++ b/include/linux/avtimer.h
@@ -0,0 +1,21 @@
+#ifndef AVTIMER_H
+#define AVTIMER_H
+
+#include <linux/ioctl.h>
+
+#define MAJOR_NUM 100
+
+#define IOCTL_GET_AVTIMER_TICK _IOR(MAJOR_NUM, 0, char *)
+/*
+ * This IOCTL is used read the avtimer tick value.
+ * Avtimer is a 64 bit timer tick, hence the expected
+ * argument is of type uint64_t
+ */
+struct dev_avtimer_data {
+ uint32_t avtimer_msw_phy_addr;
+ uint32_t avtimer_lsw_phy_addr;
+};
+int avcs_core_open(void);
+int avcs_core_disable_power_collapse(int disable);/* true or flase */
+
+#endif
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 08f74e6..f8a3a10 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -61,14 +61,6 @@
MIGRATE_TYPES
};
-/*
- * Returns a list which contains the migrate types on to which
- * an allocation falls back when the free list for the migrate
- * type mtype is depleted.
- * The end of the list is delimited by the type MIGRATE_RESERVE.
- */
-extern int *get_migratetype_fallbacks(int mtype);
-
#ifdef CONFIG_CMA
# define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
# define cma_wmark_pages(zone) zone->min_cma_pages
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index e5e0bb4..3858022 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1840,6 +1840,12 @@
V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED = 1
};
+#define V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL (V4L2_CID_MPEG_MSM_VIDC_BASE + 26)
+enum v4l2_mpeg_vidc_perf_level {
+ V4L2_CID_MPEG_VIDC_PERF_LEVEL_PERFORMANCE = 0,
+ V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO = 1,
+};
+
/* Camera class control IDs */
#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900)
#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1)
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index a932011..971c9b3 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1032,7 +1032,13 @@
#define CAMERA_EFFECT_EMBOSS 9
#define CAMERA_EFFECT_SKETCH 10
#define CAMERA_EFFECT_NEON 11
-#define CAMERA_EFFECT_MAX 12
+#define CAMERA_EFFECT_FADED 12
+#define CAMERA_EFFECT_VINTAGECOOL 13
+#define CAMERA_EFFECT_VINTAGEWARM 14
+#define CAMERA_EFFECT_ACCENT_BLUE 15
+#define CAMERA_EFFECT_ACCENT_GREEN 16
+#define CAMERA_EFFECT_ACCENT_ORANGE 17
+#define CAMERA_EFFECT_MAX 18
/* QRD */
#define CAMERA_EFFECT_BW 10
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 45a8d86..a2bad88 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -401,9 +401,16 @@
static void __hrtick_start(void *arg)
{
struct rq *rq = arg;
+ struct hrtimer *timer = &rq->hrtick_timer;
+ ktime_t soft, hard;
+ unsigned long delta;
+
+ soft = hrtimer_get_softexpires(timer);
+ hard = hrtimer_get_expires(timer);
+ delta = ktime_to_ns(ktime_sub(hard, soft));
raw_spin_lock(&rq->lock);
- hrtimer_restart(&rq->hrtick_timer);
+ __hrtimer_start_range_ns(timer, soft, delta, HRTIMER_MODE_ABS, 0);
rq->hrtick_csd_pending = 0;
raw_spin_unlock(&rq->lock);
}
@@ -421,7 +428,8 @@
hrtimer_set_expires(timer, time);
if (rq == this_rq()) {
- hrtimer_restart(timer);
+ __hrtimer_start_range_ns(timer, ns_to_ktime(delay), 0,
+ HRTIMER_MODE_REL_PINNED, 0);
} else if (!rq->hrtick_csd_pending) {
__smp_call_function_single(cpu_of(rq), &rq->hrtick_csd, 0);
rq->hrtick_csd_pending = 1;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c3142e8..92dd060 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -913,11 +913,6 @@
[MIGRATE_ISOLATE] = { MIGRATE_RESERVE }, /* Never used */
};
-int *get_migratetype_fallbacks(int mtype)
-{
- return fallbacks[mtype];
-}
-
/*
* Move the free pages in a range to the free lists of the requested type.
* Note that start_page and end_pages are not aligned on a pageblock
@@ -1400,15 +1395,18 @@
unsigned int order;
unsigned long watermark;
struct zone *zone;
+ int mt;
BUG_ON(!PageBuddy(page));
zone = page_zone(page);
order = page_order(page);
+ mt = get_pageblock_migratetype(page);
/* Obey watermarks as if the page was being allocated */
watermark = low_wmark_pages(zone) + (1 << order);
- if (!zone_watermark_ok(zone, 0, watermark, 0, 0))
+ if (!is_migrate_cma(mt) && mt != MIGRATE_ISOLATE &&
+ !zone_watermark_ok(zone, 0, watermark, 0, 0))
return 0;
/* Remove page from free list */
@@ -1424,7 +1422,7 @@
if (order >= pageblock_order - 1) {
struct page *endpage = page + (1 << order) - 1;
for (; page < endpage; page += pageblock_nr_pages) {
- int mt = get_pageblock_migratetype(page);
+ mt = get_pageblock_migratetype(page);
if (mt != MIGRATE_ISOLATE && !is_migrate_cma(mt))
set_pageblock_migratetype(page,
MIGRATE_MOVABLE);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index e5f43ec..ea116e9 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1840,15 +1840,6 @@
struct hci_cp_auth_requested cp;
hci_remove_link_key(hdev, &conn->dst);
cp.handle = cpu_to_le16(conn->handle);
- /*Initiates dedicated bonding as pin or key is missing
- on remote device*/
- /*In case if remote device is ssp supported,
- reduce the security level to MEDIUM if it is HIGH*/
- if (conn->ssp_mode && conn->auth_initiator &&
- conn->io_capability != 0x03) {
- conn->pending_sec_level = BT_SECURITY_HIGH;
- conn->auth_type = HCI_AT_DEDICATED_BONDING_MITM;
- }
hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
sizeof(cp), &cp);
hci_dev_unlock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 23526f3..8568dae7 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3094,6 +3094,12 @@
goto no_auto_confirm;
}
+ /* Show bonding dialog if neither side requires no bonding */
+ if ((conn->auth_type > 0x01) && (conn->remote_auth > 0x01)) {
+ if (!loc_mitm && !rem_mitm)
+ value = 0;
+ goto no_auto_confirm;
+ }
if ((!loc_mitm || rem_cap == 0x03) && (!rem_mitm || loc_cap == 0x03))
ev.auto_confirm = 1;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index e11b985..e672cdb 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -295,6 +295,11 @@
(1 << AIF1_CAP) | (1 << AIF2_CAP), /* AIF2_CAP */
};
+static const u32 vport_i2s_check_table[NUM_CODEC_DAIS] = {
+ 0, /* AIF1_PB */
+ 0, /* AIF1_CAP */
+};
+
struct tabla_priv {
struct snd_soc_codec *codec;
struct tabla_reg_address reg_addr;
@@ -1746,6 +1751,7 @@
u32 dai_id = widget->shift;
u32 port_id = mixer->shift;
u32 enable = ucontrol->value.integer.value[0];
+ u32 vtable = vport_check_table[dai_id];
pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__,
widget->name, ucontrol->id.name, widget->value, widget->shift,
@@ -1767,8 +1773,13 @@
/* only add to the list if value not set
*/
if (enable && !(widget->value & 1 << port_id)) {
+ if (tabla_p->intf_type ==
+ WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ vtable = vport_check_table[dai_id];
+ if (tabla_p->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
+ vtable = vport_i2s_check_table[dai_id];
if (wcd9xxx_tx_vport_validation(
- vport_check_table[dai_id],
+ vtable,
port_id,
tabla_p->dai)) {
pr_info("%s: TX%u is used by other virtual port\n",
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 5ffb60a..ebb0421 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -181,6 +181,11 @@
(1 << AIF1_CAP) | (1 << AIF2_CAP), /* AIF2_CAP */
};
+static const u32 vport_i2s_check_table[NUM_CODEC_DAIS] = {
+ 0, /* AIF1_PB */
+ 0, /* AIF1_CAP */
+};
+
struct taiko_priv {
struct snd_soc_codec *codec;
u32 adc_count;
@@ -1523,6 +1528,7 @@
u32 dai_id = widget->shift;
u32 port_id = mixer->shift;
u32 enable = ucontrol->value.integer.value[0];
+ u32 vtable = vport_check_table[dai_id];
pr_debug("%s: wname %s cname %s value %u shift %d item %ld\n", __func__,
@@ -1539,7 +1545,6 @@
return -EINVAL;
}
}
- if (taiko_p->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
switch (dai_id) {
case AIF1_CAP:
case AIF2_CAP:
@@ -1547,8 +1552,16 @@
/* only add to the list if value not set
*/
if (enable && !(widget->value & 1 << port_id)) {
+
+ if (taiko_p->intf_type ==
+ WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ vtable = vport_check_table[dai_id];
+ if (taiko_p->intf_type ==
+ WCD9XXX_INTERFACE_TYPE_I2C)
+ vtable = vport_i2s_check_table[dai_id];
+
if (wcd9xxx_tx_vport_validation(
- vport_check_table[dai_id],
+ vtable,
port_id,
taiko_p->dai)) {
pr_debug("%s: TX%u is used by other\n"
@@ -1583,7 +1596,6 @@
mutex_unlock(&codec->mutex);
return -EINVAL;
}
- }
pr_debug("%s: name %s sname %s updated value %u shift %d\n", __func__,
widget->name, widget->sname, widget->value, widget->shift);
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 37a4234..f8185bb 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -1076,6 +1076,22 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
+ {
+ .name = "VoLTE",
+ .stream_name = "VoLTE",
+ .cpu_dai_name = "VoLTE",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_VOLTE,
+ },
/* Backend BT/FM DAI Links */
{
.name = LPASS_BE_INT_BT_SCO_RX,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index f1e0f3a..a1e461d 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -33,7 +33,9 @@
static struct snd_pcm_hardware msm_pcm_hardware = {
- .info = SNDRV_PCM_INFO_INTERLEAVED,
+ .info = (SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
.rate_min = 8000,
@@ -205,6 +207,55 @@
return 0;
}
+static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ int ret = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_voice *prtd = runtime->private_data;
+ uint16_t session_id = 0;
+
+ pr_debug("%s: cmd = %d\n", __func__, cmd);
+ if (is_volte(prtd))
+ session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+ else
+ session_id = voc_get_session_id(VOICE_SESSION_NAME);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_STOP:
+ pr_debug("Start & Stop Voice call not handled in Trigger.\n");
+ break;
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ pr_debug("%s: resume call session_id = %d\n", __func__,
+ session_id);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = msm_pcm_playback_prepare(substream);
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ ret = msm_pcm_capture_prepare(substream);
+ if (prtd->playback_start && prtd->capture_start)
+ voc_resume_voice_call(session_id);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ pr_debug("%s: pause call session_id=%d\n",
+ __func__, session_id);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (prtd->playback_start)
+ prtd->playback_start = 0;
+ } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ if (prtd->capture_start)
+ prtd->capture_start = 0;
+ }
+ voc_standby_voice_call(session_id);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
static int msm_voice_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -437,6 +488,7 @@
.hw_params = msm_pcm_hw_params,
.close = msm_pcm_close,
.prepare = msm_pcm_prepare,
+ .trigger = msm_pcm_trigger,
};
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index b799e59..263f47f 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -505,9 +505,9 @@
cvs_session_cmd.hdr.opcode =
VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
if (is_volte_session(v->session_id)) {
- strlcpy(mvm_session_cmd.mvm_session.name,
+ strlcpy(cvs_session_cmd.cvs_session.name,
"default volte voice",
- sizeof(mvm_session_cmd.mvm_session.name));
+ sizeof(cvs_session_cmd.cvs_session.name));
} else {
strlcpy(cvs_session_cmd.cvs_session.name,
"default modem voice",
@@ -3455,7 +3455,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);
@@ -3661,7 +3663,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);
@@ -3753,7 +3757,9 @@
mutex_lock(&v->lock);
- if (v->voc_state == VOC_RUN || v->voc_state == VOC_ERROR) {
+ if (v->voc_state == VOC_RUN || v->voc_state == VOC_ERROR ||
+ v->voc_state == VOC_STANDBY) {
+
pr_debug("%s: VOC_STATE: %d\n", __func__, v->voc_state);
ret = voice_destroy_vocproc(v);
@@ -3767,6 +3773,69 @@
return ret;
}
+int voc_standby_voice_call(uint16_t session_id)
+{
+ struct voice_data *v = voice_get_session(session_id);
+ struct apr_hdr mvm_standby_voice_cmd;
+ void *apr_mvm;
+ u16 mvm_handle;
+ int ret = 0;
+
+ pr_debug("%s: voc state=%d", __func__, v->voc_state);
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+ if (v->voc_state == VOC_RUN) {
+ apr_mvm = common.apr_q6_mvm;
+ if (!apr_mvm) {
+ pr_err("%s: apr_mvm is NULL.\n", __func__);
+ ret = -EINVAL;
+ goto fail;
+ }
+ mvm_handle = voice_get_mvm_handle(v);
+ mvm_standby_voice_cmd.hdr_field =
+ APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ mvm_standby_voice_cmd.pkt_size =
+ APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(mvm_standby_voice_cmd) - APR_HDR_SIZE);
+ pr_debug("send mvm_standby_voice_cmd pkt size = %d\n",
+ mvm_standby_voice_cmd.pkt_size);
+ mvm_standby_voice_cmd.src_port = v->session_id;
+ mvm_standby_voice_cmd.dest_port = mvm_handle;
+ mvm_standby_voice_cmd.token = 0;
+ mvm_standby_voice_cmd.opcode = VSS_IMVM_CMD_STANDBY_VOICE;
+ v->mvm_state = CMD_STATUS_FAIL;
+ ret = apr_send_pkt(apr_mvm,
+ (uint32_t *)&mvm_standby_voice_cmd);
+ if (ret < 0) {
+ pr_err("Fail in sending VSS_IMVM_CMD_STANDBY_VOICE\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+ v->voc_state = VOC_STANDBY;
+ }
+fail:
+ return ret;
+}
+
+int voc_resume_voice_call(uint16_t session_id)
+{
+ struct voice_data *v = voice_get_session(session_id);
+ int ret = 0;
+
+ ret = voice_send_start_voice_cmd(v);
+ if (ret < 0) {
+ pr_err("Fail in sending START_VOICE\n");
+ goto fail;
+ }
+ v->voc_state = VOC_RUN;
+ return 0;
+fail:
+ return -EINVAL;
+}
+
int voc_start_voice_call(uint16_t session_id)
{
struct voice_data *v = voice_get_session(session_id);
@@ -3845,6 +3914,10 @@
}
v->voc_state = VOC_RUN;
+ } else if (v->voc_state == VOC_STANDBY) {
+ pr_err("Error: start voice in Standby\n");
+ ret = -EINVAL;
+ goto fail;
}
fail:
mutex_unlock(&v->lock);
@@ -3961,6 +4034,7 @@
case VSS_IMVM_CMD_SET_CAL_NETWORK:
case VSS_IMVM_CMD_SET_CAL_MEDIA_TYPE:
case VSS_IMEMORY_CMD_UNMAP:
+ case VSS_IMVM_CMD_STANDBY_VOICE:
pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
v->mvm_state = CMD_STATUS_SUCCESS;
wake_up(&v->mvm_wait);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index aef463f..6fb4b04 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -68,6 +68,7 @@
VOC_CHANGE,
VOC_RELEASE,
VOC_ERROR,
+ VOC_STANDBY,
};
struct mem_buffer {
@@ -171,6 +172,9 @@
#define VSS_IMVM_CMD_START_VOICE 0x00011190
/**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
+#define VSS_IMVM_CMD_STANDBY_VOICE 0x00011191
+/**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
+
#define VSS_IMVM_CMD_STOP_VOICE 0x00011192
/**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
@@ -1227,6 +1231,8 @@
int voc_set_tty_mode(uint16_t session_id, uint8_t tty_mode);
int voc_start_voice_call(uint16_t session_id);
int voc_end_voice_call(uint16_t session_id);
+int voc_standby_voice_call(uint16_t session_id);
+int voc_resume_voice_call(uint16_t session_id);
int voc_set_rxtx_port(uint16_t session_id,
uint32_t dev_port_id,
uint32_t dev_type);