msm: vidc: Get the current performance level

This change supports client to get the current
performance level of the video driver via
IOCTL_GET_PERF_LEVEL. The current performance
level indicate the number of MBs per second
is being processed by video hardware.

Change-Id: Ic6f5b2b14e0d77bf801c4f857f8a0e20339c199f
Signed-off-by: Maheshwar Ajja <majja@codeaurora.org>
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index dac8f30..3637b6e 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -678,6 +678,30 @@
 		return true;
 }
 
+static u32 vid_dec_get_curr_perf_level(struct video_client_ctx *client_ctx,
+	u32 *perf_level)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	u32 vcd_status = VCD_ERR_FAIL;
+	u32 perf_lvl = 0;
+
+	if (!client_ctx)
+		return false;
+
+	vcd_property_hdr.prop_id = VCD_I_GET_CURR_PERF_LEVEL;
+	vcd_property_hdr.sz = sizeof(u32);
+	vcd_status = vcd_get_property(client_ctx->vcd_handle,
+				      &vcd_property_hdr, &perf_lvl);
+	if (vcd_status) {
+		ERR("VCD_I_GET_PERF_LEVEL failed!!");
+		*perf_level = 0;
+		return false;
+	} else {
+		*perf_level = perf_lvl;
+		return true;
+	}
+}
+
 static u32 vid_dec_set_turbo_clk(struct video_client_ctx *client_ctx)
 {
 	struct vcd_property_hdr vcd_property_hdr;
@@ -2106,6 +2130,24 @@
 		}
 		break;
 	}
+	case VDEC_IOCTL_GET_PERF_LEVEL:
+	{
+		u32 curr_perf_level;
+		if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+			return -EFAULT;
+		result = vid_dec_get_curr_perf_level(client_ctx,
+			&curr_perf_level);
+		if (!result) {
+			ERR("get_curr_perf_level failed!!");
+			return -EIO;
+		}
+		DBG("VDEC_IOCTL_GET_PERF_LEVEL %u\n",
+			curr_perf_level);
+		if (copy_to_user(vdec_msg.out,
+			&curr_perf_level, sizeof(u32)))
+			return -EFAULT;
+		break;
+	}
 	case VDEC_IOCTL_SET_PERF_CLK:
 	{
 		DBG("VDEC_IOCTL_SET_PERF_CLK\n");
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 5adfdc9..8714a0c2 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -1759,6 +1759,24 @@
 		}
 		break;
 	}
+	case VEN_IOCTL_GET_PERF_LEVEL:
+	{
+		u32 curr_perf_level;
+		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+			return -EFAULT;
+		result = vid_enc_get_curr_perf_level(client_ctx,
+			&curr_perf_level);
+		if (!result) {
+			ERR("get_curr_perf_level failed!!");
+			return -EIO;
+		}
+		DBG("VEN_IOCTL_GET_PERF_LEVEL %u\n",
+			curr_perf_level);
+		if (copy_to_user(venc_msg.out,
+			&curr_perf_level, sizeof(u32)))
+			return -EFAULT;
+		break;
+	}
 	case VEN_IOCTL_SET_AC_PREDICTION:
 	case VEN_IOCTL_GET_AC_PREDICTION:
 	case VEN_IOCTL_SET_RVLC:
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index cdfd693..136d5ee 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -2022,3 +2022,27 @@
 			return false;
 		}
 }
+
+u32 vid_enc_get_curr_perf_level(struct video_client_ctx *client_ctx,
+		u32 *curr_perf_level)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	u32 vcd_status = VCD_ERR_FAIL;
+	u32 curr_perf_lvl = 0;
+
+	if (!client_ctx)
+		return false;
+
+	vcd_property_hdr.prop_id = VCD_I_GET_CURR_PERF_LEVEL;
+	vcd_property_hdr.sz = sizeof(u32);
+	vcd_status = vcd_get_property(client_ctx->vcd_handle,
+					&vcd_property_hdr, &curr_perf_lvl);
+	if (vcd_status) {
+		ERR("VCD_I_GET_PERF_LEVEL failed!!");
+		*curr_perf_level = 0;
+		return false;
+	} else {
+		*curr_perf_level = curr_perf_lvl;
+		return true;
+	}
+}
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.h b/drivers/video/msm/vidc/common/enc/venc_internal.h
index e724b21..1d32b26 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.h
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.h
@@ -152,4 +152,7 @@
 u32 vid_enc_get_recon_buffer_size(struct video_client_ctx *client_ctx,
 		struct venc_recon_buff_size *venc_recon_size);
 
+u32 vid_enc_get_curr_perf_level(struct video_client_ctx *client_ctx,
+		u32 *curr_perf_level);
+
 #endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index 138ac1c..48583b7 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -327,6 +327,7 @@
 
 u32 vcd_disable_clock(struct vcd_dev_ctxt *dev_ctxt);
 
+u32 vcd_get_curr_perf_level(struct vcd_dev_ctxt *dev_ctxt);
 u32 vcd_set_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl);
 
 u32 vcd_update_clnt_perf_lvl
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index a8c99c1..36d312d 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -584,7 +584,8 @@
     (struct vcd_clnt_ctxt *cctxt,
      struct vcd_property_hdr *prop_hdr, void *prop_val)
 {
-	int rc;
+	int rc = VCD_ERR_FAIL;
+	u32 prop_handled = true;
 	VCD_MSG_LOW("vcd_get_property_cmn in %d:", cctxt->clnt_state.state);
 	VCD_MSG_LOW("property Id = %d", prop_hdr->prop_id);
 	if (!prop_hdr->sz || !prop_hdr->prop_id) {
@@ -592,13 +593,6 @@
 
 		return VCD_ERR_ILLEGAL_PARM;
 	}
-	rc = ddl_get_property(cctxt->ddl_handle, prop_hdr, prop_val);
-	if (rc) {
-		/* Some properties aren't known to ddl that we can handle */
-		if (prop_hdr->prop_id != VCD_I_VOP_TIMING_CONSTANT_DELTA)
-			VCD_FAILED_RETURN(rc, "Failed: ddl_set_property");
-	}
-
 	switch (prop_hdr->prop_id) {
 	case VCD_I_VOP_TIMING_CONSTANT_DELTA:
 	{
@@ -608,8 +602,30 @@
 		delta->constant_delta = cctxt->time_frame_delta;
 		rc = VCD_S_SUCCESS;
 	}
+	break;
+	case VCD_I_GET_CURR_PERF_LEVEL:
+	{
+		u32 curr_perf_level = 0;
+		curr_perf_level = vcd_get_curr_perf_level(
+			cctxt->dev_ctxt);
+		*(u32 *)prop_val = curr_perf_level;
+		VCD_MSG_LOW("%s: curr_perf_level = %u",
+			__func__, curr_perf_level);
+		rc = VCD_S_SUCCESS;
 	}
-	return rc;
+	break;
+	default:
+		prop_handled = false;
+	break;
+	}
+
+	if (prop_handled) {
+		VCD_MSG_LOW("%s: property %u handled at vcd level",
+			__func__, prop_hdr->prop_id);
+		return rc;
+	}
+
+	return ddl_get_property(cctxt->ddl_handle, prop_hdr, prop_val);
 }
 
 static u32 vcd_set_buffer_requirements_cmn
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
index 8198a74..d525768 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
@@ -299,6 +299,11 @@
 	return rc;
 }
 
+u32 vcd_get_curr_perf_level(struct vcd_dev_ctxt *dev_ctxt)
+{
+	return dev_ctxt->reqd_perf_lvl;
+}
+
 u32 vcd_set_perf_level(struct vcd_dev_ctxt *dev_ctxt, u32 perf_lvl)
 {
 	u32 rc = VCD_S_SUCCESS;
diff --git a/include/linux/msm_vidc_dec.h b/include/linux/msm_vidc_dec.h
index 7edf6cf..57dbaef 100644
--- a/include/linux/msm_vidc_dec.h
+++ b/include/linux/msm_vidc_dec.h
@@ -223,6 +223,10 @@
 #define VDEC_IOCTL_GET_ENABLE_SEC_METADATA \
 	_IOR(VDEC_IOCTL_MAGIC, 41, struct vdec_ioctl_msg)
 
+/*IOCTL params:GET: InputData - NULL, OutputData - unsigned int.*/
+#define VDEC_IOCTL_GET_PERF_LEVEL \
+	_IOR(VDEC_IOCTL_MAGIC, 42, struct vdec_ioctl_msg)
+
 enum vdec_picture {
 	PICTURE_TYPE_I,
 	PICTURE_TYPE_P,
diff --git a/include/linux/msm_vidc_enc.h b/include/linux/msm_vidc_enc.h
index 2e98f4c..8d191bf 100644
--- a/include/linux/msm_vidc_enc.h
+++ b/include/linux/msm_vidc_enc.h
@@ -468,6 +468,11 @@
 #define VEN_IOCTL_SET_VUI_BITSTREAM_RESTRICT_FLAG \
 	_IO(VEN_IOCTLBASE_ENC, 52)
 
+/*IOCTL params:GET: InputData - NULL, OutputData - unsigned int.*/
+#define VEN_IOCTL_GET_PERF_LEVEL \
+	_IOR(VEN_IOCTLBASE_ENC, 53, struct venc_ioctl_msg)
+
+
 struct venc_switch{
 	unsigned char	status;
 };
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index a6359df..8bcac81 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -61,7 +61,7 @@
 #define VCD_I_FREE_EXT_METABUFFER (VCD_START_BASE + 0x2D)
 #define VCD_I_ENABLE_SEC_METADATA (VCD_START_BASE + 0x2E)
 #define VCD_I_ENABLE_VUI_BITSTREAM_RESTRICT_FLAG (VCD_START_BASE + 0x2F)
-
+#define VCD_I_GET_CURR_PERF_LEVEL (VCD_START_BASE + 0x30)
 
 #define VCD_START_REQ      (VCD_START_BASE + 0x1000)
 #define VCD_I_REQ_IFRAME   (VCD_START_REQ + 0x1)