Merge "msm: ocmem: Add support for tail growth." into msm-3.0
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index a0df120..99747ba 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -1180,20 +1180,16 @@
unsigned int i;
struct gic_chip_data *gic = &gic_data[0];
void __iomem *base = gic_data_dist_base(gic);
- unsigned long flags;
gic_cpu_save(0);
gic_dist_save(0);
- /* Disable all the Interrupts, if we enter from idle pc */
- if (from_idle) {
- for (i = 0; (i * 32) < gic->max_irq; i++) {
- raw_spin_lock_irqsave(
- &irq_controller_lock, flags);
- writel_relaxed(0xffffffff, base
- + GIC_DIST_ENABLE_CLEAR + i * 4);
- raw_spin_unlock_irqrestore(
- &irq_controller_lock, flags);
- }
+
+ /* Disable all the Interrupts, before we enter pc */
+ for (i = 0; (i * 32) < gic->max_irq; i++) {
+ raw_spin_lock(&irq_controller_lock);
+ writel_relaxed(0xffffffff, base
+ + GIC_DIST_ENABLE_CLEAR + i * 4);
+ raw_spin_unlock(&irq_controller_lock);
}
}
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 041e755..a65c5b0 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -653,23 +653,23 @@
/* TODO: Update core voltages when data is available. */
static struct acpu_level acpu_freq_tbl_8930[] = {
- { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 925000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 925000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 937500 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 962500 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 987500 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1000000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1062500 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1062500 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1087500 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(16), 1100000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1100000 },
- { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1100000 },
- { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1100000 },
- { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1125000 },
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 925000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 925000 },
+ { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 937500 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 962500 },
+ { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 987500 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 1000000 },
+ { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1037500 },
+ { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1062500 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1087500 },
+ { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1125000 },
+ { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(16), 1137500 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1162500 },
+ { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1187500 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1200000 },
+ { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1225000 },
{ 0, { 0 } }
};
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 91fd400..1a0a287 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -127,6 +127,7 @@
/* TABLA CODEC RESET */
PM8921_GPIO_OUTPUT(34, 1, MED),
PM8921_GPIO_INPUT(31, PM_GPIO_PULL_NO),
+ PM8921_GPIO_OUTPUT(13, 0, HIGH), /* PCIE_CLK_PWR_EN */
};
static struct pm8xxx_gpio_init pm8921_mtp_kp_gpios[] __initdata = {
@@ -146,6 +147,8 @@
PM8921_MPP_INIT(8, D_OUTPUT, PM8921_MPP_DIG_LEVEL_S4, DOUT_CTRL_LOW),
/*MPP9 is used to detect docking station connection/removal on Liquid*/
PM8921_MPP_INIT(9, D_INPUT, PM8921_MPP_DIG_LEVEL_S4, DIN_TO_INT),
+ /* PCIE_RESET_N */
+ PM8921_MPP_INIT(1, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_HIGH),
};
void __init apq8064_pm8xxx_gpio_mpp_init(void)
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 58e83a0..3d2dbaa 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -157,6 +157,8 @@
REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_ehci_host.1"),
REGULATOR_SUPPLY("HSIC_VDDCX", "msm_hsic_host"),
REGULATOR_SUPPLY("riva_vddcx", "wcnss_wlan.0"),
+ REGULATOR_SUPPLY("vp_pcie", "msm_pcie"),
+ REGULATOR_SUPPLY("vptx_pcie", "msm_pcie"),
};
VREG_CONSUMERS(S4) = {
REGULATOR_SUPPLY("8921_s4", NULL),
@@ -213,6 +215,7 @@
};
VREG_CONSUMERS(LVS6) = {
REGULATOR_SUPPLY("8921_lvs6", NULL),
+ REGULATOR_SUPPLY("vdd_pcie_vph", "msm_pcie"),
};
VREG_CONSUMERS(LVS7) = {
REGULATOR_SUPPLY("8921_lvs7", NULL),
@@ -256,6 +259,7 @@
REGULATOR_SUPPLY("lvds_vccs_3p3v", "lvds.0"),
REGULATOR_SUPPLY("dsi1_vccs_3p3v", "mipi_dsi.1"),
REGULATOR_SUPPLY("hdmi_mux_vdd", "hdmi_msm.0"),
+ REGULATOR_SUPPLY("pcie_ext_3p3v", "msm_pcie"),
};
VREG_CONSUMERS(EXT_TS_SW) = {
REGULATOR_SUPPLY("ext_ts_sw", NULL),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index ed17cc4..c123138 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -69,6 +69,7 @@
#include <sound/cs8427.h>
#include <media/gpio-ir-recv.h>
#include <linux/fmem.h>
+#include <mach/msm_pcie.h>
#include "msm_watchdog.h"
#include "board-8064.h"
@@ -114,6 +115,10 @@
#define MSM_MM_FW_SIZE 0x200000
#define APQ8064_FW_START (APQ8064_FIXED_AREA_START - MSM_MM_FW_SIZE)
+/* PCIe power enable pmic gpio */
+#define PCIE_PWR_EN_PMIC_GPIO 13
+#define PCIE_RST_N_PMIC_MPP 1
+
#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE;
static int __init pmem_kernel_ebi1_size_setup(char *p)
@@ -1998,6 +2003,22 @@
msm_bus_8064_cpss_fpb.dev.platform_data = &msm_bus_8064_cpss_fpb_pdata;
}
+/* PCIe gpios */
+static struct msm_pcie_gpio_info_t msm_pcie_gpio_info[MSM_PCIE_MAX_GPIO] = {
+ {"rst_n", PM8921_MPP_PM_TO_SYS(PCIE_RST_N_PMIC_MPP), 0},
+ {"pwr_en", PM8921_GPIO_PM_TO_SYS(PCIE_PWR_EN_PMIC_GPIO), 1},
+};
+
+static struct msm_pcie_platform msm_pcie_platform_data = {
+ .gpio = msm_pcie_gpio_info,
+};
+
+static void __init mpq8064_pcie_init(void)
+{
+ msm_device_pcie.dev.platform_data = &msm_pcie_platform_data;
+ platform_device_register(&msm_device_pcie);
+}
+
static struct platform_device apq8064_device_ext_5v_vreg __devinitdata = {
.name = GPIO_REGULATOR_DEV_NAME,
.id = PM8921_MPP_PM_TO_SYS(7),
@@ -2877,6 +2898,7 @@
machine_is_mpq8064_dtv()) {
enable_avc_i2c_bus();
platform_add_devices(mpq_devices, ARRAY_SIZE(mpq_devices));
+ mpq8064_pcie_init();
} else {
ethernet_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c
index e23b76c..3c3843a 100644
--- a/arch/arm/mach-msm/board-8930-gpu.c
+++ b/arch/arm/mach-msm/board-8930-gpu.c
@@ -115,7 +115,7 @@
static struct kgsl_device_platform_data kgsl_3d0_pdata = {
.pwrlevel = {
{
- .gpu_freq = 400000000,
+ .gpu_freq = 450000000,
.bus_freq = 3,
.io_fraction = 0,
},
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 978eb09..1c6c600 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -55,6 +55,21 @@
.pull = GPIOMUX_PULL_NONE,
};
+static struct gpiomux_setting external_vfr[] = {
+ /* Suspended state */
+ {
+ .func = GPIOMUX_FUNC_3,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+ },
+ /* Active state */
+ {
+ .func = GPIOMUX_FUNC_3,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+ },
+};
+
static struct gpiomux_setting gsbi_uart = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
@@ -424,6 +439,16 @@
},
};
+static struct msm_gpiomux_config msm8960_external_vfr_configs[] __initdata = {
+ {
+ .gpio = 23, /* EXTERNAL VFR */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &external_vfr[0],
+ [GPIOMUX_ACTIVE] = &external_vfr[1],
+ },
+ },
+};
+
static struct msm_gpiomux_config msm8960_gsbi8_uart_configs[] __initdata = {
{
.gpio = 34, /* GSBI8 UART3 */
@@ -953,15 +978,19 @@
else
msm_gpiomux_install(msm8960_gsbi5_uart_configs,
ARRAY_SIZE(msm8960_gsbi5_uart_configs));
- /* For 8960 Fusion 2.2 Primary IPC */
- if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+
+ if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
+ /* For 8960 Fusion 2.2 Primary IPC */
msm_gpiomux_install(msm8960_fusion_gsbi_configs,
ARRAY_SIZE(msm8960_fusion_gsbi_configs));
+ /* For SGLTE 8960 Fusion External VFR */
+ msm_gpiomux_install(msm8960_external_vfr_configs,
+ ARRAY_SIZE(msm8960_external_vfr_configs));
+ }
#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
msm_gpiomux_install(msm8960_sdcc2_configs,
ARRAY_SIZE(msm8960_sdcc2_configs));
#endif
-
return 0;
}
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index b0799c2..e172481 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2639,7 +2639,11 @@
#define MSM_SMI_SIZE 0x4000000
#define KERNEL_SMI_BASE (MSM_SMI_BASE)
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+#define KERNEL_SMI_SIZE 0x000000
+#else
#define KERNEL_SMI_SIZE 0x600000
+#endif
#define USER_SMI_BASE (KERNEL_SMI_BASE + KERNEL_SMI_SIZE)
#define USER_SMI_SIZE (MSM_SMI_SIZE - KERNEL_SMI_SIZE)
@@ -2648,7 +2652,7 @@
#define MSM_ION_SF_SIZE 0x4000000 /* 64MB */
#define MSM_ION_CAMERA_SIZE MSM_PMEM_ADSP_SIZE
#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */
-#define MSM_ION_MM_SIZE 0x3600000 /* (54MB) Must be a multiple of 64K */
+#define MSM_ION_MM_SIZE 0x3c00000 /* (60MB) Must be a multiple of 64K */
#define MSM_ION_MFC_SIZE SZ_8K
#ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK
#define MSM_ION_WB_SIZE 0xC00000 /* 12MB */
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 3a0b87e..1ebf597 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4992,9 +4992,9 @@
CLK_LOOKUP("iface_clk", sdc2_p_clk.c, "msm_sdcc.2"),
CLK_LOOKUP("iface_clk", sdc3_p_clk.c, "msm_sdcc.3"),
CLK_LOOKUP("iface_clk", sdc4_p_clk.c, "msm_sdcc.4"),
- CLK_LOOKUP("iface_clk", pcie_p_clk.c, ""),
- CLK_LOOKUP("ref_clk", pcie_phy_ref_clk.c, ""),
- CLK_LOOKUP("bus_clk", pcie_a_clk.c, ""),
+ CLK_LOOKUP("iface_clk", pcie_p_clk.c, "msm_pcie"),
+ CLK_LOOKUP("ref_clk", pcie_phy_ref_clk.c, "msm_pcie"),
+ CLK_LOOKUP("bus_clk", pcie_a_clk.c, "msm_pcie"),
CLK_LOOKUP("core_clk", adm0_clk.c, "msm_dmov"),
CLK_LOOKUP("iface_clk", adm0_p_clk.c, "msm_dmov"),
CLK_LOOKUP("iface_clk", pmic_arb0_p_clk.c, ""),
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index f6eee76..29a90e4 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -82,6 +82,25 @@
#define MSM_HSUSB4_PHYS 0x12530000
#define MSM_HSUSB4_SIZE SZ_4K
+/* Address of PCIE20 PARF */
+#define PCIE20_PARF_PHYS 0x1b600000
+#define PCIE20_PARF_SIZE SZ_128
+
+/* Address of PCIE20 ELBI */
+#define PCIE20_ELBI_PHYS 0x1b502000
+#define PCIE20_ELBI_SIZE SZ_256
+
+/* Address of PCIE20 */
+#define PCIE20_PHYS 0x1b500000
+#define PCIE20_SIZE SZ_4K
+
+/* AXI address for PCIE device BAR resources */
+#define PCIE_AXI_BAR_PHYS 0x08000000
+#define PCIE_AXI_BAR_SIZE SZ_8M
+
+/* AXI address for PCIE device config space */
+#define PCIE_AXI_CONF_PHYS 0x08c00000
+#define PCIE_AXI_CONF_SIZE SZ_4K
static struct msm_watchdog_pdata msm_watchdog_pdata = {
.pet_time = 10000,
@@ -1518,6 +1537,46 @@
},
};
+static struct resource resources_msm_pcie[] = {
+ {
+ .name = "parf",
+ .start = PCIE20_PARF_PHYS,
+ .end = PCIE20_PARF_PHYS + PCIE20_PARF_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "elbi",
+ .start = PCIE20_ELBI_PHYS,
+ .end = PCIE20_ELBI_PHYS + PCIE20_ELBI_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "pcie20",
+ .start = PCIE20_PHYS,
+ .end = PCIE20_PHYS + PCIE20_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "axi_bar",
+ .start = PCIE_AXI_BAR_PHYS,
+ .end = PCIE_AXI_BAR_PHYS + PCIE_AXI_BAR_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "axi_conf",
+ .start = PCIE_AXI_CONF_PHYS,
+ .end = PCIE_AXI_CONF_PHYS + PCIE_AXI_CONF_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device msm_device_pcie = {
+ .name = "msm_pcie",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_msm_pcie),
+ .resource = resources_msm_pcie,
+};
+
#ifdef CONFIG_HW_RANDOM_MSM
/* PRNG device */
#define MSM_PRNG_PHYS 0x1A500000
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 8f42ede..d01a229 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -167,6 +167,8 @@
extern struct platform_device msm_device_dmov_adm0;
extern struct platform_device msm_device_dmov_adm1;
+extern struct platform_device msm_device_pcie;
+
extern struct platform_device msm_device_nand;
extern struct platform_device msm_device_tssc;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 34640c3..7b7549a 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -194,6 +194,7 @@
return -ENOMEM;
}
}
+ driver->data_ready[i] = 0x0;
driver->data_ready[i] |= MSG_MASKS_TYPE;
driver->data_ready[i] |= EVENT_MASKS_TYPE;
driver->data_ready[i] |= LOG_MASKS_TYPE;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 1432ccf..2f503ae 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -21,6 +21,7 @@
#include "kgsl_pwrscale.h"
#include "kgsl_cffdump.h"
#include "kgsl_sharedmem.h"
+#include "kgsl_iommu.h"
#include "adreno.h"
#include "adreno_pm4types.h"
@@ -243,7 +244,144 @@
return result;
}
-static void adreno_setstate(struct kgsl_device *device,
+static void adreno_iommu_setstate(struct kgsl_device *device,
+ uint32_t flags)
+{
+ unsigned int pt_val, reg_pt_val;
+ unsigned int link[200];
+ unsigned int *cmds = &link[0];
+ int sizedwords = 0;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct kgsl_memdesc **reg_map_desc;
+ void *reg_map_array;
+ int num_iommu_units, i;
+
+ if (!adreno_dev->drawctxt_active)
+ return kgsl_mmu_device_setstate(&device->mmu, flags);
+ num_iommu_units = kgsl_mmu_get_reg_map_desc(&device->mmu,
+ ®_map_array);
+ reg_map_desc = reg_map_array;
+
+ if (kgsl_mmu_enable_clk(&device->mmu,
+ KGSL_IOMMU_CONTEXT_USER))
+ goto done;
+
+ if (adreno_is_a225(adreno_dev))
+ cmds += adreno_add_change_mh_phys_limit_cmds(cmds, 0xFFFFF000,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ else
+ cmds += adreno_add_bank_change_cmds(cmds,
+ KGSL_IOMMU_CONTEXT_USER,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+
+ if (flags & KGSL_MMUFLAGS_PTUPDATE) {
+ pt_val = kgsl_mmu_pt_get_base_addr(device->mmu.hwpagetable);
+ /*
+ * We need to perfrom the following operations for all
+ * IOMMU units
+ */
+ for (i = 0; i < num_iommu_units; i++) {
+ reg_pt_val = (pt_val &
+ (KGSL_IOMMU_TTBR0_PA_MASK <<
+ KGSL_IOMMU_TTBR0_PA_SHIFT)) +
+ kgsl_mmu_get_pt_lsb(&device->mmu, i,
+ KGSL_IOMMU_CONTEXT_USER);
+ /*
+ * Set address of the new pagetable by writng to IOMMU
+ * TTBR0 register
+ */
+ *cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
+ *cmds++ = reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_TTBR0;
+ *cmds++ = reg_pt_val;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+
+ /*
+ * Read back the ttbr0 register as a barrier to ensure
+ * above writes have completed
+ */
+ cmds += adreno_add_read_cmds(device, cmds,
+ reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_TTBR0,
+ reg_pt_val,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+
+ /* set the asid */
+ *cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
+ *cmds++ = reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_CONTEXTIDR;
+ *cmds++ = kgsl_mmu_get_hwpagetable_asid(&device->mmu);
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+
+ /* Read back asid to ensure above write completes */
+ cmds += adreno_add_read_cmds(device, cmds,
+ reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_CONTEXTIDR,
+ kgsl_mmu_get_hwpagetable_asid(&device->mmu),
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ }
+ /* invalidate all base pointers */
+ *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
+ *cmds++ = 0x7fff;
+
+ if (flags & KGSL_MMUFLAGS_TLBFLUSH)
+ cmds += __adreno_add_idle_indirect_cmds(cmds,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ }
+ if (flags & KGSL_MMUFLAGS_TLBFLUSH) {
+ /*
+ * tlb flush based on asid, no need to flush entire tlb
+ */
+ for (i = 0; i < num_iommu_units; i++) {
+ *cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
+ *cmds++ = (reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) +
+ KGSL_IOMMU_CTX_TLBIASID);
+ *cmds++ = kgsl_mmu_get_hwpagetable_asid(&device->mmu);
+ cmds += adreno_add_read_cmds(device, cmds,
+ reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) +
+ KGSL_IOMMU_CONTEXTIDR,
+ kgsl_mmu_get_hwpagetable_asid(&device->mmu),
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ }
+ }
+
+ if (adreno_is_a225(adreno_dev))
+ cmds += adreno_add_change_mh_phys_limit_cmds(cmds,
+ reg_map_desc[num_iommu_units - 1]->gpuaddr - PAGE_SIZE,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ else
+ cmds += adreno_add_bank_change_cmds(cmds,
+ KGSL_IOMMU_CONTEXT_PRIV,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+
+ sizedwords += (cmds - &link[0]);
+ if (sizedwords)
+ adreno_ringbuffer_issuecmds(device,
+ KGSL_CMD_FLAGS_PMODE, &link[0], sizedwords);
+done:
+ if (num_iommu_units)
+ kfree(reg_map_array);
+}
+
+static void adreno_gpummu_setstate(struct kgsl_device *device,
uint32_t flags)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
@@ -253,16 +391,6 @@
unsigned int mh_mmu_invalidate = 0x00000003; /*invalidate all and tc */
/*
- * A3XX doesn't support the fast path (the registers don't even exist)
- * so just bail out early
- */
-
- if (adreno_is_a3xx(adreno_dev)) {
- kgsl_mmu_device_setstate(&device->mmu, flags);
- return;
- }
-
- /*
* If possible, then set the state via the command stream to avoid
* a CPU idle. Otherwise, use the default setstate which uses register
* writes For CFF dump we must idle and use the registers so that it is
@@ -348,6 +476,16 @@
}
}
+static void adreno_setstate(struct kgsl_device *device,
+ uint32_t flags)
+{
+ /* call the mmu specific handler */
+ if (KGSL_MMU_TYPE_GPU == kgsl_mmu_get_mmutype())
+ return adreno_gpummu_setstate(device, flags);
+ else if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
+ return adreno_iommu_setstate(device, flags);
+}
+
static unsigned int
a3xx_getchipid(struct kgsl_device *device)
{
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index a7ea20c..4ce56a4 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -16,6 +16,7 @@
#include "kgsl_device.h"
#include "adreno_drawctxt.h"
#include "adreno_ringbuffer.h"
+#include "kgsl_iommu.h"
#define DEVICE_3D_NAME "kgsl-3d"
#define DEVICE_3D0_NAME "kgsl-3d0"
@@ -223,4 +224,70 @@
return (ilog2(size) - 5) << 29;
}
+static inline int __adreno_add_idle_indirect_cmds(unsigned int *cmds,
+ unsigned int nop_gpuaddr)
+{
+ /* Adding an indirect buffer ensures that the prefetch stalls until
+ * the commands in indirect buffer have completed. We need to stall
+ * prefetch with a nop indirect buffer when updating pagetables
+ * because it provides stabler synchronization */
+ *cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
+ *cmds++ = nop_gpuaddr;
+ *cmds++ = 2;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+ return 5;
+}
+
+static inline int adreno_add_change_mh_phys_limit_cmds(unsigned int *cmds,
+ unsigned int new_phys_limit,
+ unsigned int nop_gpuaddr)
+{
+ unsigned int *start = cmds;
+
+ cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
+ *cmds++ = cp_type0_packet(MH_MMU_MPU_END, 1);
+ *cmds++ = new_phys_limit;
+ cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
+ return cmds - start;
+}
+
+static inline int adreno_add_bank_change_cmds(unsigned int *cmds,
+ int cur_ctx_bank,
+ unsigned int nop_gpuaddr)
+{
+ unsigned int *start = cmds;
+
+ cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
+ *cmds++ = cp_type0_packet(REG_CP_STATE_DEBUG_INDEX, 1);
+ *cmds++ = (cur_ctx_bank ? 0 : 0x20);
+ cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
+ return cmds - start;
+}
+
+/*
+ * adreno_read_cmds - Add pm4 packets to perform read
+ * @device - Pointer to device structure
+ * @cmds - Pointer to memory where read commands need to be added
+ * @addr - gpu address of the read
+ * @val - The GPU will wait until the data at address addr becomes
+ * equal to value
+ */
+static inline int adreno_add_read_cmds(struct kgsl_device *device,
+ unsigned int *cmds, unsigned int addr,
+ unsigned int val, unsigned int nop_gpuaddr)
+{
+ unsigned int *start = cmds;
+
+ *cmds++ = cp_type3_packet(CP_WAIT_REG_MEM, 5);
+ /* MEM SPACE = memory, FUNCTION = equals */
+ *cmds++ = 0x13;
+ *cmds++ = addr;
+ *cmds++ = val;
+ *cmds++ = 0xFFFFFFFF;
+ *cmds++ = 0xFFFFFFFF;
+ cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
+ return cmds - start;
+}
+
#endif /*__ADRENO_H */
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index eb936f8..ae846da 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1848,8 +1848,13 @@
/* NQ and External Memory Swap */
GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
- /* Protected mode error checking */
- GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL);
+ /* Protected mode error checking
+ * If iommu is used then protection needs to be turned off
+ * to enable context bank switching */
+ if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
+ GSL_RB_WRITE(cmds, cmds_gpu, 0);
+ else
+ GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL);
/* Disable header dumping and Header dump address */
GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
/* Header dump size */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 6980f55..cf09f52 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -388,12 +388,18 @@
if (context == NULL)
return;
device = context->dev_priv->device;
- kgsl_cancel_events_ctxt(device, context);
id = context->id;
+
if (device->ftbl->drawctxt_destroy)
device->ftbl->drawctxt_destroy(device, context);
/*device specific drawctxt_destroy MUST clean up devctxt */
BUG_ON(context->devctxt);
+ /*
+ * Cancel events after the device-specific context is
+ * destroyed, to avoid possibly freeing memory while
+ * it is still in use by the GPU.
+ */
+ kgsl_cancel_events_ctxt(device, context);
idr_remove(&device->context_idr, id);
context->id = KGSL_CONTEXT_INVALID;
kgsl_context_put(context);
@@ -778,11 +784,6 @@
mutex_lock(&device->mutex);
kgsl_check_suspended(device);
- /* clean up any to-be-freed entries that belong to this
- * process and this device
- */
- kgsl_cancel_events(device, dev_priv);
-
while (1) {
context = idr_get_next(&device->context_idr, &next);
if (context == NULL)
@@ -793,6 +794,13 @@
next = next + 1;
}
+ /*
+ * Clean up any to-be-freed entries that belong to this
+ * process and this device. This is done after the context
+ * are destroyed to avoid possibly freeing memory while
+ * it is still in use by the GPU.
+ */
+ kgsl_cancel_events(device, dev_priv);
device->open_count--;
if (device->open_count == 0) {
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index fdd4aa5..fb65565 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -595,7 +595,9 @@
kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000001);
kgsl_regwrite(mmu->device, MH_MMU_MPU_END,
mh->mpu_base +
- iommu->iommu_units[0].reg_map.gpuaddr - PAGE_SIZE);
+ iommu->iommu_units
+ [iommu->unit_count - 1].reg_map.gpuaddr -
+ PAGE_SIZE);
} else {
kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
}
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 663ba0f..b882807 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -545,8 +545,7 @@
struct kgsl_device *device = mmu->device;
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return;
- else if (device->ftbl->setstate && (KGSL_MMU_TYPE_IOMMU !=
- kgsl_mmu_type))
+ else if (device->ftbl->setstate)
device->ftbl->setstate(device, flags);
else if (mmu->mmu_ops->mmu_device_setstate)
mmu->mmu_ops->mmu_device_setstate(mmu, flags);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 3a29d71..2aaefba 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -706,6 +706,7 @@
}
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_NAP);
+ kgsl_mmu_disable_clk(&device->mmu);
kgsl_pwrctrl_set_state(device, KGSL_STATE_NAP);
if (device->idle_wakelock.name)
wake_unlock(&device->idle_wakelock);
@@ -749,6 +750,7 @@
gpu_freq);
_sleep_accounting(device);
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP);
+ kgsl_mmu_disable_clk(&device->mmu);
kgsl_pwrctrl_set_state(device, KGSL_STATE_SLEEP);
wake_unlock(&device->idle_wakelock);
pm_qos_update_request(&device->pm_qos_req_dma,
@@ -888,6 +890,7 @@
/* Order pwrrail/clk sequence based upon platform */
kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_OFF);
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP);
+ kgsl_mmu_disable_clk(&device->mmu);
kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_OFF);
}
EXPORT_SYMBOL(kgsl_pwrctrl_disable);
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 3aff7f17..889c416 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -461,7 +461,13 @@
pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM -
- SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+ SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+ if (idx < 0) {
+ pr_err("%s: Error:-Invalid index found = %d\n",
+ __func__, idx);
+ ret = -EINVAL;
+ goto err;
+ }
sph[i] = rx[idx].sph;
grph = rx[idx].grph;
}
@@ -501,6 +507,12 @@
pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM);
+ if (idx < 0) {
+ pr_err("%s: Error:- Invalid index found = %d\n",
+ __func__, idx);
+ ret = -EINVAL;
+ goto err;
+ }
sph[i] = tx[idx].sph;
grph = tx[idx].grph;
}
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 2c42bc7..4c92ee5 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1271,9 +1271,11 @@
{
struct ion_handle *ihandle; /* Ion handle */
struct qseecom_load_img_req load_img_req;
- int32_t ret;
+ int ret;
+ int set_cpu_ret = 0;
ion_phys_addr_t pa = 0;
uint32_t len;
+ struct cpumask mask;
struct qseecom_load_app_ireq load_req;
struct qseecom_command_scm_resp resp;
@@ -1302,14 +1304,25 @@
load_req.img_len = load_img_req.img_len;
load_req.phy_addr = pa;
+ /* SCM_CALL tied to Core0 */
+ mask = CPU_MASK_CPU0;
+ set_cpu_ret = set_cpus_allowed_ptr(current, &mask);
+ if (set_cpu_ret) {
+ pr_err("set_cpus_allowed_ptr failed : ret %d\n",
+ set_cpu_ret);
+ ret = -EFAULT;
+ goto qseecom_load_external_elf_set_cpu_err;
+ }
+
/* SCM_CALL to load the external elf */
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
sizeof(struct qseecom_load_app_ireq),
&resp, sizeof(resp));
if (ret) {
- pr_err("scm_call to unload failed : ret %d\n",
+ pr_err("scm_call to load failed : ret %d\n",
ret);
ret = -EFAULT;
+ goto qseecom_load_external_elf_scm_err;
}
if (resp.result == QSEOS_RESULT_INCOMPLETE) {
@@ -1324,6 +1337,18 @@
ret = -EFAULT;
}
}
+
+qseecom_load_external_elf_scm_err:
+ /* Restore the CPU mask */
+ mask = CPU_MASK_ALL;
+ set_cpu_ret = set_cpus_allowed_ptr(current, &mask);
+ if (set_cpu_ret) {
+ pr_err("set_cpus_allowed_ptr failed to restore mask: ret %d\n",
+ set_cpu_ret);
+ ret = -EFAULT;
+ }
+
+qseecom_load_external_elf_set_cpu_err:
/* Deallocate the handle */
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
@@ -1334,11 +1359,23 @@
static int qseecom_unload_external_elf(struct qseecom_dev_handle *data)
{
int ret = 0;
+ int set_cpu_ret = 0;
struct qseecom_command_scm_resp resp;
struct qseecom_unload_app_ireq req;
+ struct cpumask mask;
/* Populate the structure for sending scm call to unload image */
req.qsee_cmd_id = QSEOS_UNLOAD_EXTERNAL_ELF_COMMAND;
+
+ /* SCM_CALL tied to Core0 */
+ mask = CPU_MASK_CPU0;
+ ret = set_cpus_allowed_ptr(current, &mask);
+ if (ret) {
+ pr_err("set_cpus_allowed_ptr failed : ret %d\n",
+ ret);
+ return -EFAULT;
+ }
+
/* SCM_CALL to unload the external elf */
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
sizeof(struct qseecom_unload_app_ireq),
@@ -1346,7 +1383,8 @@
if (ret) {
pr_err("scm_call to unload failed : ret %d\n",
ret);
- return -EFAULT;
+ ret = -EFAULT;
+ goto qseecom_unload_external_elf_scm_err;
}
if (resp.result == QSEOS_RESULT_INCOMPLETE) {
ret = __qseecom_process_incomplete_cmd(data, &resp);
@@ -1360,6 +1398,17 @@
ret = -EFAULT;
}
}
+
+qseecom_unload_external_elf_scm_err:
+ /* Restore the CPU mask */
+ mask = CPU_MASK_ALL;
+ set_cpu_ret = set_cpus_allowed_ptr(current, &mask);
+ if (set_cpu_ret) {
+ pr_err("set_cpus_allowed_ptr failed to restore mask: ret %d\n",
+ set_cpu_ret);
+ ret = -EFAULT;
+ }
+
return ret;
}
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 4967c4e..717f1d3 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1691,14 +1691,17 @@
* will take care of signaling sdio irq during
* mmc_sdio_resume().
*/
- if (host->sdcc_suspended)
+ if (host->sdcc_suspended) {
/*
* This is a wakeup interrupt so hold wakelock
* until SDCC resume is handled.
*/
wake_lock(&host->sdio_wlock);
- else
+ } else {
+ spin_unlock(&host->lock);
mmc_signal_sdio_irq(host->mmc);
+ spin_lock(&host->lock);
+ }
ret = 1;
break;
}
@@ -1725,7 +1728,9 @@
if (status & MCI_SDIOINTROPE) {
if (host->sdcc_suspending)
wake_lock(&host->sdio_suspend_wlock);
+ spin_unlock(&host->lock);
mmc_signal_sdio_irq(host->mmc);
+ spin_lock(&host->lock);
}
data = host->curr.data;
@@ -3105,15 +3110,14 @@
* clocks mci_irqenable will be written to MASK0 register.
*/
+ spin_lock_irqsave(&host->lock, flags);
if (enable) {
- spin_lock_irqsave(&host->lock, flags);
host->mci_irqenable |= MCI_SDIOINTOPERMASK;
if (host->clks_on) {
writel_relaxed(readl_relaxed(host->base + MMCIMASK0) |
MCI_SDIOINTOPERMASK, host->base + MMCIMASK0);
mb();
}
- spin_unlock_irqrestore(&host->lock, flags);
} else {
host->mci_irqenable &= ~MCI_SDIOINTOPERMASK;
if (host->clks_on) {
@@ -3122,6 +3126,7 @@
mb();
}
}
+ spin_unlock_irqrestore(&host->lock, flags);
}
#ifdef CONFIG_PM_RUNTIME
@@ -3934,10 +3939,13 @@
}
if (host->plat->is_sdio_al_client) {
wake_lock(&host->sdio_wlock);
+ spin_unlock(&host->lock);
mmc_signal_sdio_irq(host->mmc);
+ goto out_unlocked;
}
spin_unlock(&host->lock);
+out_unlocked:
return IRQ_HANDLED;
}
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index d74959e..15fc0c1 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -223,6 +223,7 @@
char **uevent_envp = NULL;
static enum android_device_state last_uevent, next_state;
unsigned long flags;
+ int pm_qos_vote = -1;
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->config) {
@@ -232,13 +233,16 @@
uevent_envp = dev->connected ? connected : disconnected;
next_state = dev->connected ? USB_CONNECTED : USB_DISCONNECTED;
if (dev->connected && strncmp(dev->pm_qos, "low", 3))
- android_pm_qos_update_latency(dev, 1);
+ pm_qos_vote = 1;
else if (!dev->connected || !strncmp(dev->pm_qos, "low", 3))
- android_pm_qos_update_latency(dev, 0);
+ pm_qos_vote = 0;
}
dev->sw_connected = dev->connected;
spin_unlock_irqrestore(&cdev->lock, flags);
+ if (pm_qos_vote != -1)
+ android_pm_qos_update_latency(dev, pm_qos_vote);
+
if (uevent_envp) {
/*
* Some userspace modules, e.g. MTP, work correctly only if
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 471ed4e..3d35dd5 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -659,6 +659,7 @@
goto error_extra;
INIT_WORK(&mgmt->mdp_histogram_worker, mdp_hist_read_work);
+ mgmt->hist = NULL;
mdp_hist_mgmt_array[index] = mgmt;
return 0;
@@ -685,7 +686,8 @@
{
struct mdp_hist_mgmt *temp;
int i, ret;
- mdp_hist_wq = alloc_workqueue("mdp_hist_wq", WQ_UNBOUND, 0);
+ mdp_hist_wq = alloc_workqueue("mdp_hist_wq",
+ WQ_NON_REENTRANT | WQ_UNBOUND, 0);
for (i = 0; i < MDP_HIST_MGMT_MAX; i++)
mdp_hist_mgmt_array[i] = NULL;
@@ -897,6 +899,7 @@
mgmt->frame_cnt = req->frame_cnt;
mgmt->bit_mask = req->bit_mask;
mgmt->num_bins = req->num_bins;
+ mgmt->hist = NULL;
ret = mdp_histogram_enable(mgmt);
@@ -1080,8 +1083,11 @@
goto error;
}
- /* if read was triggered by an underrun, don't wake up readers*/
- if (mgmt->mdp_is_hist_valid && mgmt->mdp_is_hist_init) {
+ /*
+ * if read was triggered by an underrun or failed copying,
+ * don't wake up readers
+ */
+ if (!ret && mgmt->mdp_is_hist_valid && mgmt->mdp_is_hist_init) {
mgmt->hist = NULL;
complete(&mgmt->mdp_hist_comp);
}
@@ -1177,6 +1183,11 @@
goto error_lock;
}
+ if (mgmt->hist != NULL) {
+ pr_err("%s; histogram attempted to be read twice\n", __func__);
+ ret = -EPERM;
+ goto error_lock;
+ }
mgmt->hist = hist;
mutex_unlock(&mgmt->mdp_hist_mutex);
@@ -1740,7 +1751,6 @@
spin_lock_init(&mdp_spin_lock);
mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq");
mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq");
- mdp_hist_wq = create_singlethread_workqueue("mdp_hist_wq");
mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
mdp_pipe_ctrl_workqueue_handler);
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index baad0a8..7564016 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -178,6 +178,17 @@
clk_rate = mfd->fbi->var.pixclock;
clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+ mipi_dsi_phy_ctrl(1);
+
+ if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
+ target_type = mipi_dsi_pdata->target_type;
+
+ mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);
+
+ local_bh_disable();
+ mipi_dsi_clk_enable();
+ local_bh_enable();
+
MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);
@@ -190,17 +201,6 @@
width = mfd->panel_info.xres;
height = mfd->panel_info.yres;
- mipi_dsi_phy_ctrl(1);
-
- if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
- target_type = mipi_dsi_pdata->target_type;
-
- mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);
-
- local_bh_disable();
- mipi_dsi_clk_enable();
- local_bh_enable();
-
mipi = &mfd->panel_info.mipi;
if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
dummy_xres = mfd->panel_info.lcdc.xres_pad;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 6358a0e..1218794 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -2387,6 +2387,7 @@
u32 rc, seqhdr_present = 0;
struct vcd_property_hdr prop_hdr;
struct vcd_sequence_hdr seq_hdr;
+ struct vcd_property_sps_pps_for_idr_enable idr_enable;
struct vcd_property_codec codec;
*handled = true;
prop_hdr.prop_id = DDL_I_SEQHDR_PRESENT;
@@ -2403,29 +2404,64 @@
rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr, &codec);
if (!VCD_FAILED(rc)) {
if (codec.codec != VCD_CODEC_H263) {
- prop_hdr.prop_id = VCD_I_SEQ_HEADER;
- prop_hdr.sz = sizeof(struct vcd_sequence_hdr);
- seq_hdr.sequence_header = frm_entry->virtual;
- seq_hdr.sequence_header_len =
- frm_entry->alloc_len;
- rc = ddl_get_property(cctxt->ddl_handle,
- &prop_hdr, &seq_hdr);
- if (!VCD_FAILED(rc)) {
- frm_entry->data_len =
- seq_hdr.sequence_header_len;
- frm_entry->time_stamp = 0;
- frm_entry->flags |=
- VCD_FRAME_FLAG_CODECCONFIG;
+ /*
+ * The seq. header is stored in a seperate internal
+ * buffer and is memcopied into the output buffer
+ * that we provide. In secure sessions, we aren't
+ * allowed to touch these buffers. In these cases
+ * seq. headers are returned to client as part of
+ * I-frames. So for secure session, just return
+ * empty buffer.
+ */
+ if (!cctxt->secure) {
+ prop_hdr.prop_id = VCD_I_SEQ_HEADER;
+ prop_hdr.sz = sizeof(struct vcd_sequence_hdr);
+ seq_hdr.sequence_header = frm_entry->virtual;
+ seq_hdr.sequence_header_len =
+ frm_entry->alloc_len;
+ rc = ddl_get_property(cctxt->ddl_handle,
+ &prop_hdr, &seq_hdr);
+ if (!VCD_FAILED(rc)) {
+ frm_entry->data_len =
+ seq_hdr.sequence_header_len;
+ frm_entry->time_stamp = 0;
+ frm_entry->flags |=
+ VCD_FRAME_FLAG_CODECCONFIG;
+ } else
+ VCD_MSG_ERROR("rc = 0x%x. Failed:"
+ "ddl_get_property: VCD_I_SEQ_HEADER",
+ rc);
+ } else {
+ /*
+ * First check that the proper props are enabled
+ * so client can get the proper info eventually
+ */
+ prop_hdr.prop_id = VCD_I_ENABLE_SPS_PPS_FOR_IDR;
+ prop_hdr.sz = sizeof(idr_enable);
+ rc = ddl_get_property(cctxt->ddl_handle,
+ &prop_hdr, &idr_enable);
+ if (!VCD_FAILED(rc)) {
+ if (!idr_enable.
+ sps_pps_for_idr_enable_flag) {
+ VCD_MSG_ERROR("SPS/PPS per IDR "
+ "needs to be enabled");
+ rc = VCD_ERR_BAD_STATE;
+ } else {
+ /* Send zero len frame */
+ frm_entry->data_len = 0;
+ frm_entry->time_stamp = 0;
+ frm_entry->flags = 0;
+ }
+ }
+
+ }
+
+ if (!VCD_FAILED(rc))
cctxt->callback(VCD_EVT_RESP_OUTPUT_DONE,
- VCD_S_SUCCESS, frm_entry,
- sizeof(struct vcd_frame_data),
- cctxt,
- cctxt->client_data);
- } else
- VCD_MSG_ERROR(
- "rc = 0x%x. Failed:\
- ddl_get_property: VCD_I_SEQ_HEADER",
- rc);
+ VCD_S_SUCCESS, frm_entry,
+ sizeof(struct vcd_frame_data),
+ cctxt,
+ cctxt->client_data);
} else
VCD_MSG_LOW("Codec Type is H.263\n");
} else
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 18f80ca..cad9907 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -3863,6 +3863,7 @@
tx_slot[0] = tx_ch[cnt];
tx_slot[1] = tx_ch[1 + cnt];
tx_slot[2] = tx_ch[5 + cnt];
+ tx_slot[3] = tx_ch[3 + cnt];
} else if (dai->id == AIF3_CAP) {
*tx_num = tabla_dai[dai->id - 1].capture.channels_max;
tx_slot[cnt] = tx_ch[2 + cnt];
@@ -4580,7 +4581,7 @@
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, 0, 0, &sb_tx4_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX4", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX4", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
0, tabla_codec_enable_slimtx,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
diff --git a/sound/soc/msm/msm-dai-q6-hdmi.c b/sound/soc/msm/msm-dai-q6-hdmi.c
index 3333344..dfb090e 100644
--- a/sound/soc/msm/msm-dai-q6-hdmi.c
+++ b/sound/soc/msm/msm-dai-q6-hdmi.c
@@ -38,6 +38,46 @@
union afe_port_config port_config;
};
+static int msm_dai_q6_hdmi_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+
+ struct msm_dai_q6_hdmi_dai_data *dai_data = kcontrol->private_data;
+ int value = ucontrol->value.integer.value[0];
+ dai_data->port_config.hdmi_multi_ch.data_type = value;
+ pr_debug("%s: value = %d\n", __func__, value);
+ return 0;
+}
+
+static int msm_dai_q6_hdmi_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+
+ struct msm_dai_q6_hdmi_dai_data *dai_data = kcontrol->private_data;
+ ucontrol->value.integer.value[0] =
+ dai_data->port_config.hdmi_multi_ch.data_type;
+ return 0;
+}
+
+
+/* HDMI format field for AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG command
+ * 0: linear PCM
+ * 1: non-linear PCM
+ */
+static const char *hdmi_format[] = {
+ "LPCM",
+ "Compr"
+};
+
+static const struct soc_enum hdmi_config_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, hdmi_format),
+};
+
+static const struct snd_kcontrol_new hdmi_config_controls[] = {
+ SOC_ENUM_EXT("HDMI RX Format", hdmi_config_enum[0],
+ msm_dai_q6_hdmi_format_get,
+ msm_dai_q6_hdmi_format_put),
+};
/* Current implementation assumes hw_param is called once
* This may not be the case but what to do when ADM and AFE
@@ -54,7 +94,6 @@
dai_data->channels = params_channels(params);
dai_data->rate = params_rate(params);
- dai_data->port_config.hdmi_multi_ch.data_type = 0;
dai_data->port_config.hdmi_multi_ch.reserved = 0;
switch (dai_data->channels) {
@@ -78,9 +117,11 @@
return -EINVAL;
}
dev_dbg(dai->dev, "%s() num_ch = %u rate =%u"
- " channel_allocation = %u\n", __func__, dai_data->channels,
+ " channel_allocation = %u data type = %d\n", __func__,
+ dai_data->channels,
dai_data->rate,
- dai_data->port_config.hdmi_multi_ch.channel_allocation);
+ dai_data->port_config.hdmi_multi_ch.channel_allocation,
+ dai_data->port_config.hdmi_multi_ch.data_type);
return 0;
}
@@ -168,6 +209,7 @@
static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai)
{
struct msm_dai_q6_hdmi_dai_data *dai_data;
+ const struct snd_kcontrol_new *kcontrol;
int rc = 0;
dai_data = kzalloc(sizeof(struct msm_dai_q6_hdmi_dai_data),
@@ -180,6 +222,10 @@
} else
dev_set_drvdata(dai->dev, dai_data);
+ kcontrol = &hdmi_config_controls[0];
+
+ rc = snd_ctl_add(dai->card->snd_card,
+ snd_ctl_new1(kcontrol, dai_data));
return rc;
}