Merge "ehci: hsic: add suspend/resume handshake with ipa resource manager"
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
new file mode 100644
index 0000000..6508329
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -0,0 +1,78 @@
+* ARM CPUs binding description
+
+The device tree allows to describe the layout of CPUs in a system through
+the "cpus" node, which in turn contains a number of subnodes (ie "cpu")
+defining properties for every cpu.
+
+Bindings for CPU nodes follow the ePAPR standard, available from:
+
+http://devicetree.org
+
+For the ARM architecture every CPU node must contain the following properties:
+
+- device_type: must be "cpu"
+- reg: property matching the CPU MPIDR[23:0] register bits
+ reg[31:24] bits must be set to 0
+- compatible: should be one of:
+ "arm,arm1020"
+ "arm,arm1020e"
+ "arm,arm1022"
+ "arm,arm1026"
+ "arm,arm720"
+ "arm,arm740"
+ "arm,arm7tdmi"
+ "arm,arm920"
+ "arm,arm922"
+ "arm,arm925"
+ "arm,arm926"
+ "arm,arm940"
+ "arm,arm946"
+ "arm,arm9tdmi"
+ "arm,cortex-a5"
+ "arm,cortex-a7"
+ "arm,cortex-a8"
+ "arm,cortex-a9"
+ "arm,cortex-a15"
+ "arm,arm1136"
+ "arm,arm1156"
+ "arm,arm1176"
+ "arm,arm11mpcore"
+ "faraday,fa526"
+ "intel,sa110"
+ "intel,sa1100"
+ "marvell,feroceon"
+ "marvell,mohawk"
+ "marvell,xsc3"
+ "marvell,xscale"
+ "qcom,krait"
+
+Example:
+
+ cpus {
+ #size-cells = <0>;
+ #address-cells = <1>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <0x0>;
+ };
+
+ CPU1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <0x1>;
+ };
+
+ CPU2: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x100>;
+ };
+
+ CPU3: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x101>;
+ };
+ };
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 2a1215d..ba246e5 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -108,12 +108,15 @@
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_XT_MARK=y
CONFIG_NETFILTER_XT_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_DSCP=y
CONFIG_NETFILTER_XT_MATCH_ESP=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_IP_SET=y
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index bf89321..483d8b3 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1270,6 +1270,7 @@
LPASS_SCSS_GP_HIGH_IRQ,
SPS_MTI_31,
A2_BAM_IRQ,
+ USB1_HS_BAM_IRQ,
};
struct msm_mpm_device_data msm9615_mpm_dev_data __initdata = {
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index bc9bddd..b1c1c5d 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -42,6 +42,7 @@
*/
struct ion_iommu_priv_data {
struct page **pages;
+ unsigned int pages_uses_vmalloc;
int nrpages;
unsigned long size;
};
@@ -118,6 +119,7 @@
unsigned int npages_to_vmap, total_pages, num_large_pages = 0;
unsigned long size_remaining = PAGE_ALIGN(size);
unsigned int max_order = ION_IS_CACHED(flags) ? 0 : orders[0];
+ unsigned int page_tbl_size;
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
@@ -139,8 +141,24 @@
data->size = PFN_ALIGN(size);
data->nrpages = data->size >> PAGE_SHIFT;
- data->pages = kzalloc(sizeof(struct page *)*data->nrpages,
- GFP_KERNEL);
+ data->pages_uses_vmalloc = 0;
+ page_tbl_size = sizeof(struct page *) * data->nrpages;
+
+ if (page_tbl_size > SZ_8K) {
+ /*
+ * Do fallback to ensure we have a balance between
+ * performance and availability.
+ */
+ data->pages = kmalloc(page_tbl_size,
+ __GFP_COMP | __GFP_NORETRY |
+ __GFP_NO_KSWAPD | __GFP_NOWARN);
+ if (!data->pages) {
+ data->pages = vmalloc(page_tbl_size);
+ data->pages_uses_vmalloc = 1;
+ }
+ } else {
+ data->pages = kmalloc(page_tbl_size, GFP_KERNEL);
+ }
if (!data->pages) {
ret = -ENOMEM;
goto err_free_data;
@@ -222,7 +240,10 @@
kfree(buffer->sg_table);
buffer->sg_table = 0;
err1:
- kfree(data->pages);
+ if (data->pages_uses_vmalloc)
+ vfree(data->pages);
+ else
+ kfree(data->pages);
err_free_data:
kfree(data);
@@ -253,7 +274,10 @@
sg_free_table(table);
kfree(table);
table = 0;
- kfree(data->pages);
+ if (data->pages_uses_vmalloc)
+ vfree(data->pages);
+ else
+ kfree(data->pages);
kfree(data);
}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 8caa9dd..b8c3c44 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1577,9 +1577,11 @@
if (pktsize == 192) {
if (leadingbytes)
- memcpy(timestamp, &buf[p], TIMESTAMP_LEN);
+ memcpy(timestamp, &demux->tsbuf[p],
+ TIMESTAMP_LEN);
else
- memcpy(timestamp, &buf[188], TIMESTAMP_LEN);
+ memcpy(timestamp, &demux->tsbuf[188],
+ TIMESTAMP_LEN);
} else {
memset(timestamp, 0, TIMESTAMP_LEN);
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
index b31b3f1..ff9c9b8 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
@@ -121,6 +121,7 @@
vfe_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE;
vfe_dev->subdev.sd.entity.name = pdev->name;
+ vfe_dev->subdev.close_seq = MSM_SD_CLOSE_1ST_CATEGORY | 0x2;
rc = msm_sd_register(&vfe_dev->subdev);
if (rc != 0) {
pr_err("%s: msm_sd_register error = %d\n", __func__, rc);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index dd8db03..ee205c0 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -389,6 +389,11 @@
rc = msm_isp_update_axi_stream(vfe_dev, arg);
mutex_unlock(&vfe_dev->core_mutex);
break;
+ case MSM_SD_SHUTDOWN:
+ while (vfe_dev->vfe_open_cnt != 0)
+ msm_isp_close_node(sd, NULL);
+ break;
+
default:
pr_err("%s: Invalid ISP command\n", __func__);
rc = -EINVAL;
@@ -912,11 +917,10 @@
rc = vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
if (rc <= 0)
- pr_err("%s: halt timeout\n", __func__);
+ pr_err("%s: halt timeout rc=%ld\n", __func__, rc);
vfe_dev->buf_mgr->ops->buf_mgr_deinit(vfe_dev->buf_mgr);
vfe_dev->hw_info->vfe_ops.core_ops.release_hw(vfe_dev);
-
vfe_dev->vfe_open_cnt--;
mutex_unlock(&vfe_dev->core_mutex);
mutex_unlock(&vfe_dev->realtime_mutex);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index a95eda7..dc1bcc3 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -91,7 +91,6 @@
BUG_ON(!ispif);
memset(ispif->sof_count, 0, sizeof(ispif->sof_count));
-
for (i = 0; i < ispif->vfe_info.num_vfe; i++) {
msm_camera_io_w(1 << PIX0_LINE_BUF_EN_BIT,
@@ -105,9 +104,13 @@
ISPIF_VFE_m_IRQ_CLEAR_1(i));
msm_camera_io_w(0xFFFFFFFF, ispif->base +
ISPIF_VFE_m_IRQ_CLEAR_2(i));
+
msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_INPUT_SEL(i));
- msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_INTF_CMD_0(i));
- msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_INTF_CMD_1(i));
+
+ msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY,
+ ispif->base + ISPIF_VFE_m_INTF_CMD_0(i));
+ msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY,
+ ispif->base + ISPIF_VFE_m_INTF_CMD_1(i));
msm_camera_io_w(0, ispif->base +
ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0));
@@ -905,6 +908,12 @@
switch (cmd) {
case VIDIOC_MSM_ISPIF_CFG:
return msm_ispif_cmd(sd, arg);
+ case MSM_SD_SHUTDOWN: {
+ struct ispif_device *ispif =
+ (struct ispif_device *)v4l2_get_subdevdata(sd);
+ msm_ispif_release(ispif);
+ return 0;
+ }
default:
pr_err("%s: invalid cmd 0x%x received\n", __func__, cmd);
return -ENOIOCTLCMD;
@@ -986,6 +995,7 @@
ispif->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
ispif->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ISPIF;
ispif->msm_sd.sd.entity.name = pdev->name;
+ ispif->msm_sd.close_seq = MSM_SD_CLOSE_1ST_CATEGORY | 0x1;
rc = msm_sd_register(&ispif->msm_sd);
if (rc) {
pr_err("%s: msm_sd_register error = %d\n", __func__, rc);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
index c805c3d..3cc21a7 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
@@ -91,4 +91,6 @@
#define ISPIF_IRQ_GLOBAL_CLEAR_CMD 0x1
+#define ISPIF_STOP_INTF_IMMEDIATELY 0xAAAAAAAA
+
#endif /* __MSM_ISPIF_HWREG_V2_H__ */
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index be9f613..8a691c5 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -31,6 +31,7 @@
#include "msm_sd.h"
static struct v4l2_device *msm_v4l2_dev;
+static struct list_head ordered_sd_list;
static struct msm_queue_head *msm_session_q;
@@ -301,6 +302,20 @@
return rc;
}
+static void msm_add_sd_in_position(struct msm_sd_subdev *msm_subdev,
+ struct list_head *sd_list)
+{
+ struct msm_sd_subdev *temp_sd;
+
+ list_for_each_entry(temp_sd, sd_list, list) {
+ if (msm_subdev->close_seq < temp_sd->close_seq) {
+ list_add_tail(&msm_subdev->list, &temp_sd->list);
+ return;
+ }
+ }
+ list_add_tail(&msm_subdev->list, sd_list);
+}
+
int msm_sd_register(struct msm_sd_subdev *msm_subdev)
{
if (WARN_ON(!msm_subdev))
@@ -309,6 +324,7 @@
if (WARN_ON(!msm_v4l2_dev) || WARN_ON(!msm_v4l2_dev->dev))
return -EIO;
+ msm_add_sd_in_position(msm_subdev, &ordered_sd_list);
return __msm_sd_register_subdev(&msm_subdev->sd);
}
@@ -401,62 +417,35 @@
spin_unlock_irqrestore(&(session->command_ack_q.lock), flags);
}
-static inline int __msm_v4l2_subdev_shutdown(struct v4l2_subdev *sd)
-{
- return 0;
-}
-
-static void msm_sd_try_shutdown(void)
-{
- unsigned long flags;
- struct v4l2_subdev *sd;
-
- /* release all subdev's resource */
- spin_lock_irqsave(&msm_v4l2_dev->lock, flags);
- if (!list_empty(&msm_v4l2_dev->subdevs)) {
- list_for_each_entry(sd, &msm_v4l2_dev->subdevs, list)
- __msm_v4l2_subdev_shutdown(sd);
- }
- spin_unlock_irqrestore(&msm_v4l2_dev->lock, flags);
-}
-
-static inline int __msm_sd_close_session_streams(struct v4l2_subdev *sd,
+static inline int __msm_sd_close_subdevs(struct msm_sd_subdev *msm_sd,
struct msm_sd_close_ioctl *sd_close)
{
+ struct v4l2_subdev *sd;
+ sd = &msm_sd->sd;
+ pr_debug("%s: Shutting down subdev %s", __func__, sd->name);
+
+ v4l2_subdev_call(sd, core, ioctl, MSM_SD_SHUTDOWN, sd_close);
+ v4l2_subdev_call(sd, core, s_power, 0);
+
return 0;
}
static inline int __msm_destroy_session_streams(void *d1, void *d2)
{
struct msm_stream *stream = d1;
- struct msm_sd_close_ioctl *sd_close = d2;
- struct v4l2_subdev *sd;
- unsigned long flags;
- sd_close->stream = stream->stream_id;
-
- spin_lock_irqsave(&msm_v4l2_dev->lock, flags);
- if (!list_empty(&msm_v4l2_dev->subdevs))
- list_for_each_entry(sd, &msm_v4l2_dev->subdevs, list)
- __msm_sd_close_session_streams(sd, sd_close);
- spin_unlock_irqrestore(&msm_v4l2_dev->lock, flags);
INIT_LIST_HEAD(&stream->queued_list);
return 0;
}
static void msm_destroy_session_streams(struct msm_session *session)
{
- struct msm_sd_close_ioctl sd_close;
- /* to ensure error handling purpose, it needs to detach all subdevs
- * which are being connected to streams */
if (!session)
return;
- sd_close.session = session->session_id;
-
msm_queue_traverse_action(&session->stream_q, struct msm_stream, list,
- __msm_destroy_session_streams, &sd_close);
+ __msm_destroy_session_streams, NULL);
msm_queue_drain(&session->stream_q, struct msm_stream, list);
}
@@ -694,16 +683,13 @@
struct msm_v4l2_event_data *event_data =
(struct msm_v4l2_event_data *)&event.u.data[0];
struct msm_session *session = d1;
- mutex_lock(&session->lock);
+
event.type = MSM_CAMERA_V4L2_EVENT_TYPE;
event.id = MSM_CAMERA_MSM_NOTIFY;
event_data->command = MSM_CAMERA_PRIV_SHUTDOWN;
v4l2_event_queue(session->event_q.vdev, &event);
- msm_destroy_session_streams(session);
- msm_remove_session_cmd_ack_q(session);
- mutex_unlock(&session->lock);
return 0;
}
@@ -712,22 +698,23 @@
int rc = 0;
unsigned long flags;
struct msm_video_device *pvdev = video_drvdata(filep);
+ struct msm_sd_close_ioctl sd_close;
+ struct msm_sd_subdev *msm_sd;
- /* 1st thing 1st, send v4l2_event to HAL immediately,
- * to ensure error handling purpose, it needs to detach all subdevs
- * which are being connected to streams */
+ /*stop all hardware blocks immediately*/
+ if (!list_empty(&msm_v4l2_dev->subdevs))
+ list_for_each_entry(msm_sd, &ordered_sd_list, list)
+ __msm_sd_close_subdevs(msm_sd, &sd_close);
+
+ /* send v4l2_event to HAL next*/
msm_queue_traverse_action(msm_session_q, struct msm_session, list,
__msm_close_destry_session_notify_apps, NULL);
- msm_queue_drain(msm_session_q, struct msm_session, list);
-
spin_lock_irqsave(&msm_eventq_lock, flags);
msm_eventq = NULL;
spin_unlock_irqrestore(&msm_eventq_lock, flags);
v4l2_fh_release(filep);
- msm_sd_try_shutdown();
-
spin_lock_irqsave(&msm_pid_lock, flags);
put_pid(msm_pid);
msm_pid = NULL;
@@ -754,7 +741,6 @@
int rc;
unsigned long flags;
struct msm_video_device *pvdev = video_drvdata(filep);
-
BUG_ON(!pvdev);
/* !!! only ONE open is allowed !!! */
@@ -990,7 +976,7 @@
msm_init_queue(msm_session_q);
spin_lock_init(&msm_eventq_lock);
spin_lock_init(&msm_pid_lock);
-
+ INIT_LIST_HEAD(&ordered_sd_list);
goto probe_end;
v4l2_fail:
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index b0ff832..895f452 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -161,6 +161,7 @@
msm_buf_mngr_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
msm_buf_mngr_dev->subdev.sd.entity.group_id =
MSM_CAMERA_SUBDEV_BUF_MNGR;
+ msm_buf_mngr_dev->subdev.close_seq = MSM_SD_CLOSE_4TH_CATEGORY;
rc = msm_sd_register(&msm_buf_mngr_dev->subdev);
if (rc != 0) {
pr_err("%s: msm_sd_register error = %d\n", __func__, rc);
diff --git a/drivers/media/platform/msm/camera_v2/msm_sd.h b/drivers/media/platform/msm/camera_v2/msm_sd.h
index 958e030..7c1519d 100644
--- a/drivers/media/platform/msm/camera_v2/msm_sd.h
+++ b/drivers/media/platform/msm/camera_v2/msm_sd.h
@@ -50,10 +50,12 @@
#define MSM_SD_CLOSE_1ST_CATEGORY 0x00010000
#define MSM_SD_CLOSE_2ND_CATEGORY 0x00020000
#define MSM_SD_CLOSE_3RD_CATEGORY 0x00030000
+#define MSM_SD_CLOSE_4TH_CATEGORY 0x00040000
struct msm_sd_subdev {
struct v4l2_subdev sd;
int close_seq;
+ struct list_head list;
};
struct msm_sd_req_sd {
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 5a174f5..4dd3f3d 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -43,6 +43,9 @@
#define CONFIG_MSM_CPP_DBG 0
+/* dump the frame command before writing to the hardware */
+#define MSM_CPP_DUMP_FRM_CMD 0
+
#if CONFIG_MSM_CPP_DBG
#define CPP_DBG(fmt, args...) pr_err(fmt, ##args)
#else
@@ -208,7 +211,6 @@
pr_err("ION import failed\n");
goto QUEUE_BUFF_ERROR1;
}
-
rc = ion_map_iommu(cpp_dev->client, buff->map_info.ion_handle,
cpp_dev->domain_num, 0, SZ_4K, 0,
(unsigned long *)&buff->map_info.phy_addr,
@@ -237,6 +239,7 @@
static void msm_cpp_dequeue_buffer_info(struct cpp_device *cpp_dev,
struct msm_cpp_buffer_map_list_t *buff)
{
+
ion_unmap_iommu(cpp_dev->client, buff->map_info.ion_handle,
cpp_dev->domain_num, 0);
ion_free(cpp_dev->client, buff->map_info.ion_handle);
@@ -390,6 +393,8 @@
pr_err("Queue not free sessionid: %d, streamid: %d\n",
cpp_dev->buff_queue[i].session_id,
cpp_dev->buff_queue[i].stream_id);
+ msm_cpp_dequeue_buff_info_list
+ (cpp_dev, &cpp_dev->buff_queue[i]);
msm_cpp_free_buff_queue_entry(cpp_dev,
cpp_dev->buff_queue[i].session_id,
cpp_dev->buff_queue[i].stream_id);
@@ -821,9 +826,16 @@
{
uint32_t i;
struct cpp_device *cpp_dev = v4l2_get_subdevdata(sd);
+
mutex_lock(&cpp_dev->mutex);
+
+ if (cpp_dev->cpp_open_cnt == 0) {
+ mutex_unlock(&cpp_dev->mutex);
+ return 0;
+ }
+
for (i = 0; i < MAX_ACTIVE_CPP_INSTANCE; i++) {
- if (cpp_dev->cpp_subscribe_list[i].vfh == &fh->vfh) {
+ if (cpp_dev->cpp_subscribe_list[i].active == 1) {
cpp_dev->cpp_subscribe_list[i].active = 0;
cpp_dev->cpp_subscribe_list[i].vfh = NULL;
break;
@@ -835,7 +847,6 @@
return -ENODEV;
}
- CPP_DBG("close %d %p\n", i, &fh->vfh);
cpp_dev->cpp_open_cnt--;
if (cpp_dev->cpp_open_cnt == 0) {
msm_camera_io_w(0x0, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL);
@@ -843,6 +854,7 @@
cpp_release_hardware(cpp_dev);
cpp_dev->state = CPP_STATE_OFF;
}
+
mutex_unlock(&cpp_dev->mutex);
return 0;
}
@@ -888,8 +900,7 @@
event_qcmd->command = processed_frame;
CPP_DBG("fid %d\n", processed_frame->frame_id);
msm_enqueue(&cpp_dev->eventData_q, &event_qcmd->list_eventdata);
-
- if (!processed_frame->output_buffer_info.processed_divert) {
+ if (!processed_frame->output_buffer_info[0].processed_divert) {
memset(&buff_mgr_info, 0 ,
sizeof(struct msm_buf_mngr_info));
buff_mgr_info.session_id =
@@ -899,7 +910,7 @@
buff_mgr_info.frame_id = processed_frame->frame_id;
buff_mgr_info.timestamp = processed_frame->timestamp;
buff_mgr_info.index =
- processed_frame->output_buffer_info.index;
+ processed_frame->output_buffer_info[0].index;
rc = msm_cpp_buffer_ops(cpp_dev,
VIDIOC_MSM_BUF_MNGR_BUF_DONE,
&buff_mgr_info);
@@ -908,6 +919,28 @@
rc = -EINVAL;
}
}
+
+ if (processed_frame->duplicate_output &&
+ !processed_frame->
+ output_buffer_info[1].processed_divert) {
+ memset(&buff_mgr_info, 0 ,
+ sizeof(struct msm_buf_mngr_info));
+ buff_mgr_info.session_id =
+ ((processed_frame->duplicate_identity >> 16) & 0xFFFF);
+ buff_mgr_info.stream_id =
+ (processed_frame->duplicate_identity & 0xFFFF);
+ buff_mgr_info.frame_id = processed_frame->frame_id;
+ buff_mgr_info.timestamp = processed_frame->timestamp;
+ buff_mgr_info.index =
+ processed_frame->output_buffer_info[1].index;
+ rc = msm_cpp_buffer_ops(cpp_dev,
+ VIDIOC_MSM_BUF_MNGR_BUF_DONE,
+ &buff_mgr_info);
+ if (rc < 0) {
+ pr_err("error putting buffer\n");
+ rc = -EINVAL;
+ }
+ }
v4l2_evt.id = processed_frame->inst_id;
v4l2_evt.type = V4L2_EVENT_CPP_FRAME_DONE;
v4l2_event_queue(cpp_dev->msm_sd.sd.devnode, &v4l2_evt);
@@ -915,6 +948,23 @@
return rc;
}
+#if MSM_CPP_DUMP_FRM_CMD
+static int msm_cpp_dump_frame_cmd(uint32_t *cmd, int32_t len)
+{
+ int i;
+ pr_err("%s: -------- cpp frame cmd msg start --------", __func__);
+ for (i = 0; i < len; i++)
+ pr_err("%s: msg[%03d] = 0x%08x", __func__, i, cmd[i]);
+ pr_err("%s: --------- cpp frame cmd msg end ---------", __func__);
+ return 0;
+}
+#else
+static int msm_cpp_dump_frame_cmd(uint32_t *cmd, int32_t len)
+{
+ return 0;
+}
+#endif
+
static int msm_cpp_send_frame_to_hardware(struct cpp_device *cpp_dev,
struct msm_queue_cmd *frame_qcmd)
{
@@ -927,6 +977,8 @@
msm_enqueue(&cpp_dev->processing_q,
&frame_qcmd->list_frame);
msm_cpp_write(0x6, cpp_dev->base);
+ msm_cpp_dump_frame_cmd(process_frame->cpp_cmd_msg,
+ process_frame->msg_len);
for (i = 0; i < process_frame->msg_len; i++)
msm_cpp_write(process_frame->cpp_cmd_msg[i],
cpp_dev->base);
@@ -951,7 +1003,7 @@
struct msm_cpp_frame_info_t *new_frame =
kzalloc(sizeof(struct msm_cpp_frame_info_t), GFP_KERNEL);
uint32_t *cpp_frame_msg;
- unsigned long in_phyaddr, out_phyaddr;
+ unsigned long in_phyaddr, out_phyaddr0, out_phyaddr1;
uint16_t num_stripes = 0;
struct msm_buf_mngr_info buff_mgr_info;
struct msm_cpp_frame_info_t *u_frame_info =
@@ -1001,7 +1053,7 @@
goto ERROR2;
}
- memset(&new_frame->output_buffer_info, 0,
+ memset(&new_frame->output_buffer_info[0], 0,
sizeof(struct msm_cpp_buffer_info_t));
memset(&buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info));
buff_mgr_info.session_id = ((new_frame->identity >> 16) & 0xFFFF);
@@ -1013,17 +1065,49 @@
pr_debug("error getting buffer rc:%d\n", rc);
goto ERROR2;
}
-
- new_frame->output_buffer_info.index = buff_mgr_info.index;
- out_phyaddr = msm_cpp_fetch_buffer_info(cpp_dev,
- &new_frame->output_buffer_info,
+ new_frame->output_buffer_info[0].index = buff_mgr_info.index;
+ out_phyaddr0 = msm_cpp_fetch_buffer_info(cpp_dev,
+ &new_frame->output_buffer_info[0],
((new_frame->identity >> 16) & 0xFFFF),
(new_frame->identity & 0xFFFF));
- if (!out_phyaddr) {
+ if (!out_phyaddr0) {
pr_err("error gettting output physical address\n");
rc = -EINVAL;
goto ERROR3;
}
+ out_phyaddr1 = out_phyaddr0;
+
+ /* get buffer for duplicate output */
+ if (new_frame->duplicate_output) {
+ CPP_DBG("duplication enabled, dup_id=0x%x",
+ new_frame->duplicate_identity);
+ memset(&new_frame->output_buffer_info[1], 0,
+ sizeof(struct msm_cpp_buffer_info_t));
+ memset(&buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info));
+ buff_mgr_info.session_id =
+ ((new_frame->duplicate_identity >> 16) & 0xFFFF);
+ buff_mgr_info.stream_id =
+ (new_frame->duplicate_identity & 0xFFFF);
+ rc = msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_GET_BUF,
+ &buff_mgr_info);
+ if (rc < 0) {
+ rc = -EAGAIN;
+ pr_err("error getting buffer rc:%d\n", rc);
+ goto ERROR2;
+ }
+ new_frame->output_buffer_info[1].index = buff_mgr_info.index;
+ out_phyaddr1 = msm_cpp_fetch_buffer_info(cpp_dev,
+ &new_frame->output_buffer_info[1],
+ ((new_frame->duplicate_identity >> 16) & 0xFFFF),
+ (new_frame->duplicate_identity & 0xFFFF));
+ if (!out_phyaddr1) {
+ pr_err("error gettting output physical address\n");
+ rc = -EINVAL;
+ goto ERROR3;
+ }
+ /* set duplicate enable bit */
+ cpp_frame_msg[5] |= 0x1;
+ }
num_stripes = ((cpp_frame_msg[12] >> 20) & 0x3FF) +
((cpp_frame_msg[12] >> 10) & 0x3FF) +
@@ -1031,10 +1115,10 @@
for (i = 0; i < num_stripes; i++) {
cpp_frame_msg[133 + i * 27] += (uint32_t) in_phyaddr;
- cpp_frame_msg[139 + i * 27] += (uint32_t) out_phyaddr;
- cpp_frame_msg[140 + i * 27] += (uint32_t) out_phyaddr;
- cpp_frame_msg[141 + i * 27] += (uint32_t) out_phyaddr;
- cpp_frame_msg[142 + i * 27] += (uint32_t) out_phyaddr;
+ cpp_frame_msg[139 + i * 27] += (uint32_t) out_phyaddr0;
+ cpp_frame_msg[140 + i * 27] += (uint32_t) out_phyaddr1;
+ cpp_frame_msg[141 + i * 27] += (uint32_t) out_phyaddr0;
+ cpp_frame_msg[142 + i * 27] += (uint32_t) out_phyaddr1;
}
frame_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
@@ -1245,6 +1329,13 @@
kfree(event_qcmd);
break;
}
+ case MSM_SD_SHUTDOWN: {
+ mutex_unlock(&cpp_dev->mutex);
+ while (cpp_dev->cpp_open_cnt != 0)
+ cpp_close_node(sd, NULL);
+ rc = 0;
+ break;
+ }
}
mutex_unlock(&cpp_dev->mutex);
CPP_DBG("X\n");
@@ -1446,6 +1537,7 @@
cpp_dev->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
cpp_dev->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_CPP;
cpp_dev->msm_sd.sd.entity.name = pdev->name;
+ cpp_dev->msm_sd.close_seq = MSM_SD_CLOSE_3RD_CATEGORY;
msm_sd_register(&cpp_dev->msm_sd);
msm_cpp_v4l2_subdev_fops.owner = v4l2_subdev_fops.owner;
msm_cpp_v4l2_subdev_fops.open = v4l2_subdev_fops.open;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index e1b978f..b115738 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -629,6 +629,9 @@
return msm_actuator_get_subdev_id(a_ctrl, argp);
case VIDIOC_MSM_ACTUATOR_CFG:
return msm_actuator_config(a_ctrl, argp);
+ case MSM_SD_SHUTDOWN:
+ msm_actuator_close(sd, NULL);
+ return 0;
default:
return -ENOIOCTLCMD;
}
@@ -710,6 +713,7 @@
media_entity_init(&act_ctrl_t->msm_sd.sd.entity, 0, NULL, 0);
act_ctrl_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+ act_ctrl_t->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x2;
msm_sd_register(&act_ctrl_t->msm_sd);
CDBG("succeeded\n");
CDBG("Exit\n");
@@ -780,6 +784,7 @@
media_entity_init(&msm_actuator_t->msm_sd.sd.entity, 0, NULL, 0);
msm_actuator_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
msm_actuator_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+ msm_actuator_t->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x2;
msm_sd_register(&msm_actuator_t->msm_sd);
CDBG("Exit\n");
return rc;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index 3409b3e..f3da41c 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -773,6 +773,12 @@
case VIDIOC_MSM_CCI_CFG:
rc = msm_cci_config(sd, arg);
break;
+ case MSM_SD_SHUTDOWN: {
+ struct msm_camera_cci_ctrl ctrl_cmd;
+ ctrl_cmd.cmd = MSM_CCI_RELEASE;
+ rc = msm_cci_config(sd, &ctrl_cmd);
+ break;
+ }
default:
rc = -ENOIOCTLCMD;
}
@@ -1007,6 +1013,7 @@
goto cci_release_mem;
}
disable_irq(new_cci_dev->irq->start);
+ new_cci_dev->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x6;
msm_sd_register(&new_cci_dev->msm_sd);
new_cci_dev->pdev = pdev;
msm_cci_init_cci_params(new_cci_dev);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index 33eaa69..4db6855 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -460,6 +460,7 @@
rc = msm_csid_cmd(csid_dev, arg);
break;
case VIDIOC_MSM_CSID_RELEASE:
+ case MSM_SD_SHUTDOWN:
rc = msm_csid_release(csid_dev);
break;
default:
@@ -552,6 +553,7 @@
media_entity_init(&new_csid_dev->msm_sd.sd.entity, 0, NULL, 0);
new_csid_dev->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
new_csid_dev->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_CSID;
+ new_csid_dev->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x5;
msm_sd_register(&new_csid_dev->msm_sd);
rc = request_irq(new_csid_dev->irq->start, msm_csid_irq,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
index 7d3a1fc..429d151 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -570,6 +570,7 @@
rc = msm_csiphy_cmd(csiphy_dev, arg);
break;
case VIDIOC_MSM_CSIPHY_RELEASE:
+ case MSM_SD_SHUTDOWN:
rc = msm_csiphy_release(csiphy_dev, arg);
break;
default:
@@ -665,7 +666,7 @@
media_entity_init(&new_csiphy_dev->msm_sd.sd.entity, 0, NULL, 0);
new_csiphy_dev->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
new_csiphy_dev->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_CSIPHY;
-
+ new_csiphy_dev->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x4;
msm_sd_register(&new_csiphy_dev->msm_sd);
new_csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN;
return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c
index 9119a13..044fd31 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c
@@ -81,6 +81,7 @@
media_entity_init(&fctrl->msm_sd.sd.entity, 0, NULL, 0);
fctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
fctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_LED_FLASH;
+ fctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x1;
msm_sd_register(&fctrl->msm_sd);
CDBG("probe success\n");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 27d3d40..d56a5252 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -1050,6 +1050,7 @@
struct msm_sensor_power_setting_array *power_setting_array = NULL;
struct msm_sensor_power_setting *power_setting = NULL;
struct msm_camera_sensor_board_info *data = s_ctrl->sensordata;
+ s_ctrl->stop_setting_valid = 0;
CDBG("%s:%d\n", __func__, __LINE__);
power_setting_array = &s_ctrl->power_setting_array;
@@ -1149,9 +1150,13 @@
static void msm_sensor_stop_stream(struct msm_sensor_ctrl_t *s_ctrl)
{
- s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table(
- s_ctrl->sensor_i2c_client, &s_ctrl->stop_setting);
- kfree(s_ctrl->stop_setting.reg_setting);
+ mutex_lock(s_ctrl->msm_sensor_mutex);
+ if (s_ctrl->sensor_state == MSM_SENSOR_POWER_UP) {
+ s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table(
+ s_ctrl->sensor_i2c_client, &s_ctrl->stop_setting);
+ kfree(s_ctrl->stop_setting.reg_setting);
+ }
+ mutex_unlock(s_ctrl->msm_sensor_mutex);
return;
}
@@ -1168,6 +1173,7 @@
case VIDIOC_MSM_SENSOR_CFG:
return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
case VIDIOC_MSM_SENSOR_RELEASE:
+ case MSM_SD_SHUTDOWN:
msm_sensor_stop_stream(s_ctrl);
return 0;
default:
@@ -1282,6 +1288,13 @@
struct msm_camera_i2c_reg_setting conf_array;
struct msm_camera_i2c_reg_array *reg_setting = NULL;
+ if (s_ctrl->sensor_state != MSM_SENSOR_POWER_UP) {
+ pr_err("%s:%d failed: invalid state %d\n", __func__,
+ __LINE__, s_ctrl->sensor_state);
+ rc = -EFAULT;
+ break;
+ }
+
if (copy_from_user(&conf_array,
(void *)cdata->cfg.setting,
sizeof(struct msm_camera_i2c_reg_setting))) {
@@ -1316,6 +1329,13 @@
struct msm_camera_i2c_seq_reg_setting conf_array;
struct msm_camera_i2c_seq_reg_array *reg_setting = NULL;
+ if (s_ctrl->sensor_state != MSM_SENSOR_POWER_UP) {
+ pr_err("%s:%d failed: invalid state %d\n", __func__,
+ __LINE__, s_ctrl->sensor_state);
+ rc = -EFAULT;
+ break;
+ }
+
if (copy_from_user(&conf_array,
(void *)cdata->cfg.setting,
sizeof(struct msm_camera_i2c_seq_reg_setting))) {
@@ -1350,23 +1370,54 @@
}
case CFG_POWER_UP:
- if (s_ctrl->sensordata->misc_regulator)
- msm_sensor_misc_regulator(s_ctrl, 1);
-
- if (s_ctrl->func_tbl->sensor_power_up)
- rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
- else
+ if (s_ctrl->sensor_state != MSM_SENSOR_POWER_DOWN) {
+ pr_err("%s:%d failed: invalid state %d\n", __func__,
+ __LINE__, s_ctrl->sensor_state);
rc = -EFAULT;
+ break;
+ }
+ if (s_ctrl->func_tbl->sensor_power_up) {
+ if (s_ctrl->sensordata->misc_regulator)
+ msm_sensor_misc_regulator(s_ctrl, 1);
+
+ rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+ if (rc < 0) {
+ pr_err("%s:%d failed rc %ld\n", __func__,
+ __LINE__, rc);
+ break;
+ }
+ s_ctrl->sensor_state = MSM_SENSOR_POWER_UP;
+ pr_err("%s:%d sensor state %d\n", __func__, __LINE__,
+ s_ctrl->sensor_state);
+ } else {
+ rc = -EFAULT;
+ }
break;
case CFG_POWER_DOWN:
- if (s_ctrl->sensordata->misc_regulator)
- msm_sensor_misc_regulator(s_ctrl, 0);
- if (s_ctrl->func_tbl->sensor_power_down)
+ if (s_ctrl->sensor_state != MSM_SENSOR_POWER_UP) {
+ pr_err("%s:%d failed: invalid state %d\n", __func__,
+ __LINE__, s_ctrl->sensor_state);
+ rc = -EFAULT;
+ break;
+ }
+ if (s_ctrl->func_tbl->sensor_power_down) {
+ if (s_ctrl->sensordata->misc_regulator)
+ msm_sensor_misc_regulator(s_ctrl, 0);
+
rc = s_ctrl->func_tbl->sensor_power_down(
s_ctrl);
- else
+ if (rc < 0) {
+ pr_err("%s:%d failed rc %ld\n", __func__,
+ __LINE__, rc);
+ break;
+ }
+ s_ctrl->sensor_state = MSM_SENSOR_POWER_DOWN;
+ pr_err("%s:%d sensor state %d\n", __func__, __LINE__,
+ s_ctrl->sensor_state);
+ } else {
rc = -EFAULT;
+ }
break;
case CFG_SET_STOP_STREAM_SETTING: {
@@ -1380,6 +1431,7 @@
rc = -EFAULT;
break;
}
+ s_ctrl->stop_setting_valid = 1;
reg_setting = stop_setting->reg_setting;
stop_setting->reg_setting = kzalloc(stop_setting->size *
@@ -1417,8 +1469,10 @@
int rc = 0;
struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
mutex_lock(s_ctrl->msm_sensor_mutex);
- if (!on)
- rc = s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+ if (!on && s_ctrl->sensor_state == MSM_SENSOR_POWER_UP) {
+ s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+ s_ctrl->sensor_state = MSM_SENSOR_POWER_DOWN;
+ }
if (s_ctrl->free_power_setting == true) {
kfree(s_ctrl->power_setting_array.power_setting);
s_ctrl->free_power_setting = false;
@@ -1558,6 +1612,7 @@
rc = camera_init_v4l2(&s_ctrl->pdev->dev, &session_id);
CDBG("%s rc %d session_id %d\n", __func__, rc, session_id);
s_ctrl->sensordata->sensor_info->session_id = session_id;
+ s_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x3;
msm_sd_register(&s_ctrl->msm_sd);
CDBG("%s:%d\n", __func__, __LINE__);
@@ -1649,6 +1704,7 @@
&session_id);
CDBG("%s rc %d session_id %d\n", __func__, rc, session_id);
s_ctrl->sensordata->sensor_info->session_id = session_id;
+ s_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x3;
msm_sd_register(&s_ctrl->msm_sd);
CDBG("%s:%d\n", __func__, __LINE__);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
index a1128a6..fe11a56 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.h
@@ -37,6 +37,11 @@
struct msm_sensor_ctrl_t;
+enum msm_sensor_state_t {
+ MSM_SENSOR_POWER_DOWN,
+ MSM_SENSOR_POWER_UP,
+};
+
struct msm_sensor_fn_t {
int (*sensor_config) (struct msm_sensor_ctrl_t *, void __user *);
int (*sensor_power_down)
@@ -62,10 +67,12 @@
struct v4l2_subdev_ops *sensor_v4l2_subdev_ops;
struct msm_sensor_fn_t *func_tbl;
struct msm_camera_i2c_reg_setting stop_setting;
+ bool stop_setting_valid;
bool free_power_setting;
struct msm_cam_clk_info *clk_info;
uint16_t clk_info_size;
void *misc_regulator;
+ enum msm_sensor_state_t sensor_state;
};
int32_t msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl,
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index d8a5669..9bc77be 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -278,63 +278,24 @@
svc->sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt, svc->ihandle);
svc->sb_phys = pa;
- if (qseecom.qseos_version == QSEOS_VERSION_14) {
- req.qsee_cmd_id = QSEOS_REGISTER_LISTENER;
- req.listener_id = svc->svc.listener_id;
- req.sb_len = svc->sb_length;
- req.sb_ptr = (void *)svc->sb_phys;
+ req.qsee_cmd_id = QSEOS_REGISTER_LISTENER;
+ req.listener_id = svc->svc.listener_id;
+ req.sb_len = svc->sb_length;
+ req.sb_ptr = (void *)svc->sb_phys;
- resp.result = QSEOS_RESULT_INCOMPLETE;
+ resp.result = QSEOS_RESULT_INCOMPLETE;
- ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
sizeof(req), &resp, sizeof(resp));
- if (ret) {
- pr_err("qseecom_scm_call failed with err: %d\n", ret);
- return -EINVAL;
- }
+ if (ret) {
+ pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ return -EINVAL;
+ }
- if (resp.result != QSEOS_RESULT_SUCCESS) {
- pr_err("Error SB registration req: resp.result = %d\n",
- resp.result);
- return -EPERM;
- }
- } else {
- struct qseecom_command cmd;
- struct qseecom_response resp;
- struct qse_pr_init_sb_req_s sb_init_req;
- struct qse_pr_init_sb_rsp_s sb_init_rsp;
-
- svc->sb_reg_req = kzalloc((sizeof(sb_init_req) +
- sizeof(sb_init_rsp)), GFP_KERNEL);
-
- sb_init_req.pr_cmd = TZ_SCHED_CMD_ID_REGISTER_LISTENER;
- sb_init_req.listener_id = svc->svc.listener_id;
- sb_init_req.sb_len = svc->sb_length;
- sb_init_req.sb_ptr = svc->sb_phys;
-
- memcpy(svc->sb_reg_req, &sb_init_req, sizeof(sb_init_req));
-
- /* It will always be a new cmd from this method */
- cmd.cmd_type = TZ_SCHED_CMD_NEW;
- cmd.sb_in_cmd_addr = (u8 *)(virt_to_phys(svc->sb_reg_req));
- cmd.sb_in_cmd_len = sizeof(sb_init_req);
-
- resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
-
- ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &cmd, sizeof(cmd)
- , &resp, sizeof(resp));
-
- if (ret) {
- pr_err("qseecom_scm_call failed with err: %d\n", ret);
- return -EINVAL;
- }
-
- if (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
- pr_err("SB registration fail resp.cmd_status %d\n",
- resp.cmd_status);
- return -EINVAL;
- }
- memset(svc->sb_virt, 0, svc->sb_length);
+ if (resp.result != QSEOS_RESULT_SUCCESS) {
+ pr_err("Error SB registration req: resp.result = %d\n",
+ resp.result);
+ return -EPERM;
}
return 0;
}
@@ -396,56 +357,24 @@
struct qseecom_command_scm_resp resp;
struct ion_handle *ihandle = NULL; /* Retrieve phy addr */
- if (qseecom.qseos_version == QSEOS_VERSION_14) {
- req.qsee_cmd_id = QSEOS_DEREGISTER_LISTENER;
- req.listener_id = data->listener.id;
- resp.result = QSEOS_RESULT_INCOMPLETE;
+ req.qsee_cmd_id = QSEOS_DEREGISTER_LISTENER;
+ req.listener_id = data->listener.id;
+ resp.result = QSEOS_RESULT_INCOMPLETE;
- ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
sizeof(req), &resp, sizeof(resp));
- if (ret) {
- pr_err("scm_call() failed with err: %d (lstnr id=%d)\n",
- ret, data->listener.id);
- return ret;
- }
-
- if (resp.result != QSEOS_RESULT_SUCCESS) {
- pr_err("Failed resp.result=%d,(lstnr id=%d)\n",
- resp.result, data->listener.id);
- return -EPERM;
- }
- } else {
- struct qse_pr_init_sb_req_s sb_init_req;
- struct qseecom_command cmd;
- struct qseecom_response resp;
- struct qseecom_registered_listener_list *svc;
-
- svc = __qseecom_find_svc(data->listener.id);
- sb_init_req.pr_cmd = TZ_SCHED_CMD_ID_REGISTER_LISTENER;
- sb_init_req.listener_id = data->listener.id;
- sb_init_req.sb_len = 0;
- sb_init_req.sb_ptr = 0;
-
- memcpy(svc->sb_reg_req, &sb_init_req, sizeof(sb_init_req));
-
- /* It will always be a new cmd from this method */
- cmd.cmd_type = TZ_SCHED_CMD_NEW;
- cmd.sb_in_cmd_addr = (u8 *)(virt_to_phys(svc->sb_reg_req));
- cmd.sb_in_cmd_len = sizeof(sb_init_req);
- resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
-
- ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &cmd, sizeof(cmd),
- &resp, sizeof(resp));
- if (ret) {
- pr_err("qseecom_scm_call failed with err: %d\n", ret);
- return ret;
- }
- kzfree(svc->sb_reg_req);
- if (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
- pr_err("Error with SB initialization\n");
- return -EPERM;
- }
+ if (ret) {
+ pr_err("scm_call() failed with err: %d (lstnr id=%d)\n",
+ ret, data->listener.id);
+ return ret;
}
+
+ if (resp.result != QSEOS_RESULT_SUCCESS) {
+ pr_err("Failed resp.result=%d,(lstnr id=%d)\n",
+ resp.result, data->listener.id);
+ return -EPERM;
+ }
+
data->abort = 1;
spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head,
@@ -830,8 +759,7 @@
bool unload = false;
bool found_app = false;
- if ((qseecom.qseos_version == QSEOS_VERSION_14) &&
- (data->client.app_id > 0)) {
+ if (data->client.app_id > 0) {
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
list) {
@@ -857,7 +785,7 @@
}
}
- if ((unload) && (qseecom.qseos_version == QSEOS_VERSION_14)) {
+ if (unload) {
struct qseecom_unload_app_ireq req;
__qseecom_cleanup_app(data);
@@ -890,19 +818,6 @@
}
}
}
-
- if (qseecom.qseos_version == QSEOS_VERSION_13) {
- data->abort = 1;
- wake_up_all(&qseecom.send_resp_wq);
- while (atomic_read(&data->ioctl_count) > 0) {
- if (wait_event_freezable(data->abort_wq,
- atomic_read(&data->ioctl_count) <= 0)) {
- pr_err("Interrupted from abort\n");
- ret = -ERESTARTSYS;
- break;
- }
- }
- }
qseecom_unmap_ion_allocated_memory(data);
data->released = true;
return ret;
@@ -914,98 +829,6 @@
return data->client.sb_phys + (virt - data->client.user_virt_sb_base);
}
-static int __qseecom_send_cmd_legacy(struct qseecom_dev_handle *data,
- struct qseecom_send_cmd_req *req)
-{
- int ret = 0;
- unsigned long flags;
- u32 reqd_len_sb_in = 0;
- struct qseecom_command cmd;
- struct qseecom_response resp;
-
-
- if (req->cmd_req_buf == NULL || req->resp_buf == NULL) {
- pr_err("cmd buffer or response buffer is null\n");
- return -EINVAL;
- }
-
- if (req->cmd_req_len <= 0 ||
- req->resp_len <= 0 ||
- req->cmd_req_len > data->client.sb_length ||
- req->resp_len > data->client.sb_length) {
- pr_err("cmd buffer length or "
- "response buffer length not valid\n");
- return -EINVAL;
- }
-
- reqd_len_sb_in = req->cmd_req_len + req->resp_len;
- if (reqd_len_sb_in > data->client.sb_length) {
- pr_debug("Not enough memory to fit cmd_buf and "
- "resp_buf. Required: %u, Available: %u\n",
- reqd_len_sb_in, data->client.sb_length);
- return -ENOMEM;
- }
- cmd.cmd_type = TZ_SCHED_CMD_NEW;
- cmd.sb_in_cmd_addr = (u8 *) data->client.sb_phys;
- cmd.sb_in_cmd_len = req->cmd_req_len;
-
- resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
- resp.sb_in_rsp_addr = (u8 *)data->client.sb_phys + req->cmd_req_len;
- resp.sb_in_rsp_len = req->resp_len;
-
- ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *)&cmd,
- sizeof(cmd), &resp, sizeof(resp));
-
- if (ret) {
- pr_err("qseecom_scm_call_legacy failed with err: %d\n", ret);
- return ret;
- }
-
- while (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
- /*
- * If cmd is incomplete, get the callback cmd out from SB out
- * and put it on the list
- */
- struct qseecom_registered_listener_list *ptr_svc = NULL;
- /*
- * We don't know which service can handle the command. so we
- * wake up all blocking services and let them figure out if
- * they can handle the given command.
- */
- spin_lock_irqsave(&qseecom.registered_listener_list_lock,
- flags);
- list_for_each_entry(ptr_svc,
- &qseecom.registered_listener_list_head, list) {
- ptr_svc->rcv_req_flag = 1;
- wake_up_interruptible(&ptr_svc->rcv_req_wq);
- }
- spin_unlock_irqrestore(&qseecom.registered_listener_list_lock,
- flags);
-
- pr_debug("waking up rcv_req_wq and "
- "waiting for send_resp_wq\n");
- if (wait_event_freezable(qseecom.send_resp_wq,
- __qseecom_listener_has_sent_rsp(data))) {
- pr_warning("qseecom Interrupted: exiting send_cmd loop\n");
- return -ERESTARTSYS;
- }
-
- if (data->abort) {
- pr_err("Aborting driver\n");
- return -ENODEV;
- }
- qseecom.send_resp_flag = 0;
- cmd.cmd_type = TZ_SCHED_CMD_PENDING;
- ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *)&cmd,
- sizeof(cmd), &resp, sizeof(resp));
- if (ret) {
- pr_err("qseecom_scm_call failed with err: %d\n", ret);
- return ret;
- }
- }
- return ret;
-}
-
int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr,
struct qseecom_send_svc_cmd_req *req_ptr,
struct qseecom_client_send_service_ireq *send_svc_ireq_ptr)
@@ -1171,10 +994,8 @@
pr_err("copy_from_user failed\n");
return ret;
}
- if (qseecom.qseos_version == QSEOS_VERSION_14)
- ret = __qseecom_send_cmd(data, &req);
- else
- ret = __qseecom_send_cmd_legacy(data, &req);
+ ret = __qseecom_send_cmd(data, &req);
+
if (ret)
return ret;
@@ -1289,12 +1110,9 @@
ret = __qseecom_update_with_phy_addr(&req);
if (ret)
return ret;
- if (qseecom.qseos_version == QSEOS_VERSION_14)
- ret = __qseecom_send_cmd(data, &send_cmd_req);
- else
- ret = __qseecom_send_cmd_legacy(data, &send_cmd_req);
- __qseecom_send_cmd_req_clean_up(&req);
+ ret = __qseecom_send_cmd(data, &send_cmd_req);
+ __qseecom_send_cmd_req_clean_up(&req);
if (ret)
return ret;
@@ -1333,12 +1151,7 @@
return -ENODEV;
}
this_lstnr->rcv_req_flag = 0;
- if (qseecom.qseos_version == QSEOS_VERSION_13) {
- if (*((uint32_t *)this_lstnr->sb_virt) != 0)
- break;
- } else {
- break;
- }
+ break;
}
return ret;
}
@@ -1636,11 +1449,6 @@
uint32_t len;
ion_phys_addr_t pa;
- if (qseecom.qseos_version == QSEOS_VERSION_13) {
- pr_err("This functionality is UNSUPPORTED in version 1.3\n");
- return -EINVAL;
- }
-
*handle = kzalloc(sizeof(struct qseecom_handle), GFP_KERNEL);
if (!(*handle)) {
pr_err("failed to allocate memory for kernel client handle\n");
@@ -1791,10 +1599,6 @@
unsigned long flags = 0;
bool found_handle = false;
- if (qseecom.qseos_version == QSEOS_VERSION_13) {
- pr_err("This functionality is UNSUPPORTED in version 1.3\n");
- return -EINVAL;
- }
if ((handle == NULL) || (*handle == NULL)) {
pr_err("Handle is not initialized\n");
return -EINVAL;
@@ -1835,11 +1639,6 @@
struct qseecom_send_cmd_req req = {0, 0, 0, 0};
struct qseecom_dev_handle *data;
- if (qseecom.qseos_version == QSEOS_VERSION_13) {
- pr_err("This functionality is UNSUPPORTED in version 1.3\n");
- return -EINVAL;
- }
-
if (handle == NULL) {
pr_err("Handle is not initialized\n");
return -EINVAL;
@@ -2868,11 +2667,6 @@
}
case QSEECOM_IOCTL_LOAD_EXTERNAL_ELF_REQ: {
data->released = true;
- if (qseecom.qseos_version == QSEOS_VERSION_13) {
- pr_err("Loading External elf image unsupported in rev 0x13\n");
- ret = -EINVAL;
- break;
- }
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
ret = qseecom_load_external_elf(data, argp);
@@ -2884,11 +2678,6 @@
}
case QSEECOM_IOCTL_UNLOAD_EXTERNAL_ELF_REQ: {
data->released = true;
- if (qseecom.qseos_version == QSEOS_VERSION_13) {
- pr_err("Unloading External elf image unsupported in rev 0x13\n");
- ret = -EINVAL;
- break;
- }
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
ret = qseecom_unload_external_elf(data);
@@ -2992,23 +2781,7 @@
data->released = false;
init_waitqueue_head(&data->abort_wq);
atomic_set(&data->ioctl_count, 0);
- if (qseecom.qseos_version == QSEOS_VERSION_13) {
- int pil_error;
- mutex_lock(&pil_access_lock);
- if (pil_ref_cnt == 0) {
- pil = subsystem_get("tzapps");
- if (IS_ERR(pil)) {
- pr_err("Playready PIL image load failed\n");
- pil_error = PTR_ERR(pil);
- pil = NULL;
- pr_debug("tzapps image load FAILED\n");
- mutex_unlock(&pil_access_lock);
- return pil_error;
- }
- }
- pil_ref_cnt++;
- mutex_unlock(&pil_access_lock);
- }
+
return ret;
}
@@ -3046,13 +2819,6 @@
if (data->perf_enabled == true)
qsee_disable_clock_vote(data, CLK_DFAB);
- if (qseecom.qseos_version == QSEOS_VERSION_13) {
- mutex_lock(&pil_access_lock);
- if (pil_ref_cnt == 1)
- subsystem_put(pil);
- pil_ref_cnt--;
- mutex_unlock(&pil_access_lock);
- }
kfree(data);
return ret;
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 4c59a2a..af5442a 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -2332,6 +2332,7 @@
props.num_pipes = pdata->usb_bam_num_pipes;
props.callback = usb_bam_sps_events;
props.user = bam_enable_strings[bam_idx];
+ props.options = SPS_BAM_OPT_IRQ_WAKEUP;
/*
* HSUSB and HSIC Cores don't support RESET ACK signal to BAMs
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 80e9e87..678627a 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3793,9 +3793,7 @@
pm_runtime_no_callbacks(&udc->gadget.dev);
pm_runtime_enable(&udc->gadget.dev);
- retval = register_trace_usb_daytona_invalid_access(dump_usb_info,
- NULL);
- if (retval)
+ if (register_trace_usb_daytona_invalid_access(dump_usb_info, NULL))
pr_err("Registering trace failed\n");
_udc = udc;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index ab91320..fe10189 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -614,6 +614,37 @@
}
} /* hdmi_tx_set_audio_switch_node */
+static int hdmi_tx_config_avmute(struct hdmi_tx_ctrl *hdmi_ctrl, int set)
+{
+ struct dss_io_data *io;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: Core io is not initialized\n", __func__);
+ return -EINVAL;
+ }
+
+ if (set)
+ DSS_REG_W(io, HDMI_GC,
+ DSS_REG_R(io, HDMI_GC) | BIT(0));
+ else
+ DSS_REG_W(io, HDMI_GC,
+ DSS_REG_R(io, HDMI_GC) & ~BIT(0));
+
+ /* Enable AV Mute tranmission here */
+ DSS_REG_W(io, HDMI_VBI_PKT_CTRL,
+ DSS_REG_R(io, HDMI_VBI_PKT_CTRL) | (BIT(4) & BIT(5)));
+
+ DEV_DBG("%s: AVMUTE %s\n", __func__, set ? "set" : "cleared");
+
+ return 0;
+} /* hdmi_tx_config_avmute */
+
void hdmi_tx_hdcp_cb(void *ptr, enum hdmi_hdcp_state status)
{
int rc = 0;
@@ -629,13 +660,25 @@
switch (status) {
case HDCP_STATE_AUTHENTICATED:
- if (hdmi_ctrl->hpd_state)
+ if (hdmi_ctrl->hpd_state) {
+ /* Clear AV Mute */
+ rc = hdmi_tx_config_avmute(hdmi_ctrl, 0);
+ if (rc)
+ DEV_ERR("%s: Failed to clear av mute. rc=%d\n",
+ __func__, rc);
hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1, false);
+ }
break;
case HDCP_STATE_AUTH_FAIL:
hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
if (hdmi_ctrl->hpd_state) {
+ /* Set AV Mute */
+ rc = hdmi_tx_config_avmute(hdmi_ctrl, 1);
+ if (rc)
+ DEV_ERR("%s: Failed to set av mute. rc=%d\n",
+ __func__, rc);
+
DEV_DBG("%s: Reauthenticating\n", __func__);
rc = hdmi_hdcp_reauthenticate(
hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]);
@@ -2743,6 +2786,12 @@
case MDSS_EVENT_PANEL_ON:
if (hdmi_ctrl->hdcp_feature_on && hdmi_ctrl->present_hdcp) {
+ /* Set AV Mute before starting authentication */
+ rc = hdmi_tx_config_avmute(hdmi_ctrl, 1);
+ if (rc)
+ DEV_ERR("%s: Failed to set av mute. rc=%d\n",
+ __func__, rc);
+
DEV_DBG("%s: Starting HDCP authentication\n", __func__);
rc = hdmi_hdcp_authenticate(
hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index e346082..4b763aa 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1505,7 +1505,6 @@
mdss_mdp_pp_setup_locked(ctl);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl->flush_bits);
if (sctl) {
- mdss_mdp_pp_setup_locked(sctl);
mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH,
sctl->flush_bits);
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index fcc1c1a..9d28265 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -888,14 +888,19 @@
return ret;
}
-static int pp_mixer_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
+static int pp_mixer_setup(u32 disp_num,
struct mdss_mdp_mixer *mixer)
{
u32 flags, offset, dspp_num, opmode = 0;
struct mdp_pgc_lut_data *pgc_config;
struct pp_sts_type *pp_sts;
+ struct mdss_mdp_ctl *ctl;
dspp_num = mixer->num;
+ if (!mixer || !mixer->ctl)
+ return -EINVAL;
+ ctl = mixer->ctl;
+
/* no corresponding dspp */
if ((mixer->type != MDSS_MDP_MIXER_TYPE_INTF) ||
(dspp_num >= MDSS_MDP_MAX_DSPP))
@@ -1003,8 +1008,7 @@
return ret;
}
-static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
- struct mdss_mdp_mixer *mixer)
+static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer)
{
u32 flags, base, offset, dspp_num, opmode = 0;
struct mdp_dither_cfg_data *dither_cfg;
@@ -1014,12 +1018,12 @@
char __iomem *basel;
int i, ret = 0;
struct mdss_data_type *mdata;
+ struct mdss_mdp_ctl *ctl;
- mdata = ctl->mdata;
-
- if (!mixer || !ctl || !mdata)
+ if (!mixer || !mixer->ctl || !mixer->ctl->mdata)
return -EINVAL;
-
+ ctl = mixer->ctl;
+ mdata = ctl->mdata;
dspp_num = mixer->num;
/* no corresponding dspp */
if ((mixer->type != MDSS_MDP_MIXER_TYPE_INTF) ||
@@ -1174,12 +1178,12 @@
mutex_lock(&mdss_pp_mutex);
if (ctl->mixer_left) {
- pp_mixer_setup(disp_num, ctl, ctl->mixer_left);
- pp_dspp_setup(disp_num, ctl, ctl->mixer_left);
+ pp_mixer_setup(disp_num, ctl->mixer_left);
+ pp_dspp_setup(disp_num, ctl->mixer_left);
}
if (ctl->mixer_right) {
- pp_mixer_setup(disp_num, ctl, ctl->mixer_right);
- pp_dspp_setup(disp_num, ctl, ctl->mixer_right);
+ pp_mixer_setup(disp_num, ctl->mixer_right);
+ pp_dspp_setup(disp_num, ctl->mixer_right);
}
/* clear dirty flag */
if (disp_num < MDSS_BLOCK_DISP_NUM)
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index aead2d2..6cd4995 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -112,9 +112,10 @@
struct timeval in_time, out_time;
void *cookie;
int32_t *status;
-
+ int32_t duplicate_output;
+ uint32_t duplicate_identity;
struct msm_cpp_buffer_info_t input_buffer_info;
- struct msm_cpp_buffer_info_t output_buffer_info;
+ struct msm_cpp_buffer_info_t output_buffer_info[2];
};
struct cpp_hw_info {
diff --git a/include/sound/Kbuild b/include/sound/Kbuild
index edadaa9..60847b0 100644
--- a/include/sound/Kbuild
+++ b/include/sound/Kbuild
@@ -12,3 +12,4 @@
header-y += compress_params.h
header-y += compress_offload.h
header-y += lsm_params.h
+header-y += voice_params.h
diff --git a/include/sound/voice_params.h b/include/sound/voice_params.h
new file mode 100644
index 0000000..43e3b9d
--- /dev/null
+++ b/include/sound/voice_params.h
@@ -0,0 +1,14 @@
+#ifndef __VOICE_PARAMS_H__
+#define __VOICE_PARAMS_H__
+
+#include <linux/types.h>
+#include <sound/asound.h>
+
+enum voice_lch_mode {
+ VOICE_LCH_START = 1,
+ VOICE_LCH_STOP
+};
+
+#define SNDRV_VOICE_IOCTL_LCH _IOW('U', 0x00, enum voice_lch_mode)
+
+#endif
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 25bb72f..506eae8 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -281,6 +281,58 @@
return ret;
}
+static int msm_pcm_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_voice *prtd = runtime->private_data;
+ uint16_t session_id = get_session_id(prtd);
+ enum voice_lch_mode lch_mode;
+ int ret = 0;
+
+ switch (cmd) {
+ case SNDRV_VOICE_IOCTL_LCH:
+ if (copy_from_user(&lch_mode, (void *)arg,
+ sizeof(enum voice_lch_mode))) {
+ pr_err("%s: Copy from user failed, size %d\n", __func__,
+ sizeof(enum voice_lch_mode));
+
+ ret = -EFAULT;
+ break;
+ }
+
+ pr_debug("%s: %s lch_mode:%d\n",
+ __func__, substream->pcm->id, lch_mode);
+
+ switch (lch_mode) {
+ case VOICE_LCH_START:
+ case VOICE_LCH_STOP:
+ ret = voc_set_lch(session_id, lch_mode);
+ break;
+
+ default:
+ pr_err("%s: Invalid LCH MODE %d\n", __func__, lch_mode);
+
+ ret = -EFAULT;
+ }
+
+ break;
+ default:
+ pr_debug("%s: Falling into default snd_lib_ioctl cmd 0x%x\n",
+ __func__, cmd);
+
+ ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+ break;
+ }
+
+ if (!ret)
+ pr_debug("%s: ret %d\n", __func__, ret);
+ else
+ pr_err("%s: cmd 0x%x failed %d\n", __func__, cmd, ret);
+
+ return ret;
+}
+
static int msm_voice_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -581,11 +633,12 @@
};
static struct snd_pcm_ops msm_pcm_ops = {
- .open = msm_pcm_open,
- .hw_params = msm_pcm_hw_params,
- .close = msm_pcm_close,
- .prepare = msm_pcm_prepare,
- .trigger = msm_pcm_trigger,
+ .open = msm_pcm_open,
+ .hw_params = msm_pcm_hw_params,
+ .close = msm_pcm_close,
+ .prepare = msm_pcm_prepare,
+ .trigger = msm_pcm_trigger,
+ .ioctl = msm_pcm_ioctl,
};
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 5f89e4a..d7e1ef0 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -1444,6 +1444,34 @@
return -EINVAL;
}
+static void voc_get_tx_rx_topology(struct voice_data *v,
+ uint32_t *tx_topology_id,
+ uint32_t *rx_topology_id)
+{
+ uint32_t tx_id = 0;
+ uint32_t rx_id = 0;
+
+ if (v->lch_mode == VOICE_LCH_START) {
+ pr_debug("%s: Setting TX and RX topology to NONE for LCH\n",
+ __func__);
+
+ tx_id = VSS_IVOCPROC_TOPOLOGY_ID_NONE;
+ rx_id = VSS_IVOCPROC_TOPOLOGY_ID_NONE;
+ } else {
+ /* Use default topology if invalid value in ACDB */
+ tx_id = get_voice_tx_topology();
+ if (tx_id == 0)
+ tx_id = VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS;
+
+ rx_id = get_voice_rx_topology();
+ if (rx_id == 0)
+ rx_id = VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
+ }
+
+ *tx_topology_id = tx_id;
+ *rx_topology_id = rx_id;
+}
+
static int voice_send_set_device_cmd(struct voice_data *v)
{
struct cvp_set_device_cmd cvp_setdev_cmd;
@@ -1474,26 +1502,22 @@
cvp_setdev_cmd.hdr.src_port = v->session_id;
cvp_setdev_cmd.hdr.dest_port = cvp_handle;
cvp_setdev_cmd.hdr.token = 0;
- cvp_setdev_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_DEVICE;
+ cvp_setdev_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_DEVICE_V2;
- /* Use default topology if invalid value in ACDB */
- cvp_setdev_cmd.cvp_set_device.tx_topology_id =
- get_voice_tx_topology();
- if (cvp_setdev_cmd.cvp_set_device.tx_topology_id == 0)
- cvp_setdev_cmd.cvp_set_device.tx_topology_id =
- VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS;
+ voc_get_tx_rx_topology(v,
+ &cvp_setdev_cmd.cvp_set_device_v2.tx_topology_id,
+ &cvp_setdev_cmd.cvp_set_device_v2.rx_topology_id);
- cvp_setdev_cmd.cvp_set_device.rx_topology_id =
- get_voice_rx_topology();
- if (cvp_setdev_cmd.cvp_set_device.rx_topology_id == 0)
- cvp_setdev_cmd.cvp_set_device.rx_topology_id =
- VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
- cvp_setdev_cmd.cvp_set_device.tx_port_id = v->dev_tx.port_id;
- cvp_setdev_cmd.cvp_set_device.rx_port_id = v->dev_rx.port_id;
+ cvp_setdev_cmd.cvp_set_device_v2.tx_port_id = v->dev_tx.port_id;
+ cvp_setdev_cmd.cvp_set_device_v2.rx_port_id = v->dev_rx.port_id;
+ cvp_setdev_cmd.cvp_set_device_v2.vocproc_mode =
+ VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING;
+ cvp_setdev_cmd.cvp_set_device_v2.ec_ref_port_id =
+ VSS_IVOCPROC_PORT_ID_NONE;
pr_debug("topology=%d , tx_port_id=%d, rx_port_id=%d\n",
- cvp_setdev_cmd.cvp_set_device.tx_topology_id,
- cvp_setdev_cmd.cvp_set_device.tx_port_id,
- cvp_setdev_cmd.cvp_set_device.rx_port_id);
+ cvp_setdev_cmd.cvp_set_device_v2.tx_topology_id,
+ cvp_setdev_cmd.cvp_set_device_v2.tx_port_id,
+ cvp_setdev_cmd.cvp_set_device_v2.rx_port_id);
v->cvp_state = CMD_STATUS_FAIL;
ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_setdev_cmd);
@@ -2249,18 +2273,9 @@
cvp_session_cmd.hdr.opcode =
VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2;
- /* Use default topology if invalid value in ACDB */
- cvp_session_cmd.cvp_session.tx_topology_id =
- get_voice_tx_topology();
- if (cvp_session_cmd.cvp_session.tx_topology_id == 0)
- cvp_session_cmd.cvp_session.tx_topology_id =
- VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS;
-
- cvp_session_cmd.cvp_session.rx_topology_id =
- get_voice_rx_topology();
- if (cvp_session_cmd.cvp_session.rx_topology_id == 0)
- cvp_session_cmd.cvp_session.rx_topology_id =
- VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
+ voc_get_tx_rx_topology(v,
+ &cvp_session_cmd.cvp_session.tx_topology_id,
+ &cvp_session_cmd.cvp_session.rx_topology_id);
cvp_session_cmd.cvp_session.direction = 2; /*tx and rx*/
cvp_session_cmd.cvp_session.tx_port_id = v->dev_tx.port_id;
@@ -2645,6 +2660,9 @@
if (v->dtmf_rx_detect_en)
voice_send_dtmf_rx_detection_cmd(v, 0);
+ /* reset LCH mode */
+ v->lch_mode = 0;
+
/* detach VOCPROC and wait for response from mvm */
mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
@@ -2884,7 +2902,7 @@
return -EINVAL;
}
-static int voice_send_mute_cmd(struct voice_data *v)
+static int voice_send_stream_mute_cmd(struct voice_data *v)
{
struct cvs_set_mute_cmd cvs_mute_cmd;
int ret = 0;
@@ -2912,7 +2930,7 @@
cvs_mute_cmd.hdr.token = 0;
cvs_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
cvs_mute_cmd.cvs_set_mute.direction = VSS_IVOLUME_DIRECTION_TX;
- cvs_mute_cmd.cvs_set_mute.mute_flag = v->dev_tx.mute;
+ cvs_mute_cmd.cvs_set_mute.mute_flag = v->stream_tx.stream_mute;
cvs_mute_cmd.cvs_set_mute.ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
v->cvs_state = CMD_STATUS_FAIL;
@@ -2937,7 +2955,8 @@
return -EINVAL;
}
-static int voice_send_rx_device_mute_cmd(struct voice_data *v)
+static int voice_send_device_mute_cmd(struct voice_data *v, uint16_t direction,
+ uint16_t mute_flag)
{
struct cvp_set_mute_cmd cvp_mute_cmd;
int ret = 0;
@@ -2963,8 +2982,8 @@
cvp_mute_cmd.hdr.dest_port = voice_get_cvp_handle(v);
cvp_mute_cmd.hdr.token = 0;
cvp_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
- cvp_mute_cmd.cvp_set_mute.direction = VSS_IVOLUME_DIRECTION_RX;
- cvp_mute_cmd.cvp_set_mute.mute_flag = v->dev_rx.mute;
+ cvp_mute_cmd.cvp_set_mute.direction = direction;
+ cvp_mute_cmd.cvp_set_mute.mute_flag = mute_flag;
cvp_mute_cmd.cvp_set_mute.ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
v->cvp_state = CMD_STATUS_FAIL;
@@ -3493,7 +3512,7 @@
int ret = 0;
if (v == NULL) {
- pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+ pr_err("%s: Invalid session_id 0x%x\n", __func__, session_id);
return -EINVAL;
}
@@ -3503,7 +3522,7 @@
if (v->voc_state == VOC_CHANGE) {
ret = voice_send_set_device_cmd(v);
if (ret < 0) {
- pr_err("%s: set device failed\n", __func__);
+ pr_err("%s: Set device failed\n", __func__);
goto fail;
}
@@ -3511,9 +3530,35 @@
voice_send_cvp_register_cal_cmd(v);
voice_send_cvp_register_vol_cal_cmd(v);
+ if (v->lch_mode == VOICE_LCH_START) {
+ pr_debug("%s: TX and RX mute ON\n", __func__);
+
+ voice_send_device_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_TX,
+ VSS_IVOLUME_MUTE_ON);
+ voice_send_device_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_RX,
+ VSS_IVOLUME_MUTE_ON);
+ } else if (v->lch_mode == VOICE_LCH_STOP) {
+ pr_debug("%s: TX and RX mute OFF\n", __func__);
+
+ voice_send_device_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_TX,
+ VSS_IVOLUME_MUTE_OFF);
+ voice_send_device_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_RX,
+ VSS_IVOLUME_MUTE_OFF);
+ /* Reset lch mode when VOICE_LCH_STOP is recieved */
+ v->lch_mode = 0;
+ } else {
+ pr_debug("%s: Mute commands not sent for lch_mode=%d\n",
+ __func__, v->lch_mode);
+ }
+
ret = voice_send_enable_vocproc_cmd(v);
if (ret < 0) {
- pr_err("%s: enable vocproc failed %d\n", __func__, ret);
+ pr_err("%s: Enable vocproc failed %d\n", __func__, ret);
+
goto fail;
}
@@ -3593,12 +3638,12 @@
mutex_lock(&v->lock);
- v->dev_tx.mute = mute;
+ v->stream_tx.stream_mute = mute;
if ((v->voc_state == VOC_RUN) ||
(v->voc_state == VOC_CHANGE) ||
(v->voc_state == VOC_STANDBY))
- ret = voice_send_mute_cmd(v);
+ ret = voice_send_stream_mute_cmd(v);
mutex_unlock(&v->lock);
@@ -3618,10 +3663,12 @@
mutex_lock(&v->lock);
- v->dev_rx.mute = mute;
+ v->dev_rx.dev_mute = mute;
if (v->voc_state == VOC_RUN)
- ret = voice_send_rx_device_mute_cmd(v);
+ ret = voice_send_device_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_RX,
+ v->dev_rx.dev_mute);
mutex_unlock(&v->lock);
@@ -3641,7 +3688,7 @@
mutex_lock(&v->lock);
- ret = v->dev_rx.mute;
+ ret = v->dev_rx.dev_mute;
mutex_unlock(&v->lock);
@@ -3960,6 +4007,49 @@
return ret;
}
+int voc_set_lch(uint16_t session_id, enum voice_lch_mode lch_mode)
+{
+ struct voice_data *v = voice_get_session(session_id);
+ int ret = 0;
+
+ if (v == NULL) {
+ pr_err("%s: Invalid session_id 0x%x\n", __func__, session_id);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ mutex_lock(&v->lock);
+ if (v->lch_mode == lch_mode) {
+ pr_debug("%s: Session %d already in LCH mode %d\n",
+ __func__, session_id, lch_mode);
+
+ mutex_unlock(&v->lock);
+ goto done;
+ }
+
+ v->lch_mode = lch_mode;
+ mutex_unlock(&v->lock);
+
+ ret = voc_disable_cvp(session_id);
+ if (ret < 0) {
+ pr_err("%s: voc_disable_cvp failed ret=%d\n", __func__, ret);
+
+ goto done;
+ }
+
+ /* Mute and topology_none will be set as part of voc_enable_cvp() */
+ ret = voc_enable_cvp(session_id);
+ if (ret < 0) {
+ pr_err("%s: voc_enable_cvp failed ret=%d\n", __func__, ret);
+
+ goto done;
+ }
+
+done:
+ return ret;
+}
+
int voc_resume_voice_call(uint16_t session_id)
{
struct voice_data *v = voice_get_session(session_id);
@@ -4580,7 +4670,7 @@
v->cvp_state = CMD_STATUS_SUCCESS;
wake_up(&v->cvp_wait);
break;
- case VSS_IVOCPROC_CMD_SET_DEVICE:
+ case VSS_IVOCPROC_CMD_SET_DEVICE_V2:
case VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX:
case VSS_IVOCPROC_CMD_ENABLE:
case VSS_IVOCPROC_CMD_DISABLE:
@@ -4769,13 +4859,16 @@
/* initialize dev_rx and dev_tx */
common.voice[i].dev_rx.volume = common.default_vol_val;
- common.voice[i].dev_rx.mute = 0;
- common.voice[i].dev_tx.mute = common.default_mute_val;
+ common.voice[i].dev_rx.dev_mute = 0;
+ common.voice[i].dev_tx.dev_mute = 0;
+ common.voice[i].stream_rx.stream_mute = common.default_mute_val;
+ common.voice[i].stream_tx.stream_mute = common.default_mute_val;
common.voice[i].dev_tx.port_id = 0x100B;
common.voice[i].dev_rx.port_id = 0x100A;
common.voice[i].sidetone_gain = 0x512;
common.voice[i].dtmf_rx_detect_en = 0;
+ common.voice[i].lch_mode = 0;
common.voice[i].voc_state = VOC_INIT;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index ef5c6e3..c85e0b3 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -14,6 +14,7 @@
#include <mach/qdsp6v2/apr.h>
#include <linux/msm_ion.h>
+#include <sound/voice_params.h>
#define MAX_VOC_PKT_SIZE 642
#define SESSION_NAME_LEN 20
@@ -41,11 +42,15 @@
void *cb_handle;
};
-/* Device information payload structure */
+/* Stream information payload structure */
+struct stream_data {
+ uint32_t stream_mute;
+};
+/* Device information payload structure */
struct device_data {
uint32_t volume; /* in index */
- uint32_t mute;
+ uint32_t dev_mute;
uint32_t sample;
uint32_t enabled;
uint32_t dev_id;
@@ -904,7 +909,7 @@
#define APRV2_IBASIC_CMD_DESTROY_SESSION 0x0001003C
-#define VSS_IVOCPROC_CMD_SET_DEVICE 0x000100C4
+#define VSS_IVOCPROC_CMD_SET_DEVICE_V2 0x000112C6
#define VSS_IVOCPROC_CMD_SET_VP3_DATA 0x000110EB
@@ -1042,8 +1047,8 @@
*/
} __packed;
-struct vss_ivocproc_cmd_set_device_t {
- uint32_t tx_port_id;
+struct vss_ivocproc_cmd_set_device_v2_t {
+ uint16_t tx_port_id;
/*
* TX device port ID which vocproc will connect to.
* VSS_IVOCPROC_PORT_ID_NONE means vocproc will not connect to any port.
@@ -1054,7 +1059,7 @@
* VSS_IVOCPROC_TOPOLOGY_ID_NONE means vocproc does not contain any
* pre/post-processing blocks and is pass-through.
*/
- int32_t rx_port_id;
+ uint16_t rx_port_id;
/*
* RX device port ID which vocproc will connect to.
* VSS_IVOCPROC_PORT_ID_NONE means vocproc will not connect to any port.
@@ -1065,6 +1070,15 @@
* VSS_IVOCPROC_TOPOLOGY_ID_NONE means vocproc does not contain any
* pre/post-processing blocks and is pass-through.
*/
+ uint32_t vocproc_mode;
+ /* Vocproc mode. The supported values:
+ * VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING - 0x00010F7C
+ * VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING - 0x00010F7D
+ */
+ uint16_t ec_ref_port_id;
+ /* Port ID to which the vocproc connects for receiving
+ * echo
+ */
} __packed;
struct vss_ivocproc_cmd_register_device_config_t {
@@ -1128,7 +1142,7 @@
struct cvp_set_device_cmd {
struct apr_hdr hdr;
- struct vss_ivocproc_cmd_set_device_t cvp_set_device;
+ struct vss_ivocproc_cmd_set_device_v2_t cvp_set_device_v2;
} __packed;
struct cvp_set_vp3_data_cmd {
@@ -1230,10 +1244,14 @@
wait_queue_head_t cvs_wait;
wait_queue_head_t cvp_wait;
- /* cache the values related to Rx and Tx */
+ /* Cache the values related to Rx and Tx devices */
struct device_data dev_rx;
struct device_data dev_tx;
+ /* Cache the values related to Rx and Tx streams */
+ struct stream_data stream_rx;
+ struct stream_data stream_tx;
+
u32 mvm_state;
u32 cvs_state;
u32 cvp_state;
@@ -1257,6 +1275,8 @@
uint32_t fens_enable;
uint32_t dtmf_rx_detect_en;
+ /* Local Call Hold mode */
+ uint8_t lch_mode;
struct voice_dev_route_state voc_route_state;
@@ -1353,6 +1373,7 @@
int voc_end_voice_call(uint16_t session_id);
int voc_standby_voice_call(uint16_t session_id);
int voc_resume_voice_call(uint16_t session_id);
+int voc_set_lch(uint16_t session_id, enum voice_lch_mode lch_mode);
int voc_set_rxtx_port(uint16_t session_id,
uint32_t dev_port_id,
uint32_t dev_type);