Merge "msm: ipa: fix unclocked IPA register access"
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
index 3c3a242..af5cbc6 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
@@ -11,6 +11,8 @@
- qcom,iommu-pmu-ngroups: Number of Performance Monitor Unit (PMU) groups.
- qcom,iommu-pmu-ncounters: Number of PMU counters per group.
- qcom,iommu-pmu-event-classes: List of event classes supported.
+- qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
+ access to the IOMMU configuration registers
- List of sub nodes, one for each of the translation context banks supported.
Required properties for each sub-node:
diff --git a/arch/arm/mach-msm/include/mach/msm_ipc_router.h b/arch/arm/mach-msm/include/mach/msm_ipc_router.h
index c68c783..894379e 100644
--- a/arch/arm/mach-msm/include/mach/msm_ipc_router.h
+++ b/arch/arm/mach-msm/include/mach/msm_ipc_router.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,11 @@
MSM_IPC_ROUTER_WRITE_DONE,
};
+struct comm_mode_info {
+ int mode;
+ void *xprt_info;
+};
+
struct msm_ipc_port {
struct list_head list;
@@ -39,6 +44,7 @@
uint32_t type;
unsigned flags;
spinlock_t port_lock;
+ struct comm_mode_info mode_info;
struct list_head incomplete;
struct mutex incomplete_lock;
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index c31c969..a328b2b 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -1245,6 +1245,67 @@
return 0;
}
+static int msm_ipc_router_send_remove_client(struct comm_mode_info *mode_info,
+ uint32_t node_id, uint32_t port_id)
+{
+ union rr_control_msg msg;
+ struct msm_ipc_router_xprt_info *tmp_xprt_info;
+ int mode;
+ void *xprt_info;
+ int rc = 0;
+
+ if (!mode_info) {
+ pr_err("%s: NULL mode_info\n", __func__);
+ return -EINVAL;
+ }
+ mode = mode_info->mode;
+ xprt_info = mode_info->xprt_info;
+
+ msg.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT;
+ msg.cli.node_id = node_id;
+ msg.cli.port_id = port_id;
+
+ if ((mode == SINGLE_LINK_MODE) && xprt_info) {
+ mutex_lock(&xprt_info_list_lock);
+ list_for_each_entry(tmp_xprt_info, &xprt_info_list, list) {
+ if (tmp_xprt_info != xprt_info)
+ continue;
+ msm_ipc_router_send_control_msg(tmp_xprt_info, &msg);
+ break;
+ }
+ mutex_unlock(&xprt_info_list_lock);
+ } else if ((mode == SINGLE_LINK_MODE) && !xprt_info) {
+ broadcast_ctl_msg_locally(&msg);
+ } else if (mode == MULTI_LINK_MODE) {
+ broadcast_ctl_msg(&msg);
+ broadcast_ctl_msg_locally(&msg);
+ } else if (mode != NULL_MODE) {
+ pr_err("%s: Invalid mode(%d) + xprt_inf(%p) for %08x:%08x\n",
+ __func__, mode, xprt_info, node_id, port_id);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+static void update_comm_mode_info(struct comm_mode_info *mode_info,
+ struct msm_ipc_router_xprt_info *xprt_info)
+{
+ if (!mode_info) {
+ pr_err("%s: NULL mode_info\n", __func__);
+ return;
+ }
+
+ if (mode_info->mode == NULL_MODE) {
+ mode_info->xprt_info = xprt_info;
+ mode_info->mode = SINGLE_LINK_MODE;
+ } else if (mode_info->mode == SINGLE_LINK_MODE &&
+ mode_info->xprt_info != xprt_info) {
+ mode_info->mode = MULTI_LINK_MODE;
+ }
+
+ return;
+}
+
static void reset_remote_port_info(uint32_t node_id, uint32_t port_id)
{
struct msm_ipc_router_remote_port *rport_ptr;
@@ -1915,6 +1976,7 @@
broadcast_ctl_msg(&ctl);
spin_lock_irqsave(&port_ptr->port_lock, flags);
port_ptr->type = SERVER_PORT;
+ port_ptr->mode_info.mode = MULTI_LINK_MODE;
port_ptr->port_name.service = server->name.service;
port_ptr->port_name.instance = server->name.instance;
spin_unlock_irqrestore(&port_ptr->port_lock, flags);
@@ -2026,6 +2088,7 @@
ret_len = pkt->length;
wake_up(&port_ptr->port_rx_wait_q);
mutex_unlock(&port_ptr->port_rx_q_lock);
+ update_comm_mode_info(&src->mode_info, NULL);
mutex_unlock(&local_ports_lock);
return ret_len;
@@ -2118,6 +2181,7 @@
pr_err("%s: Write on XPRT failed\n", __func__);
return ret;
}
+ update_comm_mode_info(&src->mode_info, xprt_info);
RAW_HDR("[w rr_h] "
"ver=%i,type=%s,src_nid=%08x,src_port_id=%08x,"
@@ -2407,13 +2471,11 @@
* Server port could have been a client port earlier.
* Send REMOVE_CLIENT message in either case.
*/
- msg.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT;
- msg.cli.node_id = port_ptr->this_port.node_id;
- msg.cli.port_id = port_ptr->this_port.port_id;
RR("x REMOVE_CLIENT id=%d:%08x\n",
- msg.cli.node_id, msg.cli.port_id);
- broadcast_ctl_msg(&msg);
- broadcast_ctl_msg_locally(&msg);
+ port_ptr->this_port.node_id, port_ptr->this_port.port_id);
+ msm_ipc_router_send_remove_client(&port_ptr->mode_info,
+ port_ptr->this_port.node_id,
+ port_ptr->this_port.port_id);
} else if (port_ptr->type == CONTROL_PORT) {
mutex_lock(&control_ports_lock);
list_del(&port_ptr->list);
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index cafcdd2..32832dd 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -62,6 +62,12 @@
IRSC_PORT,
};
+enum {
+ NULL_MODE,
+ SINGLE_LINK_MODE,
+ MULTI_LINK_MODE,
+};
+
union rr_control_msg {
uint32_t cmd;
struct {
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 12a3ceb..d316496 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -279,6 +279,8 @@
/* 8974 IDs */
[126] = MSM_CPU_8974,
[184] = MSM_CPU_8974,
+ [185] = MSM_CPU_8974,
+ [186] = MSM_CPU_8974,
/* 8625 IDs */
[127] = MSM_CPU_8625,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 7cd9943..2b674ab 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -308,16 +308,28 @@
static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
{
+ bool had_gpuaddr = false;
+
if (entry == NULL)
return;
+ /*
+ * Unmap the entry first so that there isn't a period of
+ * time where kgsl doesn't know about the address range
+ * but it is still present in the pagetable. Unmapping will
+ * clear the gpuaddr field, so remember if we had a mapping,
+ * and an rbtree entry for later.
+ */
+ had_gpuaddr = entry->memdesc.gpuaddr != 0;
+ kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
+
spin_lock(&entry->priv->mem_lock);
if (entry->id != 0)
idr_remove(&entry->priv->mem_idr, entry->id);
entry->id = 0;
- if (entry->memdesc.gpuaddr != 0)
+ if (had_gpuaddr)
rb_erase(&entry->node, &entry->priv->mem_rb);
spin_unlock(&entry->priv->mem_lock);
@@ -325,7 +337,6 @@
entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
entry->priv = NULL;
- kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
kgsl_mem_entry_put(entry);
}
@@ -1346,6 +1357,12 @@
"invalid gpuaddr %08x\n", gpuaddr);
return -EINVAL;
}
+ if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+ kgsl_mem_entry_put(entry);
+ return -EBUSY;
+ }
+ entry->memdesc.priv |= KGSL_MEMDESC_FREE_PENDING;
+
trace_kgsl_mem_timestamp_queue(device, entry, context_id,
kgsl_readtimestamp(device, context,
KGSL_TIMESTAMP_RETIRED),
@@ -1445,6 +1462,11 @@
return -EINVAL;
}
+ if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+ kgsl_mem_entry_put(entry);
+ return -EBUSY;
+ }
+
trace_kgsl_mem_free(entry);
kgsl_memfree_hist_set_event(entry->priv->pid,
@@ -1470,6 +1492,12 @@
KGSL_MEM_INFO(dev_priv->device, "invalid id %d\n", param->id);
return -EINVAL;
}
+
+ if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+ kgsl_mem_entry_put(entry);
+ return -EBUSY;
+ }
+
trace_kgsl_mem_free(entry);
kgsl_memfree_hist_set_event(entry->priv->pid,
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index d63aa79..debba18 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -151,6 +151,8 @@
#define KGSL_MEMDESC_GLOBAL BIT(1)
/* The memdesc is frozen during a snapshot */
#define KGSL_MEMDESC_FROZEN BIT(2)
+/* The memdesc is scheduled to be freed on a timestamp */
+#define KGSL_MEMDESC_FREE_PENDING BIT(3)
/* shared memory allocation */
struct kgsl_memdesc {
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index b1960c6..b92ec7f 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -148,12 +148,26 @@
if (ret)
clk_disable_unprepare(drvdata->pclk);
}
+
+ if (ret)
+ goto fail;
+
+ if (drvdata->aclk) {
+ ret = clk_prepare_enable(drvdata->aclk);
+ if (ret) {
+ clk_disable_unprepare(drvdata->clk);
+ clk_disable_unprepare(drvdata->pclk);
+ }
+ }
+
fail:
return ret;
}
static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
{
+ if (drvdata->aclk)
+ clk_disable_unprepare(drvdata->aclk);
if (drvdata->clk)
clk_disable_unprepare(drvdata->clk);
clk_disable_unprepare(drvdata->pclk);
diff --git a/drivers/iommu/msm_iommu_dev-v0.c b/drivers/iommu/msm_iommu_dev-v0.c
index 7ae0b21..059216e 100644
--- a/drivers/iommu/msm_iommu_dev-v0.c
+++ b/drivers/iommu/msm_iommu_dev-v0.c
@@ -129,7 +129,8 @@
}
static int msm_iommu_parse_dt(struct platform_device *pdev,
- struct msm_iommu_drvdata *drvdata)
+ struct msm_iommu_drvdata *drvdata,
+ int *needs_alt_core_clk)
{
#ifdef CONFIG_OF_DEVICE
struct device_node *child;
@@ -169,6 +170,10 @@
pr_err("%s: Missing property label\n", __func__);
return -EINVAL;
}
+
+ *needs_alt_core_clk = of_property_read_bool(pdev->dev.of_node,
+ "qcom,needs-alt-core-clk");
+
drvdata->sec_id = -1;
drvdata->ttbr_split = 0;
#endif
@@ -176,7 +181,8 @@
}
static int __get_clocks(struct platform_device *pdev,
- struct msm_iommu_drvdata *drvdata)
+ struct msm_iommu_drvdata *drvdata,
+ int needs_alt_core_clk)
{
int ret = 0;
@@ -199,6 +205,18 @@
} else {
drvdata->clk = NULL;
}
+
+ if (needs_alt_core_clk) {
+ drvdata->aclk = devm_clk_get(&pdev->dev, "alt_core_clk");
+ if (IS_ERR(drvdata->aclk))
+ return PTR_ERR(drvdata->aclk);
+ }
+
+ if (drvdata->aclk && clk_get_rate(drvdata->aclk) == 0) {
+ ret = clk_round_rate(drvdata->aclk, 1000);
+ clk_set_rate(drvdata->aclk, ret);
+ }
+
return 0;
fail:
return ret;
@@ -206,35 +224,13 @@
static void __put_clocks(struct msm_iommu_drvdata *drvdata)
{
+ if (drvdata->aclk)
+ clk_put(drvdata->aclk);
if (drvdata->clk)
clk_put(drvdata->clk);
clk_put(drvdata->pclk);
}
-static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
-{
- int ret;
-
- ret = clk_prepare_enable(drvdata->pclk);
- if (ret)
- goto fail;
-
- if (drvdata->clk) {
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- clk_disable_unprepare(drvdata->pclk);
- }
-fail:
- return ret;
-}
-
-static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
-{
- if (drvdata->clk)
- clk_disable_unprepare(drvdata->clk);
- clk_disable_unprepare(drvdata->pclk);
-}
-
/*
* Do a basic check of the IOMMU by performing an ATS operation
* on context bank 0.
@@ -326,6 +322,7 @@
struct msm_iommu_drvdata *drvdata;
struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
int ret;
+ int needs_alt_core_clk = 0;
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
@@ -335,7 +332,7 @@
}
if (pdev->dev.of_node) {
- ret = msm_iommu_parse_dt(pdev, drvdata);
+ ret = msm_iommu_parse_dt(pdev, drvdata, &needs_alt_core_clk);
if (ret)
goto fail;
} else if (pdev->dev.platform_data) {
@@ -382,12 +379,12 @@
drvdata->dev = &pdev->dev;
- ret = __get_clocks(pdev, drvdata);
+ ret = __get_clocks(pdev, drvdata, needs_alt_core_clk);
if (ret)
goto fail;
- __enable_clocks(drvdata);
+ iommu_access_ops_v0.iommu_clk_on(drvdata);
msm_iommu_reset(drvdata->base, drvdata->glb_base, drvdata->ncb);
@@ -401,7 +398,7 @@
msm_iommu_add_drv(drvdata);
platform_set_drvdata(pdev, drvdata);
- __disable_clocks(drvdata);
+ iommu_access_ops_v0.iommu_clk_off(drvdata);
pmon_info = msm_iommu_pm_alloc(&pdev->dev);
if (pmon_info != NULL) {
@@ -430,7 +427,7 @@
return 0;
fail_clk:
- __disable_clocks(drvdata);
+ iommu_access_ops_v0.iommu_clk_off(drvdata);
__put_clocks(drvdata);
fail:
return ret;
@@ -618,9 +615,9 @@
goto fail;
}
- __enable_clocks(drvdata);
+ iommu_access_ops_v0.iommu_clk_on(drvdata);
__program_m2v_tables(drvdata, ctx_drvdata);
- __disable_clocks(drvdata);
+ iommu_access_ops_v0.iommu_clk_off(drvdata);
dev_info(&pdev->dev, "context %s using bank %d\n", ctx_drvdata->name,
ctx_drvdata->num);
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 7fc8810..82a4f3c 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -316,6 +316,9 @@
case HAL_EXTRADATA_ASPECT_RATIO:
ret = HFI_PROPERTY_PARAM_INDEX_EXTRADATA;
break;
+ case HAL_EXTRADATA_MPEG2_SEQDISP:
+ ret = HFI_PROPERTY_PARAM_VDEC_MPEG2_SEQDISP_EXTRADATA;
+ break;
default:
dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
break;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index bf646a2..511a478 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -66,6 +66,7 @@
"Extradata input crop",
"Extradata digital zoom",
"Extradata aspect ratio",
+ "Extradata mpeg2 seqdisp",
};
static struct msm_vidc_ctrl msm_vdec_ctrls[] = {
@@ -203,7 +204,7 @@
.name = "Extradata Type",
.type = V4L2_CTRL_TYPE_MENU,
.minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
- .maximum = V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO,
+ .maximum = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP,
.default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
.menu_skip_mask = ~(
(1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
@@ -223,7 +224,8 @@
(1 << V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER) |
(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_INPUT_CROP) |
(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_DIGITAL_ZOOM) |
- (1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO)
+ (1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP)
),
.qmenu = mpeg_video_vidc_extradata,
.step = 0,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 4fc7518..17f4590 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -2276,6 +2276,9 @@
case V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO:
ret = HAL_EXTRADATA_ASPECT_RATIO;
break;
+ case V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP:
+ ret = HAL_EXTRADATA_MPEG2_SEQDISP;
+ break;
default:
dprintk(VIDC_WARN, "Extradata not found: %d\n", index);
break;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 1311752..bb72da7 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -75,7 +75,8 @@
#define HFI_EXTRADATA_PANSCAN_WINDOW 0x00000008
#define HFI_EXTRADATA_RECOVERY_POINT_SEI 0x00000009
#define HFI_EXTRADATA_CLOSED_CAPTION_UD 0x0000000A
-#define HFI_EXTRADATA_AFD_UD 0x0000000B
+#define HFI_EXTRADATA_AFD_UD 0x0000000B
+#define HFI_EXTRADATA_MPEG2_SEQDISP 0x0000000D
#define HFI_EXTRADATA_MULTISLICE_INFO 0x7F100000
#define HFI_EXTRADATA_NUM_CONCEALED_MB 0x7F100001
#define HFI_EXTRADATA_INDEX 0x7F100002
@@ -191,6 +192,8 @@
(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x014)
#define HFI_PROPERTY_PARAM_VDEC_AVC_SESSION_SELECT \
(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x015)
+#define HFI_PROPERTY_PARAM_VDEC_MPEG2_SEQDISP_EXTRADATA \
+ (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x016)
#define HFI_PROPERTY_CONFIG_VDEC_OX_START \
(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x0000)
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 6672d7b..bf1c70b 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -95,6 +95,7 @@
HAL_EXTRADATA_NUM_CONCEALED_MB,
HAL_EXTRADATA_METADATA_FILLER,
HAL_EXTRADATA_ASPECT_RATIO,
+ HAL_EXTRADATA_MPEG2_SEQDISP
};
enum hal_property {
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e12b9b4..c8fdc6b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1384,17 +1384,17 @@
* The result is saved with the response so that
* the ufs_core layer will handle it.
*/
- result |= DID_OK << 16;
+ result = DID_OK << 16;
ufshcd_copy_query_response(hba, lrbp);
break;
case UPIU_TRANSACTION_REJECT_UPIU:
/* TODO: handle Reject UPIU Response */
- result |= DID_ERROR << 16;
+ result = DID_ERROR << 16;
dev_err(hba->dev,
"Reject UPIU not fully implemented\n");
break;
default:
- result |= DID_ERROR << 16;
+ result = DID_ERROR << 16;
dev_err(hba->dev,
"Unexpected request response code = %x\n",
result);
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index b89f608..c5aa7e5 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -2280,7 +2280,7 @@
bam_props.phys_addr = dd->bam.phys_addr;
bam_props.virt_addr = dd->bam.base;
bam_props.irq = dd->bam.irq;
- bam_props.manage = SPS_BAM_MGR_LOCAL;
+ bam_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
bam_props.summing_threshold = 0x10;
rc = sps_register_bam_device(&bam_props, &bam_handle);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 991cf2e..f01a078 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -199,8 +199,8 @@
#define TSENS0_8X10_POINT1_SHIFT 16
#define TSENS0_8X10_POINT2_SHIFT 22
#define TSENS1_8X10_POINT2_SHIFT 6
-#define TSENS_8X10_BASE0_MASK 0xf
-#define TSENS_8X10_BASE1_MASK 0xf0
+#define TSENS_8X10_BASE0_MASK 0xff
+#define TSENS_8X10_BASE1_MASK 0xff00
#define TSENS0_8X10_POINT1_MASK 0x3f0000
#define TSENS0_8X10_POINT2_MASK 0xfc00000
#define TSENS_8X10_TSENS_CAL_SEL 0x70000000
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index f672bd4..290e317 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -32,6 +32,8 @@
#include <linux/spinlock.h>
#include <linux/semaphore.h>
#include <linux/uaccess.h>
+#include <linux/file.h>
+#include <linux/msm_kgsl.h>
#include <mach/board.h>
#include <mach/clk.h>
@@ -125,7 +127,7 @@
pr_debug("mdp3_irq_handler irq=%d\n", mdp_interrupt);
spin_lock(&mdata->irq_lock);
- mdp_interrupt &= mdata->irqMask;
+ mdp_interrupt &= mdata->irq_mask;
while (mdp_interrupt && i < MDP3_MAX_INTR) {
if ((mdp_interrupt & 0x1) && mdata->callbacks[i].cb)
@@ -145,14 +147,15 @@
pr_debug("mdp3_irq_enable type=%d\n", type);
spin_lock_irqsave(&mdp3_res->irq_lock, flag);
- if (mdp3_res->irqMask & BIT(type)) {
+ mdp3_res->irq_ref_count[type] += 1;
+ if (mdp3_res->irq_ref_count[type] > 1) {
pr_debug("interrupt %d already enabled\n", type);
spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
return;
}
- irqEnabled = mdp3_res->irqMask;
- mdp3_res->irqMask |= BIT(type);
- MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
+ irqEnabled = mdp3_res->irq_mask;
+ mdp3_res->irq_mask |= BIT(type);
+ MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
if (!irqEnabled)
enable_irq(mdp3_res->irq);
spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
@@ -163,26 +166,33 @@
unsigned long flag;
spin_lock_irqsave(&mdp3_res->irq_lock, flag);
- if (mdp3_res->irqMask & BIT(type)) {
- mdp3_res->irqMask &= ~BIT(type);
- MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
- if (!mdp3_res->irqMask)
- disable_irq(mdp3_res->irq);
- } else {
+ if (mdp3_res->irq_ref_count[type] <= 0) {
pr_debug("interrupt %d not enabled\n", type);
+ spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+ return;
+ }
+ mdp3_res->irq_ref_count[type] -= 1;
+ if (mdp3_res->irq_ref_count[type] == 0) {
+ mdp3_res->irq_mask &= ~BIT(type);
+ MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
+ if (!mdp3_res->irq_mask)
+ disable_irq(mdp3_res->irq);
}
spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
}
void mdp3_irq_disable_nosync(int type)
{
- if (mdp3_res->irqMask & BIT(type)) {
- mdp3_res->irqMask &= ~BIT(type);
- MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
- if (!mdp3_res->irqMask)
- disable_irq_nosync(mdp3_res->irq);
- } else {
+ if (mdp3_res->irq_ref_count[type] <= 0) {
pr_debug("interrupt %d not enabled\n", type);
+ return;
+ }
+ mdp3_res->irq_ref_count[type] -= 1;
+ if (mdp3_res->irq_ref_count[type] == 0) {
+ mdp3_res->irq_mask &= ~BIT(type);
+ MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
+ if (!mdp3_res->irq_mask)
+ disable_irq_nosync(mdp3_res->irq);
}
}
@@ -688,6 +698,108 @@
return 0;
}
+int mdp3_put_img(struct mdp3_img_data *data)
+{
+ struct ion_client *iclient = mdp3_res->ion_client;
+ int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+ if (!data->srcp_file) {
+ pr_debug("No img to put\n");
+ return 0;
+ }
+ if (data->flags & MDP_BLIT_SRC_GEM) {
+ pr_debug("memory source MDP_BLIT_SRC_GEM\n");
+ } else if (data->flags & MDP_MEMORY_ID_TYPE_FB) {
+ pr_debug("fb mem buf=0x%x\n", data->addr);
+ fput_light(data->srcp_file, data->p_need);
+ data->srcp_file = NULL;
+ } else {
+ ion_unmap_iommu(iclient, data->srcp_ihdl, dom, 0);
+ ion_free(iclient, data->srcp_ihdl);
+ data->srcp_ihdl = NULL;
+ }
+ return 0;
+}
+
+int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data)
+{
+ struct file *file;
+ int ret = -EINVAL;
+ int fb_num;
+ unsigned long *start, *len;
+ struct ion_client *iclient = mdp3_res->ion_client;
+ int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+ start = (unsigned long *) &data->addr;
+ len = (unsigned long *) &data->len;
+ data->flags |= img->flags;
+ data->p_need = 0;
+
+ if (img->flags & MDP_BLIT_SRC_GEM) {
+ data->srcp_file = NULL;
+ ret = kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
+ &data->addr, &data->len);
+ if (!ret)
+ goto done;
+ }
+ if (img->flags & MDP_MEMORY_ID_TYPE_FB) {
+ file = fget_light(img->memory_id, &data->p_need);
+ if (file == NULL) {
+ pr_err("invalid framebuffer file (%d)\n",
+ img->memory_id);
+ return -EINVAL;
+ }
+ if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+ fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
+ ret = mdss_fb_get_phys_info(start, len, fb_num);
+ if (ret) {
+ pr_err("mdss_fb_get_phys_info() failed\n");
+ fput_light(file, data->p_need);
+ file = NULL;
+ }
+ } else {
+ pr_err("invalid FB_MAJOR\n");
+ fput_light(file, data->p_need);
+ file = NULL;
+ ret = -EINVAL;
+ }
+ data->srcp_file = file;
+ if (!ret)
+ goto done;
+ }
+ if (iclient) {
+ data->srcp_ihdl = ion_import_dma_buf(iclient, img->memory_id);
+ if (IS_ERR_OR_NULL(data->srcp_ihdl)) {
+ pr_err("error on ion_import_fd\n");
+ ret = PTR_ERR(data->srcp_ihdl);
+ data->srcp_ihdl = NULL;
+ return ret;
+ }
+
+ ret = ion_map_iommu(iclient, data->srcp_ihdl, dom,
+ 0, SZ_4K, 0, start, len, 0, 0);
+
+ if (IS_ERR_VALUE(ret)) {
+ ion_free(iclient, data->srcp_ihdl);
+ pr_err("failed to map ion handle (%d)\n", ret);
+ return ret;
+ }
+ }
+done:
+ if (!ret && (img->offset < data->len)) {
+ data->addr += img->offset;
+ data->len -= img->offset;
+
+ pr_debug("mem=%d ihdl=%p buf=0x%x len=0x%x\n", img->memory_id,
+ data->srcp_ihdl, data->addr, data->len);
+ } else {
+ mdp3_put_img(data);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
static int mdp3_init(struct msm_fb_data_type *mfd)
{
return mdp3_ctrl_init(mfd);
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 5774e5a..7e395e1 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -23,6 +23,7 @@
#include <mach/iommu_domains.h>
#include "mdp3_dma.h"
+#include "mdss_fb.h"
enum {
MDP3_CLK_AHB,
@@ -100,12 +101,22 @@
struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
spinlock_t irq_lock;
- u32 irqMask;
+ u32 irq_ref_count[MDP3_MAX_INTR];
+ u32 irq_mask;
struct mdp3_intr_cb callbacks[MDP3_MAX_INTR];
struct early_suspend suspend_handler;
};
+struct mdp3_img_data {
+ u32 addr;
+ u32 len;
+ u32 flags;
+ int p_need;
+ struct file *srcp_file;
+ struct ion_handle *srcp_ihdl;
+};
+
extern struct mdp3_hw_resource *mdp3_res;
struct mdp3_dma *mdp3_get_dma_pipe(int capability);
@@ -117,6 +128,8 @@
int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate);
int mdp3_clk_enable(int enable);
int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
+int mdp3_put_img(struct mdp3_img_data *data);
+int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data);
#define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
#define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 929e5f8..f5ac5e9 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -26,37 +26,108 @@
#define MDP_VSYNC_CLK_RATE 19200000
#define VSYNC_PERIOD 16
+static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd);
+
+static void mdp3_bufq_init(struct mdp3_buffer_queue *bufq)
+{
+ bufq->count = 0;
+ bufq->push_idx = 0;
+ bufq->pop_idx = 0;
+}
+
+static void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq)
+{
+ int count = bufq->count;
+
+ if (!count)
+ return;
+
+ while (count--) {
+ struct mdp3_img_data *data = &bufq->img_data[bufq->pop_idx];
+ bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
+ mdp3_put_img(data);
+ }
+ bufq->count = 0;
+ bufq->push_idx = 0;
+ bufq->pop_idx = 0;
+}
+
+static int mdp3_bufq_push(struct mdp3_buffer_queue *bufq,
+ struct mdp3_img_data *data)
+{
+ if (bufq->count >= MDP3_MAX_BUF_QUEUE) {
+ pr_err("bufq full\n");
+ return -EPERM;
+ }
+
+ bufq->img_data[bufq->push_idx] = *data;
+ bufq->push_idx = (bufq->push_idx + 1) % MDP3_MAX_BUF_QUEUE;
+ bufq->count++;
+ return 0;
+}
+
+static struct mdp3_img_data *mdp3_bufq_pop(struct mdp3_buffer_queue *bufq)
+{
+ struct mdp3_img_data *data;
+ if (bufq->count == 0)
+ return NULL;
+
+ data = &bufq->img_data[bufq->pop_idx];
+ bufq->count--;
+ bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
+ return data;
+}
+
+static int mdp3_bufq_count(struct mdp3_buffer_queue *bufq)
+{
+ return bufq->count;
+}
+
void vsync_notify_handler(void *arg)
{
struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
+ spin_lock(&session->vsync_lock);
+ session->vsync_time = ktime_get();
complete(&session->vsync_comp);
+ spin_unlock(&session->vsync_lock);
}
static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
{
struct mdp3_session_data *mdp3_session;
struct mdp3_vsync_notification vsync_client;
+ struct mdp3_vsync_notification *arg = NULL;
+ unsigned long flag;
+ pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
!mdp3_session->intf)
return -ENODEV;
- vsync_client.handler = vsync_notify_handler;
- vsync_client.arg = mdp3_session;
-
- mutex_lock(&mdp3_session->lock);
if (!mdp3_session->status) {
pr_debug("fb%d is not on yet", mfd->index);
- mutex_unlock(&mdp3_session->lock);
return -EINVAL;
}
+ if (enable) {
+ vsync_client.handler = vsync_notify_handler;
+ vsync_client.arg = mdp3_session;
+ arg = &vsync_client;
+ }
- mdp3_session->dma->vsync_enable(mdp3_session->dma, &vsync_client);
+ mutex_lock(&mdp3_session->lock);
+ mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
mutex_unlock(&mdp3_session->lock);
+ spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
+ if (enable)
+ INIT_COMPLETION(mdp3_session->vsync_comp);
+ else
+ complete_all(&mdp3_session->vsync_comp);
+ spin_unlock_irqrestore(&mdp3_session->vsync_lock, flag);
return 0;
}
+
static ssize_t mdp3_vsync_show_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -64,8 +135,8 @@
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
struct mdp3_session_data *mdp3_session = NULL;
u64 vsync_ticks;
- ktime_t vsync_time;
int rc;
+ unsigned long flag;
if (!mfd || !mfd->mdp.private1)
return 0;
@@ -78,11 +149,11 @@
if (rc <= 0) {
pr_warn("vsync wait on fb%d interrupted (%d)\n",
mfd->index, rc);
- return -EBUSY;
}
- vsync_time = mdp3_session->dma->get_vsync_time(mdp3_session->dma);
- vsync_ticks = ktime_to_ns(vsync_time);
+ spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
+ vsync_ticks = ktime_to_ns(mdp3_session->vsync_time);
+ spin_unlock_irqrestore(&mdp3_session->vsync_lock, flag);
pr_debug("fb%d vsync=%llu", mfd->index, vsync_ticks);
rc = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_ticks);
@@ -395,6 +466,148 @@
return 0;
}
+static int mdp3_overlay_get(struct msm_fb_data_type *mfd,
+ struct mdp_overlay *req)
+{
+ int rc = 0;
+ struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+
+ mutex_lock(&mdp3_session->lock);
+
+ if (mdp3_session->overlay.id == req->id)
+ *req = mdp3_session->overlay;
+ else
+ rc = -EINVAL;
+
+ mutex_unlock(&mdp3_session->lock);
+
+ return rc;
+}
+
+static int mdp3_overlay_set(struct msm_fb_data_type *mfd,
+ struct mdp_overlay *req)
+{
+ int rc = 0;
+ struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+
+ mutex_lock(&mdp3_session->lock);
+
+ if (mdp3_session->overlay.id == req->id) {
+ mdp3_session->overlay = *req;
+ if (req->id == MSMFB_NEW_REQUEST) {
+ mdp3_session->overlay.id = 1;
+ req->id = 1;
+ }
+ } else {
+ rc = -EINVAL;
+ }
+ mutex_unlock(&mdp3_session->lock);
+
+ return rc;
+}
+
+static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx)
+{
+ int rc = 0;
+ struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+
+ mdp3_ctrl_pan_display(mfd);
+
+ mutex_lock(&mdp3_session->lock);
+
+ if (mdp3_session->overlay.id == ndx && ndx == 1) {
+ mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
+ mdp3_bufq_deinit(&mdp3_session->bufq_in);
+ mdp3_bufq_deinit(&mdp3_session->bufq_out);
+ } else {
+ rc = -EINVAL;
+ }
+
+ mutex_unlock(&mdp3_session->lock);
+
+ return rc;
+}
+
+static int mdp3_overlay_queue_buffer(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_data *req)
+{
+ int rc;
+ struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+ struct msmfb_data *img = &req->data;
+ struct mdp3_img_data data;
+
+ rc = mdp3_get_img(img, &data);
+ if (rc) {
+ pr_err("fail to get overlay buffer\n");
+ return rc;
+ }
+
+ rc = mdp3_bufq_push(&mdp3_session->bufq_in, &data);
+ if (rc) {
+ pr_err("fail to queue the overlay buffer, buffer drop\n");
+ mdp3_put_img(&data);
+ return rc;
+ }
+ return 0;
+}
+
+static int mdp3_overlay_play(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_data *req)
+{
+ struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+ int rc = 0;
+
+ pr_debug("mdp3_overlay_play req id=%x mem_id=%d\n",
+ req->id, req->data.memory_id);
+
+ mutex_lock(&mdp3_session->lock);
+
+ if (mfd->panel_power_on)
+ rc = mdp3_overlay_queue_buffer(mfd, req);
+ else
+ rc = -EPERM;
+
+ mutex_unlock(&mdp3_session->lock);
+
+ return rc;
+}
+
+static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd)
+{
+ struct mdp3_session_data *mdp3_session;
+ struct mdp3_img_data *data;
+ int rc = 0;
+
+ if (!mfd || !mfd->mdp.private1)
+ return -EINVAL;
+
+ mdp3_session = mfd->mdp.private1;
+ if (!mdp3_session || !mdp3_session->dma)
+ return -EINVAL;
+
+ if (!mdp3_session->status) {
+ pr_err("%s, display off!\n", __func__);
+ return -EPERM;
+ }
+
+ mutex_lock(&mdp3_session->lock);
+
+ data = mdp3_bufq_pop(&mdp3_session->bufq_in);
+ if (data) {
+ mdp3_session->dma->update(mdp3_session->dma,
+ (void *)data->addr);
+ mdp3_bufq_push(&mdp3_session->bufq_out, data);
+ }
+
+ if (mdp3_bufq_count(&mdp3_session->bufq_out) > 1) {
+ data = mdp3_bufq_pop(&mdp3_session->bufq_out);
+ mdp3_put_img(data);
+ }
+
+ mutex_unlock(&mdp3_session->lock);
+ return rc;
+}
+
static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
{
struct fb_info *fbi;
@@ -445,6 +658,9 @@
break;
case metadata_op_get_caps:
metadata->data.caps.mdp_rev = 304;
+ metadata->data.caps.rgb_pipes = 0;
+ metadata->data.caps.vig_pipes = 0;
+ metadata->data.caps.dma_pipes = 1;
break;
default:
pr_warn("Unsupported request to MDP META IOCTL.\n");
@@ -460,6 +676,8 @@
int rc = -EINVAL;
struct mdp3_session_data *mdp3_session;
struct msmfb_metadata metadata;
+ struct mdp_overlay req;
+ struct msmfb_overlay_data ov_data;
int val;
pr_debug("mdp3_ctrl_ioctl_handler\n");
@@ -478,8 +696,6 @@
case MSMFB_OVERLAY_VSYNC_CTRL:
if (!copy_from_user(&val, argp, sizeof(val))) {
rc = mdp3_ctrl_vsync_enable(mfd, val);
- if (!val)
- init_completion(&mdp3_session->vsync_comp);
} else {
pr_err("MSMFB_OVERLAY_VSYNC_CTRL failed\n");
rc = -EFAULT;
@@ -493,10 +709,42 @@
if (!rc)
rc = copy_to_user(argp, &metadata, sizeof(metadata));
break;
+ case MSMFB_OVERLAY_GET:
+ rc = copy_from_user(&req, argp, sizeof(req));
+ if (!rc) {
+ rc = mdp3_overlay_get(mfd, &req);
+
+ if (!IS_ERR_VALUE(rc))
+ rc = copy_to_user(argp, &req, sizeof(req));
+ }
+ if (rc)
+ pr_err("OVERLAY_GET failed (%d)\n", rc);
+ break;
+ case MSMFB_OVERLAY_SET:
+ rc = copy_from_user(&req, argp, sizeof(req));
+ if (!rc) {
+ rc = mdp3_overlay_set(mfd, &req);
+
+ if (!IS_ERR_VALUE(rc))
+ rc = copy_to_user(argp, &req, sizeof(req));
+ }
+ if (rc)
+ pr_err("OVERLAY_SET failed (%d)\n", rc);
+ break;
+ case MSMFB_OVERLAY_UNSET:
+ if (!IS_ERR_VALUE(copy_from_user(&val, argp, sizeof(val))))
+ rc = mdp3_overlay_unset(mfd, val);
+ break;
+ case MSMFB_OVERLAY_PLAY:
+ rc = copy_from_user(&ov_data, argp, sizeof(ov_data));
+ if (!rc)
+ rc = mdp3_overlay_play(mfd, &ov_data);
+ if (rc)
+ pr_err("OVERLAY_PLAY failed (%d)\n", rc);
+ break;
default:
break;
}
-
return rc;
}
@@ -515,7 +763,7 @@
mdp3_interface->cursor_update = NULL;
mdp3_interface->dma_fnc = mdp3_ctrl_pan_display;
mdp3_interface->ioctl_handler = mdp3_ctrl_ioctl_handler;
- mdp3_interface->kickoff_fnc = NULL;
+ mdp3_interface->kickoff_fnc = mdp3_ctrl_display_commit_kickoff;
mdp3_session = kmalloc(sizeof(struct mdp3_session_data), GFP_KERNEL);
if (!mdp3_session) {
@@ -525,6 +773,7 @@
memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
mutex_init(&mdp3_session->lock);
init_completion(&mdp3_session->vsync_comp);
+ spin_lock_init(&mdp3_session->vsync_lock);
mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
if (!mdp3_session->dma) {
rc = -ENODEV;
@@ -540,6 +789,9 @@
mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev);
mdp3_session->status = 0;
+ mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
+ mdp3_bufq_init(&mdp3_session->bufq_in);
+ mdp3_bufq_init(&mdp3_session->bufq_out);
mfd->mdp.private1 = mdp3_session;
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index d42ece7..fb3bd36 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -18,10 +18,20 @@
#include <linux/mutex.h>
#include <linux/completion.h>
+#include "mdp3.h"
#include "mdp3_dma.h"
#include "mdss_fb.h"
#include "mdss_panel.h"
+#define MDP3_MAX_BUF_QUEUE 8
+
+struct mdp3_buffer_queue {
+ struct mdp3_img_data img_data[MDP3_MAX_BUF_QUEUE];
+ int count;
+ int push_idx;
+ int pop_idx;
+};
+
struct mdp3_session_data {
struct mutex lock;
int status;
@@ -29,7 +39,12 @@
struct mdss_panel_data *panel;
struct mdp3_intf *intf;
struct msm_fb_data_type *mfd;
+ ktime_t vsync_time;
+ spinlock_t vsync_lock;
struct completion vsync_comp;
+ struct mdp_overlay overlay;
+ struct mdp3_buffer_queue bufq_in;
+ struct mdp3_buffer_queue bufq_out;
};
int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 69e3d7e..a09f503 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -20,17 +20,6 @@
#define DMA_STOP_POLL_SLEEP_US 1000
#define DMA_STOP_POLL_TIMEOUT_US 16000
-static ktime_t mdp3_get_vsync_time(struct mdp3_dma *dma)
-{
- unsigned long flag;
- ktime_t time;
-
- spin_lock_irqsave(&dma->dma_lock, flag);
- time = dma->vsync_time;
- spin_unlock_irqrestore(&dma->dma_lock, flag);
- return time;
-}
-
static void mdp3_vsync_intr_handler(int type, void *arg)
{
struct mdp3_dma *dma = (struct mdp3_dma *)arg;
@@ -41,13 +30,11 @@
vsync_client = dma->vsync_client;
if (!vsync_client.handler)
dma->cb_type &= ~MDP3_DMA_CALLBACK_TYPE_VSYNC;
- dma->vsync_time = ktime_get();
complete(&dma->vsync_comp);
+ spin_unlock(&dma->dma_lock);
if (vsync_client.handler)
vsync_client.handler(vsync_client.arg);
- spin_unlock(&dma->dma_lock);
-
- if (!vsync_client.handler)
+ else
mdp3_irq_disable_nosync(type);
}
@@ -186,7 +173,7 @@
updated = 1;
}
} else {
- if (!dma->vsync_client.handler) {
+ if (dma->vsync_client.handler) {
dma->vsync_client.handler = NULL;
dma->vsync_client.arg = NULL;
updated = 1;
@@ -696,7 +683,6 @@
dma->histo_intr_enable = mdp3_dmap_histo_intr_enable;
dma->histo_intr_clear = mdp3_dmap_histo_intr_clear;
dma->vsync_enable = mdp3_dma_vsync_enable;
- dma->get_vsync_time = mdp3_get_vsync_time;
dma->start = mdp3_dma_start;
dma->stop = mdp3_dma_stop;
break;
@@ -717,7 +703,6 @@
dma->histo_intr_enable = NULL;
dma->histo_intr_clear = NULL;
dma->vsync_enable = mdp3_dma_vsync_enable;
- dma->get_vsync_time = mdp3_get_vsync_time;
dma->start = mdp3_dma_start;
dma->stop = mdp3_dma_stop;
break;
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 2fb8427..cef749b 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -231,7 +231,6 @@
spinlock_t dma_lock;
struct completion vsync_comp;
struct completion dma_comp;
- ktime_t vsync_time;
struct mdp3_vsync_notification vsync_client;
u32 cb_type;
@@ -275,9 +274,6 @@
void (*vsync_enable)(struct mdp3_dma *dma,
struct mdp3_vsync_notification *vsync_client);
-
- ktime_t (*get_vsync_time)(struct mdp3_dma *dma);
-
};
struct mdp3_video_intf_cfg {
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index ef8323e..26d4ada 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1839,6 +1839,7 @@
V4L2_MPEG_VIDC_INDEX_EXTRADATA_INPUT_CROP,
V4L2_MPEG_VIDC_INDEX_EXTRADATA_DIGITAL_ZOOM,
V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO,
+ V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP
};
#define V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO \
(V4L2_CID_MPEG_MSM_VIDC_BASE + 23)
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index f632ad6..2164275 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -73,6 +73,16 @@
unsigned int aspect_height;
};
+struct msm_vidc_mpeg2_seqdisp_payload {
+ unsigned int video_format;
+ bool color_descp;
+ unsigned int color_primaries;
+ unsigned int transfer_char;
+ unsigned int matrix_coeffs;
+ unsigned int disp_width;
+ unsigned int disp_height;
+};
+
struct msm_vidc_panscan_window {
unsigned int panscan_height_offset;
unsigned int panscan_width_offset;
@@ -94,6 +104,7 @@
EXTRADATA_FRAME_RATE = 0x00000007,
EXTRADATA_PANSCAN_WINDOW = 0x00000008,
EXTRADATA_RECOVERY_POINT_SEI = 0x00000009,
+ EXTRADATA_MPEG2_SEQDISP = 0x0000000D,
EXTRADATA_MULTISLICE_INFO = 0x7F100000,
EXTRADATA_NUM_CONCEALED_MB = 0x7F100001,
EXTRADATA_INDEX = 0x7F100002,
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 0dd14e6..2d34d70 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -70,7 +70,6 @@
#define COMPRESSED_IO 0x0040
#define NT_MODE 0x0400
-
#define NO_TIMESTAMP 0xFF00
#define SET_TIMESTAMP 0x0000
@@ -79,6 +78,19 @@
#define SESSION_MAX 0x08
+/* payload structure bytes */
+#define READDONE_IDX_STATUS 0
+#define READDONE_IDX_BUFADD_LSW 1
+#define READDONE_IDX_BUFADD_MSW 2
+#define READDONE_IDX_MEMMAP_HDL 3
+#define READDONE_IDX_SIZE 4
+#define READDONE_IDX_OFFSET 5
+#define READDONE_IDX_LSW_TS 6
+#define READDONE_IDX_MSW_TS 7
+#define READDONE_IDX_FLAGS 8
+#define READDONE_IDX_NUMFRAMES 9
+#define READDONE_IDX_SEQ_ID 10
+
#define SOFT_PAUSE_PERIOD 30 /* ramp up/down for 30ms */
#define SOFT_PAUSE_STEP 2000 /* Step value 2ms or 2000us */
enum {
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index b140b5b..c3967dc 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2336,6 +2336,9 @@
{
int ret;
+ /* Set GPIO headset detection by default */
+ hs_detect_use_gpio = true;
+
if (!cpu_is_msm9615()) {
pr_err("%s: Not the right machine type\n", __func__);
return -ENODEV ;
@@ -2413,8 +2416,6 @@
sif_virt_addr = ioremap(LPASS_SIF_MUX_ADDR, 4);
secpcm_portslc_virt_addr = ioremap(SEC_PCM_PORT_SLC_ADDR, 4);
- hs_detect_use_gpio = true;
-
return ret;
}
module_init(mdm9615_audio_init);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 9359ed7..9dbbf20 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -39,7 +39,10 @@
#define COMPRE_CAPTURE_NUM_PERIODS 16
/* Allocate the worst case frame size for compressed audio */
#define COMPRE_CAPTURE_HEADER_SIZE (sizeof(struct snd_compr_audio_info))
-#define COMPRE_CAPTURE_MAX_FRAME_SIZE (6144)
+/* Changing period size to 4032. 4032 will make sure COMPRE_CAPTURE_PERIOD_SIZE
+ * is 4096 with meta data size of 64 and MAX_NUM_FRAMES_PER_BUFFER 1
+ */
+#define COMPRE_CAPTURE_MAX_FRAME_SIZE (4032)
#define COMPRE_CAPTURE_PERIOD_SIZE ((COMPRE_CAPTURE_MAX_FRAME_SIZE + \
COMPRE_CAPTURE_HEADER_SIZE) * \
MAX_NUM_FRAMES_PER_BUFFER)
@@ -226,7 +229,7 @@
prtd->pcm_irq_pos);
memcpy(prtd->audio_client->port[OUT].buf->data +
- prtd->pcm_irq_pos, (ptrmem + 2),
+ prtd->pcm_irq_pos, (ptrmem + READDONE_IDX_SIZE),
COMPRE_CAPTURE_HEADER_SIZE);
pr_debug("buf = %p, updated data = 0x%X, *data = %p\n",
prtd->audio_client->port[OUT].buf,
@@ -235,9 +238,10 @@
prtd->audio_client->port[OUT].buf->data);
if (!atomic_read(&prtd->start))
break;
- pr_debug("frame size=%d, buffer = 0x%X\n", ptrmem[2],
- ptrmem[1]);
- if (ptrmem[2] > COMPRE_CAPTURE_MAX_FRAME_SIZE) {
+ pr_debug("frame size=%d, buffer = 0x%X\n",
+ ptrmem[READDONE_IDX_SIZE],
+ ptrmem[READDONE_IDX_BUFADD_LSW]);
+ if (ptrmem[READDONE_IDX_SIZE] > COMPRE_CAPTURE_MAX_FRAME_SIZE) {
pr_err("Frame length exceeded the max length");
break;
}
@@ -546,7 +550,7 @@
{
pr_debug("%s\n", __func__);
/* MP3 Block */
- compr->info.compr_cap.num_codecs = 4;
+ compr->info.compr_cap.num_codecs = 5;
compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
@@ -555,6 +559,7 @@
compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
+ compr->info.compr_cap.codecs[4] = SND_AUDIOCODEC_AMRWB;
/* Add new codecs here */
}
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 59d4de2..af8e873 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -45,17 +45,6 @@
#define TRUE 0x01
#define FALSE 0x00
-#define READDONE_IDX_STATUS 0
-#define READDONE_IDX_BUFADD_LSW 1
-#define READDONE_IDX_BUFADD_MSW 2
-#define READDONE_IDX_MEMMAP_HDL 3
-#define READDONE_IDX_SIZE 4
-#define READDONE_IDX_OFFSET 5
-#define READDONE_IDX_LSW_TS 6
-#define READDONE_IDX_MSW_TS 7
-#define READDONE_IDX_FLAGS 8
-#define READDONE_IDX_NUMFRAMES 9
-#define READDONE_IDX_SEQ_ID 10
/* TODO, combine them together */
static DEFINE_MUTEX(session_lock);
@@ -3371,6 +3360,7 @@
struct list_head *ptr, *next;
u32 lbuf_addr_lsw;
u32 liomode;
+ u32 io_compressed;
if (!ac || ac->apr == NULL) {
pr_err("%s: APR handle NULL\n", __func__);
@@ -3387,12 +3377,15 @@
read.buf_size = param->len;
read.seq_id = param->uid;
liomode = (NT_MODE | ASYNC_IO_MODE);
+ io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
if (ac->io_mode == liomode)
lbuf_addr_lsw = (read.buf_addr_lsw - 32);
+ else if (ac->io_mode == io_compressed)
+ lbuf_addr_lsw = (read.buf_addr_lsw - 64);
else
lbuf_addr_lsw = read.buf_addr_lsw;
- list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) {
+ list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
buf_node = list_entry(ptr, struct asm_buffer_node, list);
if (buf_node->buf_addr_lsw == lbuf_addr_lsw) {
read.mem_map_handle = buf_node->mmap_hdl;