Merge "msm: headsmp: Fix section mismatch warning" into msm-3.0
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
new file mode 100644
index 0000000..002431a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
@@ -0,0 +1,24 @@
+Qualcomm LPASS QDSP6v5 Peripheral Image Loader
+
+pil-qdsp6v5-lpass is a peripheral image loader (PIL) driver. It is used for
+loading QDSP6v5 (Hexagon) firmware images for Low Power Audio Subsystems
+into memory and preparing the subsystem's processor to execute code. It's
+also responsible for shutting down the processor when it's not needed.
+
+Required properties:
+- compatible: Must be "qcom,pil-q6v5-lpass"
+- reg: Three pairs of physical base addresses and region sizes
+ of memory mapped registers. The first region corresponds
+ to QDSP6SS_PUB, the second corresponds to LPASS_CC, and
+ the third to LPASS_HALTREQ.
+- qcom,firmware-name: Base name of the firmware image. Ex. "lpass"
+
+Example:
+ qcom,lpass@fe200000 {
+ compatible = "qcom,pil-q6v5-lpass";
+ reg = <0xfe200000 0x00100>,
+ <0xfe000000 0x40000>,
+ <0xfd485100 0x00010>;
+
+ qcom,firmware-name = "lpass";
+ };
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 5a4b08f..4821290 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -243,4 +243,13 @@
interrupts = <0 131 0>;
qcom,dwc-usb3-msm-dbm-eps = <4>;
};
+
+ qcom,lpass@fe200000 {
+ compatible = "qcom,pil-q6v5-lpass";
+ reg = <0xfe200000 0x00100>,
+ <0xfe000000 0x40000>,
+ <0xfd485100 0x00010>;
+
+ qcom,firmware-name = "lpass";
+ };
};
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 1574a54..64451eb 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -42,6 +42,7 @@
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
# CONFIG_MSM_HW3D is not set
+CONFIG_MSM_PIL_LPASS_QDSP6V5=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index a6bbaf4..87296cc 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -69,6 +69,7 @@
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_IOMMU=y
CONFIG_MSM_WATCHDOG=y
CONFIG_MSM_DLOAD_MODE=y
CONFIG_MSM_ETM=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index df49bdc..fd06714 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -68,6 +68,7 @@
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_IOMMU=y
CONFIG_MSM_WATCHDOG=y
CONFIG_MSM_DLOAD_MODE=y
CONFIG_MSM_ETM=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 4ea24a4..ca3e459 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -239,6 +239,7 @@
select MSM_GPIOMUX
select MULTI_IRQ_HANDLER
select MSM_MULTIMEDIA_USE_ION
+ select MSM_PIL
config ARCH_FSM9XXX
bool "FSM9XXX"
@@ -1742,7 +1743,6 @@
config MSM_PIL
bool "Peripheral image loading"
select FW_LOADER
- depends on (ARCH_MSM8X60 || ARCH_MSM8960)
default n
help
Some peripherals need to be loaded into memory before they can be
@@ -1771,6 +1771,13 @@
The QDSP6 is a low power DSP used in audio, modem firmware, and modem
software applications.
+config MSM_PIL_LPASS_QDSP6V5
+ tristate "LPASS QDSP6v5 (Hexagon) Boot Support"
+ depends on MSM_PIL
+ help
+ Support for booting and shutting down QDSP6v5 processors (Hexagon)
+ processors in low power audio subsystems.
+
config MSM_PIL_RIVA
tristate "RIVA (WCNSS) Boot Support"
depends on MSM_PIL
@@ -2190,12 +2197,12 @@
For production builds, you should probably say 'N' here.
config MSM_L1_ERR_PANIC
- bool "Panic on L1 cache / TLB errors"
+ bool "Panic on L1 cache errors"
depends on MSM_CACHE_ERP
help
- To cause the kernel to panic whenever an L1 cache or TLB error is
- detected, say 'Y' here. This may be useful as a debugging technique if
- general system instability is suspected.
+ To cause the kernel to panic whenever an L1 cache error is detected, say
+ 'Y' here. This may be useful as a debugging technique if general system
+ instability is suspected.
For production builds, you should probably say 'N' here.
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1bd91a8..84af813 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -67,6 +67,7 @@
obj-$(CONFIG_MSM_PIL) += scm-pas.o
obj-$(CONFIG_MSM_PIL_QDSP6V3) += pil-q6v3.o
obj-$(CONFIG_MSM_PIL_QDSP6V4) += pil-q6v4.o
+obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V5) += pil-q6v5.o pil-q6v5-lpass.o
obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
obj-$(CONFIG_MSM_PIL_VIDC) += pil-vidc.o
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d33a71f..5b0b9c3 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -77,6 +77,7 @@
#include "pm.h"
#include "pm-boot.h"
#include "devices-msm8x60.h"
+#include "smd_private.h"
#define MSM_PMEM_ADSP_SIZE 0x7800000
#define MSM_PMEM_AUDIO_SIZE 0x4CF000
@@ -442,6 +443,12 @@
apq8064_reserve_info.bank_size);
}
+static int apq8064_change_memory_power(u64 start, u64 size,
+ int change_type)
+{
+ return soc_change_memory_power(start, size, change_type);
+}
+
static char prim_panel_name[PANEL_NAME_MAX_LEN];
static char ext_panel_name[PANEL_NAME_MAX_LEN];
static int __init prim_display_setup(char *param)
@@ -1971,6 +1978,7 @@
&apq_cpudai_slim_4_rx,
&apq_cpudai_slim_4_tx,
&msm8960_gemini_device,
+ &apq8064_iommu_domain_device,
};
static struct platform_device *sim_devices[] __initdata = {
@@ -2576,6 +2584,8 @@
static void __init apq8064_cdp_init(void)
{
+ if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
+ pr_err("meminfo_init() failed!\n");
apq8064_common_init();
if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
machine_is_mpq8064_dtv()) {
@@ -2597,6 +2607,8 @@
if (machine_is_apq8064_mtp())
platform_device_register(&mtp_kp_pdev);
+
+ change_memory_power = &apq8064_change_memory_power;
}
MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 4327fd9..24e6a79 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1791,6 +1791,7 @@
&msm_bus_8930_sys_fpb,
&msm_bus_8930_cpss_fpb,
&msm8960_device_cache_erp,
+ &msm8930_iommu_domain_device,
};
static struct platform_device *cdp_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 45ebcaa..6328ab3 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2495,9 +2495,7 @@
}
static struct msm_serial_hs_platform_data msm_uart_dm9_pdata = {
- .inject_rx_on_wakeup = 1,
- .rx_to_inject = 0xFD,
- .gpio_config = configure_uart_gpios,
+ .gpio_config = configure_uart_gpios,
};
#else
static struct msm_serial_hs_platform_data msm_uart_dm9_pdata;
@@ -2589,6 +2587,7 @@
#ifdef CONFIG_MSM_CACHE_DUMP
&msm_cache_dump_device,
#endif
+ &msm8960_iommu_domain_device,
};
static struct platform_device *sim_devices[] __initdata = {
@@ -3155,8 +3154,10 @@
platform_device_register(&msm8960_device_uart_gsbi5);
/* For 8960 Fusion 2.2 Primary IPC */
- if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+ if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
+ msm_uart_dm9_pdata.wakeup_irq = gpio_to_irq(94); /* GSBI9(2) */
msm_device_uart_dm9.dev.platform_data = &msm_uart_dm9_pdata;
+ }
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm8960_pm8921_gpio_mpp_init();
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index d81ad92..ccfc770 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -456,6 +456,8 @@
"msm_sdcc.1", NULL),
OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF984B000, \
"msm_sdcc.3", NULL),
+ OF_DEV_AUXDATA("qcom,pil-q6v5-lpass", 0xFE200000, \
+ "pil-q6v5-lpass", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index af3d187..2a703f0 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -581,83 +581,83 @@
int i = 0;
int remainder;
/* device address byte = 0x72 */
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(67);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(33);
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(33);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(67);
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(33);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(67);
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(33);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(67);
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(67);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(33);
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(67);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(33);
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(33);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(67);
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(67);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(33);
/* t-EOS and t-start */
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
ndelay(4200);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
ndelay(9000);
/* data byte */
/* RFA = 0 */
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(67);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(33);
/* Address bits */
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(67);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(33);
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(67);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(33);
/* Data bits */
for (i = 0; i < 5; i++) {
remainder = (level) & (16);
if (remainder) {
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(33);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(67);
} else {
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
udelay(67);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
udelay(33);
}
level = level << 1;
}
/* t-EOS */
- gpio_set_value_cansleep(96, 0);
+ gpio_set_value(96, 0);
ndelay(12000);
- gpio_set_value_cansleep(96, 1);
+ gpio_set_value(96, 1);
return 0;
}
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index f1960ce..2ed5897 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -567,8 +567,8 @@
(DEC4_FORMAT),
/* Concurrency 6 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
0, 0, 0,
/* Concurrency 7 */
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 510ce6b..86bf205 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -510,8 +510,8 @@
(DEC4_FORMAT),
/* Concurrency 6 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
0, 0, 0,
/* Concurrency 7 */
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index 9a721e4..97225ac 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -17,7 +17,11 @@
#include <linux/errno.h>
#include <linux/proc_fs.h>
#include <linux/cpu.h>
+#include <linux/io.h>
#include <mach/msm-krait-l2-accessors.h>
+#include <mach/msm_iomap.h>
+#include <asm/cputype.h>
+#include "acpuclock.h"
#define CESR_DCTPE BIT(0)
#define CESR_DCDPE BIT(1)
@@ -193,11 +197,25 @@
struct msm_l1_err_stats *l1_stats = dev_id;
unsigned int cesr = read_cesr();
unsigned int i_cesynr, d_cesynr;
+ unsigned int cpu = smp_processor_id();
int print_regs = cesr & CESR_PRINT_MASK;
+ void *const saw_bases[] = {
+ MSM_SAW0_BASE,
+ MSM_SAW1_BASE,
+ MSM_SAW2_BASE,
+ MSM_SAW3_BASE,
+ };
+
if (print_regs) {
- pr_alert("L1 Error detected on CPU %d!\n", smp_processor_id());
- pr_alert("\tCESR = 0x%08x\n", cesr);
+ pr_alert("L1 / TLB Error detected on CPU %d!\n", cpu);
+ pr_alert("\tCESR = 0x%08x\n", cesr);
+ pr_alert("\tCPU speed = %lu\n", acpuclk_get_rate(cpu));
+ pr_alert("\tMIDR = 0x%08x\n", read_cpuid_id());
+ pr_alert("\tPTE fuses = 0x%08x\n",
+ readl_relaxed(MSM_QFPROM_BASE + 0xC0));
+ pr_alert("\tPMIC_VREG = 0x%08x\n",
+ readl_relaxed(saw_bases[cpu] + 0x14));
}
if (cesr & CESR_DCTPE) {
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 39eddfa..aaa5bfb 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -40,6 +40,7 @@
#include "rpm_stats.h"
#include "rpm_log.h"
#include <mach/mpm.h>
+#include <mach/iommu_domains.h>
/* Address of GSBI blocks */
#define MSM_GSBI1_PHYS 0x12440000
@@ -2249,3 +2250,161 @@
.num_resources = ARRAY_SIZE(msm_etm_resources),
.resource = msm_etm_resources,
};
+
+struct msm_iommu_domain_name apq8064_iommu_ctx_names[] = {
+ /* Camera */
+ {
+ .name = "vpe_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vpe_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_imgwr",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_misc",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_src",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_dst",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_mm1",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_b_mm2",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_stream",
+ .domain = VIDEO_DOMAIN,
+ },
+};
+
+static struct mem_pool apq8064_video_pools[] = {
+ /*
+ * Video hardware has the following requirements:
+ * 1. All video addresses used by the video hardware must be at a higher
+ * address than video firmware address.
+ * 2. Video hardware can only access a range of 256MB from the base of
+ * the video firmware.
+ */
+ [VIDEO_FIRMWARE_POOL] =
+ /* Low addresses, intended for video firmware */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_16M - SZ_128K,
+ },
+ [VIDEO_MAIN_POOL] =
+ /* Main video pool */
+ {
+ .paddr = SZ_16M,
+ .size = SZ_256M - SZ_16M,
+ },
+ [GEN_POOL] =
+ /* Remaining address space up to 2G */
+ {
+ .paddr = SZ_256M,
+ .size = SZ_2G - SZ_256M,
+ },
+};
+
+static struct mem_pool apq8064_camera_pools[] = {
+ [GEN_POOL] =
+ /* One address space for camera */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool apq8064_display_pools[] = {
+ [GEN_POOL] =
+ /* One address space for display */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool apq8064_rotator_pools[] = {
+ [GEN_POOL] =
+ /* One address space for rotator */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct msm_iommu_domain apq8064_iommu_domains[] = {
+ [VIDEO_DOMAIN] = {
+ .iova_pools = apq8064_video_pools,
+ .npools = ARRAY_SIZE(apq8064_video_pools),
+ },
+ [CAMERA_DOMAIN] = {
+ .iova_pools = apq8064_camera_pools,
+ .npools = ARRAY_SIZE(apq8064_camera_pools),
+ },
+ [DISPLAY_DOMAIN] = {
+ .iova_pools = apq8064_display_pools,
+ .npools = ARRAY_SIZE(apq8064_display_pools),
+ },
+ [ROTATOR_DOMAIN] = {
+ .iova_pools = apq8064_rotator_pools,
+ .npools = ARRAY_SIZE(apq8064_rotator_pools),
+ },
+};
+
+struct iommu_domains_pdata apq8064_iommu_domain_pdata = {
+ .domains = apq8064_iommu_domains,
+ .ndomains = ARRAY_SIZE(apq8064_iommu_domains),
+ .domain_names = apq8064_iommu_ctx_names,
+ .nnames = ARRAY_SIZE(apq8064_iommu_ctx_names),
+ .domain_alloc_flags = 0,
+};
+
+struct platform_device apq8064_iommu_domain_device = {
+ .name = "iommu_domains",
+ .id = -1,
+ .dev = {
+ .platform_data = &apq8064_iommu_domain_pdata,
+ },
+};
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 85e927e..b7048db 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -22,6 +22,7 @@
#include <mach/msm_bus_board.h>
#include <mach/board.h>
#include <mach/socinfo.h>
+#include <mach/iommu_domains.h>
#include "devices.h"
#include "rpm_log.h"
@@ -628,3 +629,161 @@
}
platform_add_devices(vidc_device, ARRAY_SIZE(vidc_device));
}
+
+struct msm_iommu_domain_name msm8930_iommu_ctx_names[] = {
+ /* Camera */
+ {
+ .name = "vpe_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vpe_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_imgwr",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_misc",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_src",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_dst",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_mm1",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_b_mm2",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_stream",
+ .domain = VIDEO_DOMAIN,
+ },
+};
+
+static struct mem_pool msm8930_video_pools[] = {
+ /*
+ * Video hardware has the following requirements:
+ * 1. All video addresses used by the video hardware must be at a higher
+ * address than video firmware address.
+ * 2. Video hardware can only access a range of 256MB from the base of
+ * the video firmware.
+ */
+ [VIDEO_FIRMWARE_POOL] =
+ /* Low addresses, intended for video firmware */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_16M - SZ_128K,
+ },
+ [VIDEO_MAIN_POOL] =
+ /* Main video pool */
+ {
+ .paddr = SZ_16M,
+ .size = SZ_256M - SZ_16M,
+ },
+ [GEN_POOL] =
+ /* Remaining address space up to 2G */
+ {
+ .paddr = SZ_256M,
+ .size = SZ_2G - SZ_256M,
+ },
+};
+
+static struct mem_pool msm8930_camera_pools[] = {
+ [GEN_POOL] =
+ /* One address space for camera */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool msm8930_display_pools[] = {
+ [GEN_POOL] =
+ /* One address space for display */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool msm8930_rotator_pools[] = {
+ [GEN_POOL] =
+ /* One address space for rotator */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct msm_iommu_domain msm8930_iommu_domains[] = {
+ [VIDEO_DOMAIN] = {
+ .iova_pools = msm8930_video_pools,
+ .npools = ARRAY_SIZE(msm8930_video_pools),
+ },
+ [CAMERA_DOMAIN] = {
+ .iova_pools = msm8930_camera_pools,
+ .npools = ARRAY_SIZE(msm8930_camera_pools),
+ },
+ [DISPLAY_DOMAIN] = {
+ .iova_pools = msm8930_display_pools,
+ .npools = ARRAY_SIZE(msm8930_display_pools),
+ },
+ [ROTATOR_DOMAIN] = {
+ .iova_pools = msm8930_rotator_pools,
+ .npools = ARRAY_SIZE(msm8930_rotator_pools),
+ },
+};
+
+struct iommu_domains_pdata msm8930_iommu_domain_pdata = {
+ .domains = msm8930_iommu_domains,
+ .ndomains = ARRAY_SIZE(msm8930_iommu_domains),
+ .domain_names = msm8930_iommu_ctx_names,
+ .nnames = ARRAY_SIZE(msm8930_iommu_ctx_names),
+ .domain_alloc_flags = 0,
+};
+
+struct platform_device msm8930_iommu_domain_device = {
+ .name = "iommu_domains",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm8930_iommu_domain_pdata,
+ },
+};
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 894c13f..8df1d7a 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -47,6 +47,7 @@
#include "pil-q6v4.h"
#include "scm-pas.h"
#include <mach/msm_dcvs.h>
+#include <mach/iommu_domains.h>
#ifdef CONFIG_MSM_MPM
#include <mach/mpm.h>
@@ -3343,3 +3344,161 @@
.num_resources = ARRAY_SIZE(msm_cache_erp_resources),
.resource = msm_cache_erp_resources,
};
+
+struct msm_iommu_domain_name msm8960_iommu_ctx_names[] = {
+ /* Camera */
+ {
+ .name = "vpe_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vpe_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_imgwr",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "vfe_misc",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "ijpeg_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_src",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Camera */
+ {
+ .name = "jpegd_dst",
+ .domain = CAMERA_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_src",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Rotator */
+ {
+ .name = "rot_dst",
+ .domain = ROTATOR_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_mm1",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_b_mm2",
+ .domain = VIDEO_DOMAIN,
+ },
+ /* Video */
+ {
+ .name = "vcodec_a_stream",
+ .domain = VIDEO_DOMAIN,
+ },
+};
+
+static struct mem_pool msm8960_video_pools[] = {
+ /*
+ * Video hardware has the following requirements:
+ * 1. All video addresses used by the video hardware must be at a higher
+ * address than video firmware address.
+ * 2. Video hardware can only access a range of 256MB from the base of
+ * the video firmware.
+ */
+ [VIDEO_FIRMWARE_POOL] =
+ /* Low addresses, intended for video firmware */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_16M - SZ_128K,
+ },
+ [VIDEO_MAIN_POOL] =
+ /* Main video pool */
+ {
+ .paddr = SZ_16M,
+ .size = SZ_256M - SZ_16M,
+ },
+ [GEN_POOL] =
+ /* Remaining address space up to 2G */
+ {
+ .paddr = SZ_256M,
+ .size = SZ_2G - SZ_256M,
+ },
+};
+
+static struct mem_pool msm8960_camera_pools[] = {
+ [GEN_POOL] =
+ /* One address space for camera */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool msm8960_display_pools[] = {
+ [GEN_POOL] =
+ /* One address space for display */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct mem_pool msm8960_rotator_pools[] = {
+ [GEN_POOL] =
+ /* One address space for rotator */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ },
+};
+
+static struct msm_iommu_domain msm8960_iommu_domains[] = {
+ [VIDEO_DOMAIN] = {
+ .iova_pools = msm8960_video_pools,
+ .npools = ARRAY_SIZE(msm8960_video_pools),
+ },
+ [CAMERA_DOMAIN] = {
+ .iova_pools = msm8960_camera_pools,
+ .npools = ARRAY_SIZE(msm8960_camera_pools),
+ },
+ [DISPLAY_DOMAIN] = {
+ .iova_pools = msm8960_display_pools,
+ .npools = ARRAY_SIZE(msm8960_display_pools),
+ },
+ [ROTATOR_DOMAIN] = {
+ .iova_pools = msm8960_rotator_pools,
+ .npools = ARRAY_SIZE(msm8960_rotator_pools),
+ },
+};
+
+struct iommu_domains_pdata msm8960_iommu_domain_pdata = {
+ .domains = msm8960_iommu_domains,
+ .ndomains = ARRAY_SIZE(msm8960_iommu_domains),
+ .domain_names = msm8960_iommu_ctx_names,
+ .nnames = ARRAY_SIZE(msm8960_iommu_ctx_names),
+ .domain_alloc_flags = 0,
+};
+
+struct platform_device msm8960_iommu_domain_device = {
+ .name = "iommu_domains",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm8960_iommu_domain_pdata,
+ },
+};
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 29e8180..9a03afd 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -376,11 +376,13 @@
static struct msm_iommu_dev gfx2d0_iommu = {
.name = "gfx2d0",
.ncb = 2,
+ .ttbr_split = 2,
};
static struct msm_iommu_dev gfx2d1_iommu = {
.name = "gfx2d1",
.ncb = 2,
+ .ttbr_split = 2,
};
static struct msm_iommu_dev vcap_iommu = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 9e3ac63..5718fe0 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -373,5 +373,8 @@
extern struct platform_device msm_device_csic1;
extern struct platform_device msm_device_vfe;
extern struct platform_device msm_device_vpe;
-
extern struct platform_device mpq8064_device_qup_i2c_gsbi5;
+
+extern struct platform_device msm8960_iommu_domain_device;
+extern struct platform_device msm8930_iommu_domain_device;
+extern struct platform_device apq8064_iommu_domain_device;
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 74e1115..52e70ec 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -13,6 +13,8 @@
#ifndef _ARCH_IOMMU_DOMAINS_H
#define _ARCH_IOMMU_DOMAINS_H
+#include <linux/memory_alloc.h>
+
enum {
VIDEO_DOMAIN,
CAMERA_DOMAIN,
@@ -27,6 +29,32 @@
GEN_POOL,
};
+struct msm_iommu_domain_name {
+ char *name;
+ int domain;
+};
+
+struct msm_iommu_domain {
+ /* iommu domain to map in */
+ struct iommu_domain *domain;
+ /* total number of allocations from this domain */
+ atomic_t allocation_cnt;
+ /* number of iova pools */
+ int npools;
+ /*
+ * array of gen_pools for allocating iovas.
+ * behavior is undefined if these overlap
+ */
+ struct mem_pool *iova_pools;
+};
+
+struct iommu_domains_pdata {
+ struct msm_iommu_domain *domains;
+ int ndomains;
+ struct msm_iommu_domain_name *domain_names;
+ int nnames;
+ unsigned int domain_alloc_flags;
+};
#if defined(CONFIG_MSM_IOMMU)
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index dbc1389..8f4af3b 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -13,6 +13,7 @@
#include <mach/msm_subsystem_map.h>
#include <linux/memory_alloc.h>
#include <linux/iommu.h>
+#include <linux/platform_device.h>
#include <linux/vmalloc.h>
#include <asm/sizes.h>
#include <asm/page.h>
@@ -24,166 +25,12 @@
/* dummy 4k for overmapping */
char iommu_dummy[2*PAGE_SIZE-4];
-struct msm_iommu_domain {
- /* iommu domain to map in */
- struct iommu_domain *domain;
- /* total number of allocations from this domain */
- atomic_t allocation_cnt;
- /* number of iova pools */
- int npools;
- /*
- * array of gen_pools for allocating iovas.
- * behavior is undefined if these overlap
- */
- struct mem_pool *iova_pools;
-
+struct msm_iommu_domain_state {
+ struct msm_iommu_domain *domains;
+ int ndomains;
};
-
-struct {
- char *name;
- int domain;
-} msm_iommu_ctx_names[] = {
- /* Camera */
- {
- .name = "vpe_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "ijpeg_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "ijpeg_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "jpegd_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "jpegd_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Rotator */
- {
- .name = "rot_src",
- .domain = ROTATOR_DOMAIN,
- },
- /* Rotator */
- {
- .name = "rot_dst",
- .domain = ROTATOR_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_a_mm1",
- .domain = VIDEO_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_b_mm2",
- .domain = VIDEO_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_a_stream",
- .domain = VIDEO_DOMAIN,
- },
-};
-
-static struct mem_pool video_pools[] = {
- /*
- * Video hardware has the following requirements:
- * 1. All video addresses used by the video hardware must be at a higher
- * address than video firmware address.
- * 2. Video hardware can only access a range of 256MB from the base of
- * the video firmware.
- */
- [VIDEO_FIRMWARE_POOL] =
- /* Low addresses, intended for video firmware */
- {
- .paddr = SZ_128K,
- .size = SZ_16M - SZ_128K,
- },
- [VIDEO_MAIN_POOL] =
- /* Main video pool */
- {
- .paddr = SZ_16M,
- .size = SZ_256M - SZ_16M,
- },
- [GEN_POOL] =
- /* Remaining address space up to 2G */
- {
- .paddr = SZ_256M,
- .size = SZ_2G - SZ_256M,
- },
-};
-
-static struct mem_pool camera_pools[] = {
- [GEN_POOL] =
- /* One address space for camera */
- {
- .paddr = SZ_128K,
- .size = SZ_2G - SZ_128K,
- },
-};
-
-static struct mem_pool display_pools[] = {
- [GEN_POOL] =
- /* One address space for display */
- {
- .paddr = SZ_128K,
- .size = SZ_2G - SZ_128K,
- },
-};
-
-static struct mem_pool rotator_pools[] = {
- [GEN_POOL] =
- /* One address space for rotator */
- {
- .paddr = SZ_128K,
- .size = SZ_2G - SZ_128K,
- },
-};
-
-static struct msm_iommu_domain msm_iommu_domains[] = {
- [VIDEO_DOMAIN] = {
- .iova_pools = video_pools,
- .npools = ARRAY_SIZE(video_pools),
- },
- [CAMERA_DOMAIN] = {
- .iova_pools = camera_pools,
- .npools = ARRAY_SIZE(camera_pools),
- },
- [DISPLAY_DOMAIN] = {
- .iova_pools = display_pools,
- .npools = ARRAY_SIZE(display_pools),
- },
- [ROTATOR_DOMAIN] = {
- .iova_pools = rotator_pools,
- .npools = ARRAY_SIZE(rotator_pools),
- },
-};
+static struct msm_iommu_domain_state domain_state;
int msm_iommu_map_extra(struct iommu_domain *domain,
unsigned long start_iova,
@@ -221,8 +68,8 @@
struct iommu_domain *msm_get_iommu_domain(int domain_num)
{
- if (domain_num >= 0 && domain_num < MAX_DOMAINS)
- return msm_iommu_domains[domain_num].domain;
+ if (domain_num >= 0 && domain_num < domain_state.ndomains)
+ return domain_state.domains[domain_num].domain;
else
return NULL;
}
@@ -235,13 +82,13 @@
struct mem_pool *pool;
unsigned long iova;
- if (iommu_domain >= MAX_DOMAINS)
+ if (iommu_domain >= domain_state.ndomains)
return 0;
- if (partition_no >= msm_iommu_domains[iommu_domain].npools)
+ if (partition_no >= domain_state.domains[iommu_domain].npools)
return 0;
- pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+ pool = &domain_state.domains[iommu_domain].iova_pools[partition_no];
if (!pool->gpool)
return 0;
@@ -260,18 +107,18 @@
{
struct mem_pool *pool;
- if (iommu_domain >= MAX_DOMAINS) {
+ if (iommu_domain >= domain_state.ndomains) {
WARN(1, "Invalid domain %d\n", iommu_domain);
return;
}
- if (partition_no >= msm_iommu_domains[iommu_domain].npools) {
+ if (partition_no >= domain_state.domains[iommu_domain].npools) {
WARN(1, "Invalid partition %d for domain %d\n",
partition_no, iommu_domain);
return;
}
- pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+ pool = &domain_state.domains[iommu_domain].iova_pools[partition_no];
if (!pool)
return;
@@ -282,20 +129,31 @@
int msm_use_iommu()
{
- return iommu_found();
+ /*
+ * If there are no domains, don't bother trying to use the iommu
+ */
+ return domain_state.ndomains && iommu_found();
}
-static int __init msm_subsystem_iommu_init(void)
+static int __init iommu_domain_probe(struct platform_device *pdev)
{
+ struct iommu_domains_pdata *p = pdev->dev.platform_data;
int i, j;
- for (i = 0; i < ARRAY_SIZE(msm_iommu_domains); i++) {
- msm_iommu_domains[i].domain = iommu_domain_alloc(0);
- if (!msm_iommu_domains[i].domain)
+ if (!p)
+ return -ENODEV;
+
+ domain_state.domains = p->domains;
+ domain_state.ndomains = p->ndomains;
+
+ for (i = 0; i < domain_state.ndomains; i++) {
+ domain_state.domains[i].domain = iommu_domain_alloc(
+ p->domain_alloc_flags);
+ if (!domain_state.domains[i].domain)
continue;
- for (j = 0; j < msm_iommu_domains[i].npools; j++) {
- struct mem_pool *pool = &msm_iommu_domains[i].
+ for (j = 0; j < domain_state.domains[i].npools; j++) {
+ struct mem_pool *pool = &domain_state.domains[i].
iova_pools[j];
mutex_init(&pool->pool_mutex);
if (pool->size) {
@@ -325,29 +183,41 @@
}
}
- for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_names); i++) {
+ for (i = 0; i < p->nnames; i++) {
int domain_idx;
struct device *ctx = msm_iommu_get_ctx(
- msm_iommu_ctx_names[i].name);
+ p->domain_names[i].name);
if (!ctx)
continue;
- domain_idx = msm_iommu_ctx_names[i].domain;
+ domain_idx = p->domain_names[i].domain;
- if (!msm_iommu_domains[domain_idx].domain)
+ if (!domain_state.domains[domain_idx].domain)
continue;
- if (iommu_attach_device(msm_iommu_domains[domain_idx].domain,
+ if (iommu_attach_device(domain_state.domains[domain_idx].domain,
ctx)) {
WARN(1, "%s: could not attach domain %d to context %s."
" iommu programming will not occur.\n",
__func__, domain_idx,
- msm_iommu_ctx_names[i].name);
+ p->domain_names[i].name);
continue;
}
}
return 0;
}
+
+static struct platform_driver iommu_domain_driver = {
+ .driver = {
+ .name = "iommu_domains",
+ .owner = THIS_MODULE
+ },
+};
+
+static int __init msm_subsystem_iommu_init(void)
+{
+ return platform_driver_probe(&iommu_domain_driver, iommu_domain_probe);
+}
device_initcall(msm_subsystem_iommu_init);
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
new file mode 100644
index 0000000..60ae4d9
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/err.h>
+#include <linux/of.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v5.h"
+
+/* Register Offsets */
+#define QDSP6SS_RST_EVB 0x010
+#define LPASS_Q6SS_BCR 0x06000
+#define LPASS_Q6SS_AHB_LFABIF_CBCR 0x22000
+#define LPASS_Q6SS_XO_CBCR 0x26000
+#define AXI_HALTREQ 0x0
+#define AXI_HALTACK 0x4
+#define AXI_IDLE 0x8
+
+#define HALT_ACK_TIMEOUT_US 100000
+
+static void clk_reg_enable(void __iomem *reg)
+{
+ u32 val;
+ val = readl_relaxed(reg);
+ val |= BIT(0);
+ writel_relaxed(val, reg);
+}
+
+static void clk_reg_disable(void __iomem *reg)
+{
+ u32 val;
+ val = readl_relaxed(reg);
+ val &= ~BIT(0);
+ writel_relaxed(val, reg);
+}
+
+static int pil_lpass_shutdown(struct pil_desc *pil)
+{
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+ int ret;
+ u32 status;
+
+ writel_relaxed(1, drv->axi_halt_base + AXI_HALTREQ);
+ ret = readl_poll_timeout(drv->axi_halt_base + AXI_HALTACK,
+ status, status, 50, HALT_ACK_TIMEOUT_US);
+ if (ret)
+ dev_err(pil->dev, "Port halt timeout\n");
+ else if (!readl_relaxed(drv->axi_halt_base + AXI_IDLE))
+ dev_err(pil->dev, "Port halt failed\n");
+ writel_relaxed(0, drv->axi_halt_base + AXI_HALTREQ);
+
+ /* Make sure Q6 registers are accessible */
+ writel_relaxed(0, drv->clk_base + LPASS_Q6SS_BCR);
+ clk_reg_enable(drv->clk_base + LPASS_Q6SS_AHB_LFABIF_CBCR);
+ mb();
+
+ pil_q6v5_shutdown(pil);
+
+ /* Disable clocks and assert subsystem resets. */
+ clk_reg_disable(drv->clk_base + LPASS_Q6SS_AHB_LFABIF_CBCR);
+ clk_reg_disable(drv->clk_base + LPASS_Q6SS_XO_CBCR);
+ writel_relaxed(1, drv->clk_base + LPASS_Q6SS_BCR);
+
+ return 0;
+}
+
+static int pil_lpass_reset(struct pil_desc *pil)
+{
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+
+ /*
+ * Bring subsystem out of reset and enable required
+ * regulators and clocks.
+ */
+ writel_relaxed(0, drv->clk_base + LPASS_Q6SS_BCR);
+ clk_reg_enable(drv->clk_base + LPASS_Q6SS_XO_CBCR);
+ clk_reg_enable(drv->clk_base + LPASS_Q6SS_AHB_LFABIF_CBCR);
+ mb();
+
+ /* Program Image Address */
+ writel_relaxed(((drv->start_addr >> 4) & 0x0FFFFFF0),
+ drv->reg_base + QDSP6SS_RST_EVB);
+
+ return pil_q6v5_reset(pil);
+}
+
+static struct pil_reset_ops pil_lpass_ops = {
+ .init_image = pil_q6v5_init_image,
+ .proxy_vote = pil_q6v5_make_proxy_votes,
+ .proxy_unvote = pil_q6v5_remove_proxy_votes,
+ .auth_and_reset = pil_lpass_reset,
+ .shutdown = pil_lpass_shutdown,
+};
+
+static int __devinit pil_lpass_driver_probe(struct platform_device *pdev)
+{
+ struct q6v5_data *drv;
+ struct pil_desc *desc;
+ struct resource *res;
+
+ desc = pil_q6v5_init(pdev);
+ drv = platform_get_drvdata(pdev);
+
+ desc->ops = &pil_lpass_ops;
+ desc->owner = THIS_MODULE;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ drv->axi_halt_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->axi_halt_base)
+ return -ENOMEM;
+
+ drv->pil = msm_pil_register(desc);
+ if (IS_ERR(drv->pil))
+ return PTR_ERR(drv->pil);
+
+ return 0;
+}
+
+static int __devexit pil_lpass_driver_exit(struct platform_device *pdev)
+{
+ struct q6v5_data *drv = platform_get_drvdata(pdev);
+ msm_pil_unregister(drv->pil);
+ return 0;
+}
+
+static struct of_device_id lpass_match_table[] = {
+ { .compatible = "qcom,pil-q6v5-lpass" },
+ {}
+};
+
+static struct platform_driver pil_lpass_driver = {
+ .probe = pil_lpass_driver_probe,
+ .remove = __devexit_p(pil_lpass_driver_exit),
+ .driver = {
+ .name = "pil-q6v5-lpass",
+ .of_match_table = lpass_match_table,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pil_lpass_init(void)
+{
+ return platform_driver_register(&pil_lpass_driver);
+}
+module_init(pil_lpass_init);
+
+static void __exit pil_lpass_exit(void)
+{
+ platform_driver_unregister(&pil_lpass_driver);
+}
+module_exit(pil_lpass_exit);
+
+MODULE_DESCRIPTION("Support for booting low-power audio subsystems with QDSP6v5 (Hexagon) processors");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index 23471d1..b17d4e7 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -22,6 +22,7 @@
struct q6v5_data {
void __iomem *reg_base;
void __iomem *clk_base;
+ void __iomem *axi_halt_base;
void __iomem *rmb_base;
unsigned long start_addr;
struct regulator *vreg;
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 430a4c0..abcd336 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -287,7 +287,6 @@
int bytes_read;
int pkt_size;
struct smd_pkt_dev *smd_pkt_devp;
- struct smd_channel *chl;
unsigned long flags;
smd_pkt_devp = file->private_data;
@@ -312,20 +311,30 @@
D_READ("Begin %s on smd_pkt_dev id:%d buffer_size %d\n",
__func__, smd_pkt_devp->i, count);
- chl = smd_pkt_devp->ch;
wait_for_packet:
r = wait_event_interruptible(smd_pkt_devp->ch_read_wait_queue,
- (smd_cur_packet_size(chl) > 0 &&
- smd_read_avail(chl)) ||
+ !smd_pkt_devp->ch ||
+ (smd_cur_packet_size(smd_pkt_devp->ch) > 0
+ && smd_read_avail(smd_pkt_devp->ch)) ||
smd_pkt_devp->has_reset);
+ mutex_lock(&smd_pkt_devp->rx_lock);
if (smd_pkt_devp->has_reset) {
+ mutex_unlock(&smd_pkt_devp->rx_lock);
pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
__func__, smd_pkt_devp->i);
return notify_reset(smd_pkt_devp);
}
+ if (!smd_pkt_devp->ch) {
+ mutex_unlock(&smd_pkt_devp->rx_lock);
+ pr_err("%s on a closed smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
+ return -EINVAL;
+ }
+
if (r < 0) {
+ mutex_unlock(&smd_pkt_devp->rx_lock);
/* qualify error message */
if (r != -ERESTARTSYS) {
/* we get this anytime a signal comes in */
@@ -337,8 +346,6 @@
}
/* Here we have a whole packet waiting for us */
-
- mutex_lock(&smd_pkt_devp->rx_lock);
pkt_size = smd_cur_packet_size(smd_pkt_devp->ch);
if (!pkt_size) {
@@ -429,7 +436,7 @@
return -EINVAL;
}
- if (smd_pkt_devp->do_reset_notification) {
+ if (smd_pkt_devp->do_reset_notification || smd_pkt_devp->has_reset) {
pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
__func__, smd_pkt_devp->i);
/* notify client that a reset occurred */
@@ -485,6 +492,9 @@
__func__, smd_pkt_devp->i);
return notify_reset(smd_pkt_devp);
}
+ pr_err("%s on smd_pkt_dev id:%d failed r:%d\n",
+ __func__, smd_pkt_devp->i, r);
+ return r;
}
bytes_written += r;
}
@@ -512,11 +522,20 @@
smd_pkt_devp->poll_mode = 1;
poll_wait(file, &smd_pkt_devp->ch_read_wait_queue, wait);
+ mutex_lock(&smd_pkt_devp->ch_lock);
+ if (smd_pkt_devp->has_reset || !smd_pkt_devp->ch) {
+ mutex_unlock(&smd_pkt_devp->ch_lock);
+ pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
+ return POLLERR;
+ }
+
if (smd_read_avail(smd_pkt_devp->ch)) {
mask |= POLLIN | POLLRDNORM;
D_POLL("%s sets POLLIN for smd_pkt_dev id: %d\n",
__func__, smd_pkt_devp->i);
}
+ mutex_unlock(&smd_pkt_devp->ch_lock);
return mask;
}
@@ -814,8 +833,12 @@
r = wait_event_interruptible_timeout(
smd_pkt_devp->ch_opened_wait_queue,
smd_pkt_devp->is_open, (2 * HZ));
- if (r == 0)
+ if (r == 0) {
r = -ETIMEDOUT;
+ /* close the ch to sync smd's state with smd_pkt */
+ smd_close(smd_pkt_devp->ch);
+ smd_pkt_devp->ch = NULL;
+ }
if (r < 0) {
pr_err("%s: wait on smd_pkt_dev id:%d OPEN event failed"
@@ -864,6 +887,8 @@
clean_and_signal(smd_pkt_devp);
mutex_lock(&smd_pkt_devp->ch_lock);
+ mutex_lock(&smd_pkt_devp->rx_lock);
+ mutex_lock(&smd_pkt_devp->tx_lock);
if (smd_pkt_devp->ch != 0) {
r = smd_close(smd_pkt_devp->ch);
smd_pkt_devp->ch = 0;
@@ -873,6 +898,8 @@
if (smd_pkt_devp->pil)
pil_put(smd_pkt_devp->pil);
}
+ mutex_unlock(&smd_pkt_devp->tx_lock);
+ mutex_unlock(&smd_pkt_devp->rx_lock);
mutex_unlock(&smd_pkt_devp->ch_lock);
smd_pkt_devp->has_reset = 0;
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index f6d3cad..a992059 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -857,7 +857,7 @@
*cmds++ = cp_nop_packet(1);
*cmds++ = KGSL_END_OF_IB_IDENTIFIER;
- kgsl_setstate(device,
+ kgsl_setstate(&device->mmu,
kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
device->id));
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 65bcb09..1d80a30 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -397,15 +397,15 @@
return baseptr[pte] & GSL_PT_PAGE_ADDR_MASK;
}
-static void kgsl_gpummu_pagefault(struct kgsl_device *device)
+static void kgsl_gpummu_pagefault(struct kgsl_mmu *mmu)
{
unsigned int reg;
unsigned int ptbase;
- kgsl_regread(device, MH_MMU_PAGE_FAULT, ®);
- kgsl_regread(device, MH_MMU_PT_BASE, &ptbase);
+ kgsl_regread(mmu->device, MH_MMU_PAGE_FAULT, ®);
+ kgsl_regread(mmu->device, MH_MMU_PT_BASE, &ptbase);
- KGSL_MEM_CRIT(device,
+ KGSL_MEM_CRIT(mmu->device,
"mmu page fault: page=0x%lx pt=%d op=%s axi=%d\n",
reg & ~(PAGE_SIZE - 1),
kgsl_mmu_get_ptname_from_ptbase(ptbase),
@@ -460,7 +460,7 @@
return NULL;
}
-static void kgsl_gpummu_default_setstate(struct kgsl_device *device,
+static void kgsl_gpummu_default_setstate(struct kgsl_mmu *mmu,
uint32_t flags)
{
struct kgsl_gpummu_pt *gpummu_pt;
@@ -468,23 +468,21 @@
return;
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
- kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
- gpummu_pt = device->mmu.hwpagetable->priv;
- kgsl_regwrite(device, MH_MMU_PT_BASE,
+ kgsl_idle(mmu->device, KGSL_TIMEOUT_DEFAULT);
+ gpummu_pt = mmu->hwpagetable->priv;
+ kgsl_regwrite(mmu->device, MH_MMU_PT_BASE,
gpummu_pt->base.gpuaddr);
}
if (flags & KGSL_MMUFLAGS_TLBFLUSH) {
/* Invalidate all and tc */
- kgsl_regwrite(device, MH_MMU_INVALIDATE, 0x00000003);
+ kgsl_regwrite(mmu->device, MH_MMU_INVALIDATE, 0x00000003);
}
}
-static void kgsl_gpummu_setstate(struct kgsl_device *device,
+static void kgsl_gpummu_setstate(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pagetable)
{
- struct kgsl_mmu *mmu = &device->mmu;
-
if (mmu->flags & KGSL_FLAGS_STARTED) {
/* page table not current, then setup mmu to use new
* specified page table
@@ -497,13 +495,13 @@
kgsl_mmu_pt_get_flags(pagetable, mmu->device->id);
/* call device specific set page table */
- kgsl_setstate(mmu->device, KGSL_MMUFLAGS_TLBFLUSH |
+ kgsl_setstate(mmu, KGSL_MMUFLAGS_TLBFLUSH |
KGSL_MMUFLAGS_PTUPDATE);
}
}
}
-static int kgsl_gpummu_init(struct kgsl_device *device)
+static int kgsl_gpummu_init(struct kgsl_mmu *mmu)
{
/*
* intialize device mmu
@@ -511,9 +509,6 @@
* call this with the global lock held
*/
int status = 0;
- struct kgsl_mmu *mmu = &device->mmu;
-
- mmu->device = device;
/* sub-client MMU lookups require address translation */
if ((mmu->config & ~0x1) > 0) {
@@ -533,12 +528,12 @@
mmu->setstate_memory.size);
}
- dev_info(device->dev, "|%s| MMU type set for device is GPUMMU\n",
+ dev_info(mmu->device->dev, "|%s| MMU type set for device is GPUMMU\n",
__func__);
return status;
}
-static int kgsl_gpummu_start(struct kgsl_device *device)
+static int kgsl_gpummu_start(struct kgsl_mmu *mmu)
{
/*
* intialize device mmu
@@ -546,7 +541,7 @@
* call this with the global lock held
*/
- struct kgsl_mmu *mmu = &device->mmu;
+ struct kgsl_device *device = mmu->device;
struct kgsl_gpummu_pt *gpummu_pt;
if (mmu->flags & KGSL_FLAGS_STARTED)
@@ -587,12 +582,12 @@
mmu->hwpagetable = mmu->defaultpagetable;
gpummu_pt = mmu->hwpagetable->priv;
- kgsl_regwrite(device, MH_MMU_PT_BASE,
+ kgsl_regwrite(mmu->device, MH_MMU_PT_BASE,
gpummu_pt->base.gpuaddr);
- kgsl_regwrite(device, MH_MMU_VA_RANGE,
+ kgsl_regwrite(mmu->device, MH_MMU_VA_RANGE,
(KGSL_PAGETABLE_BASE |
(CONFIG_MSM_KGSL_PAGE_TABLE_SIZE >> 16)));
- kgsl_setstate(device, KGSL_MMUFLAGS_TLBFLUSH);
+ kgsl_setstate(mmu, KGSL_MMUFLAGS_TLBFLUSH);
mmu->flags |= KGSL_FLAGS_STARTED;
return 0;
@@ -691,25 +686,21 @@
return 0;
}
-static int kgsl_gpummu_stop(struct kgsl_device *device)
+static int kgsl_gpummu_stop(struct kgsl_mmu *mmu)
{
- struct kgsl_mmu *mmu = &device->mmu;
-
- kgsl_regwrite(device, MH_MMU_CONFIG, 0x00000000);
+ kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
mmu->flags &= ~KGSL_FLAGS_STARTED;
return 0;
}
-static int kgsl_gpummu_close(struct kgsl_device *device)
+static int kgsl_gpummu_close(struct kgsl_mmu *mmu)
{
/*
* close device mmu
*
* call this with the global lock held
*/
- struct kgsl_mmu *mmu = &device->mmu;
-
if (mmu->setstate_memory.gpuaddr)
kgsl_sharedmem_free(&mmu->setstate_memory);
@@ -720,10 +711,10 @@
}
static unsigned int
-kgsl_gpummu_get_current_ptbase(struct kgsl_device *device)
+kgsl_gpummu_get_current_ptbase(struct kgsl_mmu *mmu)
{
unsigned int ptbase;
- kgsl_regread(device, MH_MMU_PT_BASE, &ptbase);
+ kgsl_regread(mmu->device, MH_MMU_PT_BASE, &ptbase);
return ptbase;
}
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index b7f7b0a..bf2a4ee 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -166,17 +166,15 @@
return ret;
}
-static void kgsl_iommu_setstate(struct kgsl_device *device,
+static void kgsl_iommu_setstate(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pagetable)
{
- struct kgsl_mmu *mmu = &device->mmu;
-
if (mmu->flags & KGSL_FLAGS_STARTED) {
/* page table not current, then setup mmu to use new
* specified page table
*/
if (mmu->hwpagetable != pagetable) {
- kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
+ kgsl_idle(mmu->device, KGSL_TIMEOUT_DEFAULT);
kgsl_detach_pagetable_iommu_domain(mmu);
mmu->hwpagetable = pagetable;
if (mmu->hwpagetable)
@@ -185,7 +183,7 @@
}
}
-static int kgsl_iommu_init(struct kgsl_device *device)
+static int kgsl_iommu_init(struct kgsl_mmu *mmu)
{
/*
* intialize device mmu
@@ -193,11 +191,8 @@
* call this with the global lock held
*/
int status = 0;
- struct kgsl_mmu *mmu = &device->mmu;
struct kgsl_iommu *iommu;
- mmu->device = device;
-
iommu = kzalloc(sizeof(struct kgsl_iommu), GFP_KERNEL);
if (!iommu) {
KGSL_CORE_ERR("kzalloc(%d) failed\n",
@@ -205,27 +200,26 @@
return -ENOMEM;
}
- status = kgsl_get_iommu_ctxt(iommu, device);
+ status = kgsl_get_iommu_ctxt(iommu, mmu->device);
if (status) {
kfree(iommu);
iommu = NULL;
}
mmu->priv = iommu;
- dev_info(device->dev, "|%s| MMU type set for device is IOMMU\n",
+ dev_info(mmu->device->dev, "|%s| MMU type set for device is IOMMU\n",
__func__);
return status;
}
-static int kgsl_iommu_start(struct kgsl_device *device)
+static int kgsl_iommu_start(struct kgsl_mmu *mmu)
{
int status;
- struct kgsl_mmu *mmu = &device->mmu;
if (mmu->flags & KGSL_FLAGS_STARTED)
return 0;
- kgsl_regwrite(device, MH_MMU_CONFIG, 0x00000000);
+ kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
if (mmu->defaultpagetable == NULL)
mmu->defaultpagetable =
kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
@@ -304,14 +298,13 @@
return ret;
}
-static int kgsl_iommu_stop(struct kgsl_device *device)
+static int kgsl_iommu_stop(struct kgsl_mmu *mmu)
{
/*
* stop device mmu
*
* call this with the global lock held
*/
- struct kgsl_mmu *mmu = &device->mmu;
if (mmu->flags & KGSL_FLAGS_STARTED) {
/* detach iommu attachment */
@@ -323,9 +316,8 @@
return 0;
}
-static int kgsl_iommu_close(struct kgsl_device *device)
+static int kgsl_iommu_close(struct kgsl_mmu *mmu)
{
- struct kgsl_mmu *mmu = &device->mmu;
if (mmu->defaultpagetable)
kgsl_mmu_putpagetable(mmu->defaultpagetable);
@@ -333,13 +325,13 @@
}
static unsigned int
-kgsl_iommu_get_current_ptbase(struct kgsl_device *device)
+kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu)
{
/* Current base is always the hwpagetables domain as we
* do not use per process pagetables right not for iommu.
* This will change when we switch to per process pagetables.
*/
- return (unsigned int)device->mmu.hwpagetable->priv;
+ return (unsigned int)mmu->hwpagetable->priv;
}
struct kgsl_mmu_ops iommu_ops = {
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 323c992..2b359ec 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -328,7 +328,7 @@
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return 0;
else
- return mmu->mmu_ops->mmu_get_current_ptbase(device);
+ return mmu->mmu_ops->mmu_get_current_ptbase(mmu);
}
EXPORT_SYMBOL(kgsl_mmu_get_current_ptbase);
@@ -359,7 +359,7 @@
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return;
else
- mmu->mmu_ops->mmu_setstate(device,
+ mmu->mmu_ops->mmu_setstate(mmu,
pagetable);
}
EXPORT_SYMBOL(kgsl_mmu_setstate);
@@ -385,7 +385,7 @@
else if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type)
mmu->mmu_ops = &iommu_ops;
- return mmu->mmu_ops->mmu_init(device);
+ return mmu->mmu_ops->mmu_init(mmu);
}
EXPORT_SYMBOL(kgsl_mmu_init);
@@ -400,7 +400,7 @@
kgsl_setup_pt(NULL);
return 0;
} else {
- return mmu->mmu_ops->mmu_start(device);
+ return mmu->mmu_ops->mmu_start(mmu);
}
}
EXPORT_SYMBOL(kgsl_mmu_start);
@@ -418,7 +418,7 @@
if (status & MH_INTERRUPT_MASK__AXI_WRITE_ERROR)
KGSL_MEM_CRIT(device, "axi write error interrupt: %08x\n", reg);
if (status & MH_INTERRUPT_MASK__MMU_PAGE_FAULT)
- device->mmu.mmu_ops->mmu_pagefault(device);
+ device->mmu.mmu_ops->mmu_pagefault(&device->mmu);
status &= KGSL_MMU_INT_MASK;
kgsl_regwrite(device, MH_INTERRUPT_CLEAR, status);
@@ -543,15 +543,15 @@
}
EXPORT_SYMBOL(kgsl_mmu_putpagetable);
-void kgsl_setstate(struct kgsl_device *device, uint32_t flags)
+void kgsl_setstate(struct kgsl_mmu *mmu, uint32_t flags)
{
- struct kgsl_mmu *mmu = &device->mmu;
+ struct kgsl_device *device = mmu->device;
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return;
else if (device->ftbl->setstate)
device->ftbl->setstate(device, flags);
else if (mmu->mmu_ops->mmu_device_setstate)
- mmu->mmu_ops->mmu_device_setstate(device, flags);
+ mmu->mmu_ops->mmu_device_setstate(mmu, flags);
}
EXPORT_SYMBOL(kgsl_setstate);
@@ -561,7 +561,7 @@
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return;
else if (mmu->mmu_ops->mmu_device_setstate)
- mmu->mmu_ops->mmu_device_setstate(device, flags);
+ mmu->mmu_ops->mmu_device_setstate(mmu, flags);
}
EXPORT_SYMBOL(kgsl_mmu_device_setstate);
@@ -753,7 +753,7 @@
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
return 0;
else
- return mmu->mmu_ops->mmu_stop(device);
+ return mmu->mmu_ops->mmu_stop(mmu);
}
EXPORT_SYMBOL(kgsl_mmu_stop);
@@ -764,8 +764,9 @@
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
kgsl_sharedmem_free(&mmu->setstate_memory);
return 0;
- } else
- return mmu->mmu_ops->mmu_close(device);
+ } else {
+ return mmu->mmu_ops->mmu_close(mmu);
+ }
}
EXPORT_SYMBOL(kgsl_mmu_close);
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 63ecdd6..e35f368 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -116,18 +116,20 @@
void *priv;
};
+struct kgsl_mmu;
+
struct kgsl_mmu_ops {
- int (*mmu_init) (struct kgsl_device *device);
- int (*mmu_close) (struct kgsl_device *device);
- int (*mmu_start) (struct kgsl_device *device);
- int (*mmu_stop) (struct kgsl_device *device);
- void (*mmu_setstate) (struct kgsl_device *device,
+ int (*mmu_init) (struct kgsl_mmu *mmu);
+ int (*mmu_close) (struct kgsl_mmu *mmu);
+ int (*mmu_start) (struct kgsl_mmu *mmu);
+ int (*mmu_stop) (struct kgsl_mmu *mmu);
+ void (*mmu_setstate) (struct kgsl_mmu *mmu,
struct kgsl_pagetable *pagetable);
- void (*mmu_device_setstate) (struct kgsl_device *device,
+ void (*mmu_device_setstate) (struct kgsl_mmu *mmu,
uint32_t flags);
- void (*mmu_pagefault) (struct kgsl_device *device);
+ void (*mmu_pagefault) (struct kgsl_mmu *mmu);
unsigned int (*mmu_get_current_ptbase)
- (struct kgsl_device *device);
+ (struct kgsl_mmu *mmu);
};
struct kgsl_mmu_pt_ops {
@@ -177,7 +179,7 @@
int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc);
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
-void kgsl_setstate(struct kgsl_device *device, uint32_t flags);
+void kgsl_setstate(struct kgsl_mmu *mmu, uint32_t flags);
void kgsl_mmu_device_setstate(struct kgsl_device *device, uint32_t flags);
void kgsl_mmu_setstate(struct kgsl_device *device,
struct kgsl_pagetable *pt);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 5902361..3ca9e18 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -468,8 +468,9 @@
cnt = PACKETSIZE_STATESTREAM;
ofs = 0;
}
- kgsl_setstate(device, kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
- device->id));
+ kgsl_setstate(&device->mmu,
+ kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
+ device->id));
result = wait_event_interruptible_timeout(device->wait_queue,
room_in_rb(z180_dev),
@@ -881,7 +882,7 @@
if (z180_dev->ringbuffer.prevctx == context->id) {
z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT;
device->mmu.hwpagetable = device->mmu.defaultpagetable;
- kgsl_setstate(device, KGSL_MMUFLAGS_PTUPDATE);
+ kgsl_setstate(&device->mmu, KGSL_MMUFLAGS_PTUPDATE);
}
}
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index a027a2d..e9c710a 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -603,6 +603,7 @@
struct vcd_property_profile vcd_property_profile;
struct vcd_property_hdr vcd_property_hdr;
struct vcd_property_codec vcd_property_codec;
+ struct vcd_property_i_period vcd_property_i_period;
int rc = 0;
/* Validate params */
@@ -614,7 +615,7 @@
if (rc < 0) {
WFD_MSG_ERR("Error getting codec property");
rc = -EINVAL;
- goto err;
+ goto err_set_profile;
}
if (!((vcd_property_codec.codec == VCD_CODEC_H264
@@ -624,7 +625,7 @@
WFD_MSG_ERR("Attempting to set %d for codec type %d",
codec, vcd_property_codec.codec);
rc = -EINVAL;
- goto err;
+ goto err_set_profile;
}
/* Set property */
@@ -671,12 +672,31 @@
"not setting profile (%d)",
codec, profile);
rc = -ENOTSUPP;
- goto err;
+ goto err_set_profile;
}
rc = vcd_set_property(client_ctx->vcd_handle,
&vcd_property_hdr, &vcd_property_profile);
-err:
+
+ /* Disable B-frames, since VSG doesn't support out of order i/p bufs */
+ vcd_property_hdr.prop_id = VCD_I_INTRA_PERIOD;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_i_period);
+
+ rc = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_i_period);
+ if (rc) {
+ WFD_MSG_ERR("Error getting I-period property");
+ goto err_set_profile;
+ }
+ vcd_property_i_period.b_frames = 0;
+ rc = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_i_period);
+ if (rc) {
+ WFD_MSG_ERR("Error setting I-period property");
+ goto err_set_profile;
+ }
+
+err_set_profile:
return rc;
}
@@ -1529,6 +1549,146 @@
return rc;
}
+static long venc_set_entropy_mode(struct video_client_ctx *client_ctx,
+ __s32 value)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_entropy_control entropy_control;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ rc = -EINVAL;
+ goto set_entropy_mode_fail;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_ENTROPY_CTRL;
+ vcd_property_hdr.sz = sizeof(entropy_control);
+
+ switch (value) {
+ case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
+ entropy_control.entropy_sel = VCD_ENTROPY_SEL_CAVLC;
+ break;
+ case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
+ entropy_control.entropy_sel = VCD_ENTROPY_SEL_CABAC;
+ entropy_control.cabac_model = VCD_CABAC_MODEL_NUMBER_0;
+ break;
+ default:
+ WFD_MSG_ERR("Entropy type %d not supported\n", value);
+ rc = -ENOTSUPP;
+ goto set_entropy_mode_fail;
+ }
+ rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &entropy_control);
+ if (rc) {
+ WFD_MSG_ERR("Failed to set entropy mode\n");
+ goto set_entropy_mode_fail;
+ }
+
+set_entropy_mode_fail:
+ return rc;
+}
+
+static long venc_get_entropy_mode(struct video_client_ctx *client_ctx,
+ __s32 *value)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_entropy_control entropy_control;
+ int rc = 0;
+
+ if (!client_ctx || !value) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ rc = -EINVAL;
+ goto get_entropy_mode_fail;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_ENTROPY_CTRL;
+ vcd_property_hdr.sz = sizeof(entropy_control);
+
+ rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &entropy_control);
+
+ if (rc) {
+ WFD_MSG_ERR("Failed to get entropy mode\n");
+ goto get_entropy_mode_fail;
+ }
+
+ switch (entropy_control.entropy_sel) {
+ case VCD_ENTROPY_SEL_CAVLC:
+ *value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
+ break;
+ case VCD_ENTROPY_SEL_CABAC:
+ *value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
+ break;
+ default:
+ WFD_MSG_ERR("Entropy type %d not known\n",
+ entropy_control.entropy_sel);
+ rc = -EINVAL;
+ goto get_entropy_mode_fail;
+ }
+get_entropy_mode_fail:
+ return rc;
+}
+
+static long venc_set_cyclic_intra_refresh_mb(
+ struct video_client_ctx *client_ctx,
+ __s32 value)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_intra_refresh_mb_number cir_mb_num;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ rc = -EINVAL;
+ goto set_cir_mbs_fail;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_INTRA_REFRESH;
+ vcd_property_hdr.sz = sizeof(cir_mb_num);
+
+ cir_mb_num.cir_mb_number = value;
+
+ rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &cir_mb_num);
+ if (rc) {
+ WFD_MSG_ERR("Failed to set CIR MBs\n");
+ goto set_cir_mbs_fail;
+ }
+
+set_cir_mbs_fail:
+ return rc;
+}
+
+static long venc_get_cyclic_intra_refresh_mb(
+ struct video_client_ctx *client_ctx,
+ __s32 *value)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_intra_refresh_mb_number cir_mb_num;
+ int rc = 0;
+
+ if (!client_ctx || !value) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ rc = -EINVAL;
+ goto get_cir_mbs_fail;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_INTRA_REFRESH;
+ vcd_property_hdr.sz = sizeof(cir_mb_num);
+
+ rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &cir_mb_num);
+ if (rc) {
+ WFD_MSG_ERR("Failed to set CIR MBs\n");
+ goto get_cir_mbs_fail;
+ }
+
+ *value = cir_mb_num.cir_mb_number;
+
+get_cir_mbs_fail:
+ return rc;
+}
static long venc_set_input_buffer(struct v4l2_subdev *sd, void *arg)
{
struct mem_region *mregion = arg;
@@ -1904,6 +2064,12 @@
case V4L2_CID_MPEG_QCOM_SET_PERF_LEVEL:
rc = venc_set_max_perf_level(client_ctx, ctrl->value);
break;
+ case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+ rc = venc_set_entropy_mode(client_ctx, ctrl->value);
+ break;
+ case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+ rc = venc_set_cyclic_intra_refresh_mb(client_ctx, ctrl->value);
+ break;
default:
WFD_MSG_ERR("Set property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
@@ -1963,6 +2129,12 @@
rc = venc_get_multislicing_mode(client_ctx, ctrl->id,
&ctrl->value);
break;
+ case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+ rc = venc_get_entropy_mode(client_ctx, &ctrl->value);
+ break;
+ case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+ rc = venc_get_cyclic_intra_refresh_mb(client_ctx, &ctrl->value);
+ break;
default:
WFD_MSG_ERR("Get property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
diff --git a/drivers/media/video/msm/wfd/mdp-subdev.c b/drivers/media/video/msm/wfd/mdp-subdev.c
index e519a4d..a6d244f 100644
--- a/drivers/media/video/msm/wfd/mdp-subdev.c
+++ b/drivers/media/video/msm/wfd/mdp-subdev.c
@@ -45,13 +45,6 @@
goto exit;
}
- /*Tell HDMI daemon to open fb1*/
- rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ADD);
- if (rc) {
- WFD_MSG_ERR("Failed add to kobj");
- goto exit;
- }
-
msm_fb_writeback_init(fbi);
inst->mdp = fbi;
*cookie = inst;
@@ -78,9 +71,6 @@
rc = -ENODEV;
goto exit;
}
- rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ONLINE);
- if (rc)
- WFD_MSG_ERR("Failed to send ONLINE event\n");
}
exit:
return rc;
@@ -89,19 +79,12 @@
{
struct mdp_instance *inst = arg;
int rc = 0;
- struct fb_info *fbi = NULL;
if (inst) {
rc = msm_fb_writeback_stop(inst->mdp);
if (rc) {
WFD_MSG_ERR("Failed to stop writeback mode\n");
return rc;
}
- fbi = (struct fb_info *)inst->mdp;
- rc = kobject_uevent(&fbi->dev->kobj, KOBJ_OFFLINE);
- if (rc) {
- WFD_MSG_ERR("Failed to send offline event\n");
- return -EIO;
- }
}
return 0;
}
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index c12636c..7ab5d17 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -43,6 +43,7 @@
#define VENC_INPUT_BUFFERS 4
struct wfd_device {
+ struct mutex dev_lock;
struct platform_device *pdev;
struct v4l2_device v4l2_dev;
struct video_device *pvdev;
@@ -51,6 +52,7 @@
struct v4l2_subdev vsg_sdev;
struct ion_client *ion_client;
bool secure_device;
+ bool in_use;
};
struct mem_info {
@@ -1243,13 +1245,25 @@
static int wfd_open(struct file *filp)
{
int rc = 0;
- struct wfd_inst *inst;
- struct wfd_device *wfd_dev;
+ struct wfd_inst *inst = NULL;
+ struct wfd_device *wfd_dev = NULL;
struct venc_msg_ops enc_mops;
struct vsg_msg_ops vsg_mops;
WFD_MSG_DBG("wfd_open: E\n");
wfd_dev = video_drvdata(filp);
+
+ mutex_lock(&wfd_dev->dev_lock);
+ if (wfd_dev->in_use) {
+ WFD_MSG_ERR("Device already in use.\n");
+ rc = -EBUSY;
+ mutex_unlock(&wfd_dev->dev_lock);
+ goto err_dev_busy;
+ }
+
+ wfd_dev->in_use = true;
+ mutex_unlock(&wfd_dev->dev_lock);
+
inst = kzalloc(sizeof(struct wfd_inst), GFP_KERNEL);
if (!inst || !wfd_dev) {
WFD_MSG_ERR("Could not allocate memory for "
@@ -1310,6 +1324,7 @@
MDP_CLOSE, (void *)inst->mdp_inst);
err_mdp_open:
kfree(inst);
+err_dev_busy:
return rc;
}
@@ -1345,6 +1360,10 @@
kfree(inst);
}
+ mutex_lock(&wfd_dev->dev_lock);
+ wfd_dev->in_use = false;
+ mutex_unlock(&wfd_dev->dev_lock);
+
WFD_MSG_DBG("wfd_close: X\n");
return 0;
}
@@ -1487,7 +1506,9 @@
}
/* Other device specific stuff */
+ mutex_init(&wfd_dev[c].dev_lock);
wfd_dev[c].ion_client = ion_client;
+ wfd_dev[c].in_use = false;
switch (WFD_DEVICE_NUMBER_BASE + c) {
case WFD_DEVICE_SECURE:
wfd_dev[c].secure_device = true;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 2da48ab..f319eb5 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -168,8 +168,6 @@
return rc;
}
-#ifdef CONFIG_PM_SLEEP
-#define USB_PHY_SUSP_DIG_VOL 500000
static int msm_hsusb_config_vddcx(int high)
{
struct msm_otg *motg = the_msm_otg;
@@ -190,12 +188,6 @@
return ret;
}
-#else
-static int msm_hsusb_config_vddcx(int high)
-{
- return 0;
-}
-#endif
static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
{
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 222d353..7cc73de 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -99,7 +99,7 @@
static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
static int new_perf_level;
static struct ion_client *display_iclient;
-static struct mdp4_iommu_pipe_info mdp_iommu[MDP4_MIXER_MAX][OVERLAY_PIPE_RGB3];
+static struct mdp4_iommu_pipe_info mdp_iommu[MDP4_MIXER_MAX][OVERLAY_PIPE_MAX];
int mdp4_overlay_iommu_map_buf(int mem_id,
struct mdp4_overlay_pipe *pipe, unsigned int plane,
@@ -160,7 +160,7 @@
if (!display_iclient)
return;
- for (j = 0; j < OVERLAY_PIPE_RGB3; j++) {
+ for (j = 0; j < OVERLAY_PIPE_MAX; j++) {
iom_pipe_info = &mdp_iommu[pipe->mixer_num][j];
for (i = 0; i < MDP4_MAX_PLANE; i++) {
if (iom_pipe_info->prev_ihdl[i]) {
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index ea04723..b9760bf 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -259,14 +259,8 @@
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
if (dtv_pipe != NULL) {
- mdp4_mixer_stage_down(dtv_pipe);
- /*
- * wait4vsync to make sure pipes are
- * dis-engaged from mixer1
- * before turn off timing generator
- */
- mdp4_overlay_dtv_wait4vsync();
mdp4_dtv_stop(mfd);
+ mdp4_mixer_stage_down(dtv_pipe);
mdp4_overlay_pipe_free(dtv_pipe);
mdp4_iommu_unmap(dtv_pipe);
dtv_pipe = NULL;
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index 2301472..570d71c 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -37,6 +37,9 @@
/* Length of the DSP frame info header added to the voc packet. */
#define DSP_FRAME_HDR_LEN 1
+#define MODE_IS127 0x2
+#define MODE_4GV_NB 0x3
+#define MODE_4GV_WB 0x4
#define MODE_AMR 0x5
#define MODE_AMR_WB 0xD
#define MODE_PCM 0xC
@@ -74,7 +77,10 @@
};
struct voip_frame {
+ union {
uint32_t frame_type;
+ uint32_t packet_rate;
+ } header;
uint32_t len;
uint8_t voc_pkt[VOIP_MAX_VOC_PKT_SIZE];
};
@@ -276,7 +282,8 @@
* Bits 0-3: Frame rate
* Bits 4-7: Frame type
*/
- buf_node->frame.frame_type = ((*voc_pkt) & 0xF0) >> 4;
+ buf_node->frame.header.frame_type =
+ ((*voc_pkt) & 0xF0) >> 4;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
memcpy(&buf_node->frame.voc_pkt[0],
@@ -285,6 +292,24 @@
list_add_tail(&buf_node->list, &prtd->out_queue);
break;
}
+ case MODE_IS127:
+ case MODE_4GV_NB:
+ case MODE_4GV_WB: {
+ /* Remove the DSP frame info header.
+ * Header format:
+ * Bits 0-3: frame rate
+ */
+ buf_node->frame.header.packet_rate = (*voc_pkt) & 0x0F;
+ voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+ buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
+
+ memcpy(&buf_node->frame.voc_pkt[0],
+ voc_pkt,
+ buf_node->frame.len);
+
+ list_add_tail(&buf_node->list, &prtd->out_queue);
+ break;
+ }
default: {
buf_node->frame.len = pkt_len;
memcpy(&buf_node->frame.voc_pkt[0],
@@ -332,8 +357,8 @@
* Bits 0-3: Frame rate
* Bits 4-7: Frame type
*/
- *voc_pkt = ((buf_node->frame.frame_type & 0x0F) << 4) |
- (prtd->rate_type & 0x0F);
+ *voc_pkt = ((buf_node->frame.header.frame_type &
+ 0x0F) << 4) | (prtd->rate_type & 0x0F);
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
memcpy(voc_pkt,
@@ -342,6 +367,23 @@
list_add_tail(&buf_node->list, &prtd->free_in_queue);
break;
}
+ case MODE_IS127:
+ case MODE_4GV_NB:
+ case MODE_4GV_WB: {
+ /* Add the DSP frame info header. Header format:
+ * Bits 0-3 : Frame rate
+ */
+ *voc_pkt = buf_node->frame.header.packet_rate & 0x0F;
+ voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+ *pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
+
+ memcpy(voc_pkt,
+ &buf_node->frame.voc_pkt[0],
+ buf_node->frame.len);
+
+ list_add_tail(&buf_node->list, &prtd->free_in_queue);
+ break;
+ }
default: {
*pkt_len = buf_node->frame.len;
@@ -702,7 +744,9 @@
ret = msm_pcm_capture_prepare(substream);
if ((runtime->format != FORMAT_SPECIAL) &&
- ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB))) {
+ ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB) ||
+ (prtd->mode == MODE_IS127) || (prtd->mode == MODE_4GV_NB) ||
+ (prtd->mode == MODE_4GV_WB))) {
pr_err("mode:%d and format:%u are not mached\n",
prtd->mode, (uint32_t)runtime->format);
ret = -EINVAL;
@@ -976,6 +1020,24 @@
*rate_type = 0;
break;
}
+ case MODE_IS127:
+ case MODE_4GV_NB:
+ case MODE_4GV_WB: {
+ switch (rate) {
+ case VOC_0_RATE:
+ case VOC_8_RATE:
+ case VOC_4_RATE:
+ case VOC_2_RATE:
+ case VOC_1_RATE:
+ *rate_type = rate;
+ break;
+ default:
+ pr_err("wrong rate for IS127/4GV_NB/WB.\n");
+ ret = -EINVAL;
+ break;
+ }
+ break;
+ }
default:
pr_err("wrong mode type.\n");
ret = -EINVAL;
@@ -1005,6 +1067,15 @@
else
media_type = VSS_MEDIA_ID_PCM_WB;
break;
+ case MODE_IS127: /* EVRC-A */
+ media_type = VSS_MEDIA_ID_EVRC_MODEM;
+ break;
+ case MODE_4GV_NB: /* EVRC-B */
+ media_type = VSS_MEDIA_ID_4GV_NB_MODEM;
+ break;
+ case MODE_4GV_WB: /* EVRC-WB */
+ media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
+ break;
default:
pr_debug(" input mode is not supported\n");
media_type = -EINVAL;
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 3310abd..cf691c0 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -163,6 +163,14 @@
#define VSS_IWIDEVOICE_CMD_SET_WIDEVOICE 0x00011243
/* Enable/disable WideVoice */
+enum msm_audio_voc_rate {
+ VOC_0_RATE, /* Blank frame */
+ VOC_8_RATE, /* 1/8 rate */
+ VOC_4_RATE, /* 1/4 rate */
+ VOC_2_RATE, /* 1/2 rate */
+ VOC_1_RATE /* Full rate */
+};
+
struct vss_istream_cmd_set_tty_mode_t {
uint32_t mode;
/**<
@@ -657,6 +665,10 @@
/* G.711 mu-law (contains two 10ms vocoder frames). */
#define VSS_MEDIA_ID_G729 0x00010FD0
/* G.729AB (contains two 10ms vocoder frames. */
+#define VSS_MEDIA_ID_4GV_NB_MODEM 0x00010FC3
+/*CDMA EVRC-B vocoder modem format */
+#define VSS_MEDIA_ID_4GV_WB_MODEM 0x00010FC4
+/*CDMA EVRC-WB vocoder modem format */
#define VSS_IVOCPROC_CMD_SET_MUTE 0x000110EF