msm: vidc: Add support for FW version check

Encoder VPE and decoder DS features need to be supported
on targets which are using Venus 1.4 FW. FW sends version
as part of system property message. Driver needs to process
the version and reject VPE and DS features accordingly.

Change-Id: I600d402f36aa9bb484fc8dca76fce7d8f9120521
Signed-off-by: Praneeth Paladugu <ppaladug@codeaurora.org>
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 2bd038d..101b148 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1209,7 +1209,7 @@
 				version[i] = ' ';
 		}
 		version[i] = '\0';
-		dprintk(VIDC_INFO, "F/W version: %s\n", version);
+		dprintk(VIDC_DBG, "F/W version: %s\n", version);
 	}
 
 	smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 6a2be9b..975f98b 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -876,8 +876,6 @@
 				"Failed to get buffer requirements: %d\n", rc);
 			break;
 		}
-		inst->capability.pixelprocess_capabilities =
-			call_hfi_op(hdev, get_core_capabilities);
 		*num_planes = 1;
 		mutex_lock(&inst->lock);
 		*num_buffers = inst->buff_req.buffer[0].buffer_count_actual =
@@ -1983,12 +1981,11 @@
 {
 
 	int rc = 0, c = 0;
-	struct hfi_device *hdev;
 
 	struct msm_vidc_inst *inst = container_of(ctrl->handler,
 					struct msm_vidc_inst, ctrl_handler);
 
-	if (!inst || !inst->core || !inst->core->device) {
+	if (!inst) {
 		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
 		return -EINVAL;
 	}
@@ -2001,10 +1998,6 @@
 		goto failed_open_done;
 	}
 
-	hdev = inst->core->device;
-	inst->capability.pixelprocess_capabilities =
-		call_hfi_op(hdev, get_core_capabilities);
-
 	for (c = 0; c < ctrl->ncontrols; ++c) {
 		if (ctrl->cluster[c]->is_new) {
 			struct v4l2_ctrl *temp = ctrl->cluster[c];
@@ -2334,8 +2327,6 @@
 				dprintk(VIDC_ERR, "Failed to open instance\n");
 				goto exit;
 			}
-			inst->capability.pixelprocess_capabilities =
-				call_hfi_op(hdev, get_core_capabilities);
 			frame_sz.width = inst->prop.width[CAPTURE_PORT];
 			frame_sz.height = inst->prop.height[CAPTURE_PORT];
 			frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 73b5b7c..6da90c4 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -424,16 +424,20 @@
 {
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst = NULL;
+	struct hfi_device *hdev;
+
 	if (response) {
 		struct vidc_hal_session_init_done *session_init_done =
 			(struct vidc_hal_session_init_done *)
 			response->data;
 		inst = (struct msm_vidc_inst *)response->session_id;
-		if (!inst) {
-			dprintk(VIDC_ERR, "%s: invalid input parameters",
-				__func__);
+		if (!inst || !inst->core || !inst->core->device) {
+			dprintk(VIDC_ERR, "%s invalid parameters", __func__);
 			return;
 		}
+
+		hdev = inst->core->device;
+
 		if (!response->status && session_init_done) {
 			inst->capability.width = session_init_done->width;
 			inst->capability.height = session_init_done->height;
@@ -441,6 +445,8 @@
 				session_init_done->frame_rate;
 			inst->capability.scale_x = session_init_done->scale_x;
 			inst->capability.scale_y = session_init_done->scale_y;
+			inst->capability.pixelprocess_capabilities =
+				call_hfi_op(hdev, get_core_capabilities);
 			inst->capability.capability_set = true;
 			inst->capability.buffer_mode[CAPTURE_PORT] =
 				session_init_done->alloc_mode_out;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 6eba932..c2d8c38 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -23,6 +23,7 @@
 #include <mach/ocmem.h>
 #include <mach/scm.h>
 #include <mach/subsystem_restart.h>
+#include <mach/msm_smem.h>
 #include <asm/memory.h>
 #include "hfi_packetization.h"
 #include "venus_hfi.h"
@@ -3304,10 +3305,40 @@
 
 int venus_hfi_get_core_capabilities(void)
 {
-	return HAL_VIDEO_ENCODER_ROTATION_CAPABILITY |
-		HAL_VIDEO_ENCODER_SCALING_CAPABILITY |
-		HAL_VIDEO_ENCODER_DEINTERLACE_CAPABILITY |
-		HAL_VIDEO_DECODER_MULTI_STREAM_CAPABILITY;
+	int i = 0, rc = 0, j = 0, venus_version_length = 0;
+	u32 smem_block_size = 0;
+	u8 *smem_table_ptr;
+	char version[256];
+	const u32 version_string_size = 128;
+	char venus_version[] = "VIDEO.VE.1.4";
+	u8 version_info[256];
+	const u32 smem_image_index_venus = 14 * 128;
+	/* Venus version is stored at 14th entry in smem table */
+
+	smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
+			&smem_block_size);
+	if (smem_table_ptr &&
+			((smem_image_index_venus + version_string_size) <=
+			smem_block_size))
+		memcpy(version_info, smem_table_ptr + smem_image_index_venus,
+				version_string_size);
+
+	while (version_info[i++] != 'V' && i < version_string_size)
+		;
+
+	venus_version_length = strlen(venus_version);
+	for (i--, j = 0; i < version_string_size && j < venus_version_length;
+		i++)
+		version[j++] = version_info[i];
+	version[venus_version_length] = '\0';
+	dprintk(VIDC_DBG, "F/W version retrieved : %s\n", version);
+
+	if (strcmp((const char *)version, (const char *)venus_version) == 0)
+		rc = HAL_VIDEO_ENCODER_ROTATION_CAPABILITY |
+			HAL_VIDEO_ENCODER_SCALING_CAPABILITY |
+			HAL_VIDEO_ENCODER_DEINTERLACE_CAPABILITY |
+			HAL_VIDEO_DECODER_MULTI_STREAM_CAPABILITY;
+	return rc;
 }
 
 int venus_hfi_capability_check(u32 fourcc, u32 width,