Merge "msm: kgsl: Switch pagetables in stream for IOMMU" 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/Makefile b/arch/arm/mach-msm/Makefile
index cf80fa6..2295679 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -318,7 +318,7 @@
ifdef CONFIG_VCM
obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
endif
-obj-$(CONFIG_MSM_OCMEM) += ocmem.o
+obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o
obj-$(CONFIG_ARCH_MSM7X27) += gpiomux-7x27.o gpiomux-v1.o gpiomux.o
obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
diff --git a/arch/arm/mach-msm/acpuclock-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-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/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 32d46b4..4b46c01 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -74,4 +74,6 @@
};
struct ocmem_zone *get_zone(unsigned);
+unsigned long allocate_head(struct ocmem_zone *, unsigned long);
+int free_head(struct ocmem_zone *, unsigned long, unsigned long);
#endif
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index af39dc3..203b8d1 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -225,6 +225,8 @@
zone->max_regions = 0;
INIT_LIST_HEAD(&zone->region_list);
zone->z_ops = z_ops;
+ z_ops->allocate = allocate_head;
+ z_ops->free = free_head;
active_zones++;
if (active_zones == 1)
diff --git a/arch/arm/mach-msm/ocmem_allocator.c b/arch/arm/mach-msm/ocmem_allocator.c
new file mode 100644
index 0000000..9f073fc
--- /dev/null
+++ b/arch/arm/mach-msm/ocmem_allocator.c
@@ -0,0 +1,45 @@
+/* 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 <mach/ocmem.h>
+#include <mach/ocmem_priv.h>
+#include <linux/genalloc.h>
+
+/* All allocator operations are serialized by ocmem driver */
+unsigned long allocate_head(struct ocmem_zone *z, unsigned long size)
+{
+
+ unsigned long offset;
+
+ offset = gen_pool_alloc(z->z_pool, size);
+
+ if (!offset)
+ return -ENOMEM;
+
+ z->z_head += size;
+ z->z_free -= size;
+ return offset;
+}
+
+int free_head(struct ocmem_zone *z, unsigned long offset,
+ unsigned long size)
+{
+ if (offset > z->z_head) {
+ pr_err("ocmem: Detected out of order free "
+ "leading to fragmentation\n");
+ return -EINVAL;
+ }
+ gen_pool_free(z->z_pool, offset, size);
+ z->z_head -= size;
+ z->z_free += size;
+ return 0;
+}
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/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index a7a4a2a..4ac2643 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1139,8 +1139,17 @@
}
}
#if defined(CONFIG_DIAG_OVER_USB)
+ /* Check for the command/respond msg for the maximum packet length */
+ if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
+ (*(uint16_t *)(buf+2) == 0x0055)) {
+ for (i = 0; i < 4; i++)
+ *(driver->apps_rsp_buf+i) = *(buf+i);
+ *(uint32_t *)(driver->apps_rsp_buf+4) = PKT_SIZE;
+ ENCODE_RSP_AND_SEND(7);
+ return 0;
+ }
/* Check for Apps Only & get event mask request */
- if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
+ else if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
driver->apps_rsp_buf[0] = 0x81;
driver->apps_rsp_buf[1] = 0x0;
*(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
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/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index 8cad387..c94fa13 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -365,7 +365,15 @@
WFD_MSG_ERR("Failed to get out buf reqs rc = %d", rc);
goto err;
}
- b->count = buf_req.actual_count;
+
+ buf_req.actual_count = b->count = max(buf_req.min_count, b->count);
+ rc = vcd_set_buffer_requirements(client_ctx->vcd_handle,
+ VCD_BUFFER_OUTPUT, &buf_req);
+ if (rc) {
+ WFD_MSG_ERR("Failed to set out buf reqs rc = %d", rc);
+ goto err;
+ }
+
err:
return rc;
}
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/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/include/linux/diagchar.h b/include/linux/diagchar.h
index e50a054..537960b 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -52,7 +52,7 @@
#define APQ8030_TOOLS_ID 4079
#define MSM8627_TOOLS_ID 4080
#define MSM8227_TOOLS_ID 4081
-#define MSM8974_TOOLS_ID 4072
+#define MSM8974_TOOLS_ID 4083
#define MSG_MASK_0 (0x00000001)
#define MSG_MASK_1 (0x00000002)
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;
}