]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
media: vidc: Qualcomm video encoder/decoder driver
authorStanimir Varbanov <stanimir.varbanov@linaro.org>
Mon, 17 Aug 2015 12:38:23 +0000 (15:38 +0300)
committerSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Mon, 11 Jan 2016 09:54:01 +0000 (09:54 +0000)
add venus video encoder/decoder driver.

Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
44 files changed:
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/msm/Kconfig [new file with mode: 0644]
drivers/media/platform/msm/Makefile [new file with mode: 0644]
drivers/media/platform/msm/vidc/Kconfig [new file with mode: 0644]
drivers/media/platform/msm/vidc/Makefile [new file with mode: 0644]
drivers/media/platform/msm/vidc/hfi/hfi_packetization.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/hfi/hfi_packetization.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/hfi/hfi_response_handler.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/hfi/venus/venus_hfi.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/hfi/venus/venus_hfi.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/hfi/venus/vidc_hfi_io.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/hfi/vidc_hfi.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/hfi/vidc_hfi.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/hfi/vidc_hfi_api.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/hfi/vidc_hfi_helper.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_hfi_interface.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_internal-buffers.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_internal-buffers.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_media_info.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_smem.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_smem.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_v4l2_vidc.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vdec-ctrls.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vdec-ctrls.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vdec.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vdec.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_venc-ctrls.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_venc-ctrls.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_venc.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_venc.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vidc.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vidc_common.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vidc_common.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vidc_debug.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vidc_debug.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vidc_internal.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vidc_load.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vidc_load.h [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vidc_resources.c [new file with mode: 0644]
drivers/media/platform/msm/vidc/msm_vidc_resources.h [new file with mode: 0644]
include/uapi/linux/v4l2-controls.h
include/uapi/media/Kbuild [new file with mode: 0644]
include/uapi/media/msm-v4l2-controls.h [new file with mode: 0644]

index ccbc9742cb7aeca46b22edb65eaaae69ce00aa17..eb349cf4f114325f87f46bc7e6fc13ff4c891d1f 100644 (file)
@@ -119,6 +119,7 @@ source "drivers/media/platform/exynos4-is/Kconfig"
 source "drivers/media/platform/s5p-tv/Kconfig"
 source "drivers/media/platform/am437x/Kconfig"
 source "drivers/media/platform/xilinx/Kconfig"
+source "drivers/media/platform/msm/Kconfig"
 
 endif # V4L_PLATFORM_DRIVERS
 
index efa0295af87bfe089acb526329b1601e95756c89..722f18b4e3e4d873365ceca9accdc6d068adfa7d 100644 (file)
@@ -55,3 +55,5 @@ obj-$(CONFIG_VIDEO_AM437X_VPFE)               += am437x/
 obj-$(CONFIG_VIDEO_XILINX)             += xilinx/
 
 ccflags-y += -I$(srctree)/drivers/media/i2c
+
+obj-y  += msm/
diff --git a/drivers/media/platform/msm/Kconfig b/drivers/media/platform/msm/Kconfig
new file mode 100644 (file)
index 0000000..4f55c85
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# MSM camera configuration
+#
+
+comment "Qualcomm MSM Camera And Video"
+
+source "drivers/media/platform/msm/vidc/Kconfig"
diff --git a/drivers/media/platform/msm/Makefile b/drivers/media/platform/msm/Makefile
new file mode 100644 (file)
index 0000000..ef7d987
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the QCOM spcific video device drivers
+# based on V4L2.
+#
+
+obj-$(CONFIG_MSM_VIDC_V4L2)     += vidc/
diff --git a/drivers/media/platform/msm/vidc/Kconfig b/drivers/media/platform/msm/vidc/Kconfig
new file mode 100644 (file)
index 0000000..da3e8bf
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# VIDEO CORE
+#
+
+menuconfig MSM_VIDC_V4L2
+       tristate "Qualcomm MSM V4L2 based video driver"
+       depends on ARCH_QCOM && VIDEO_V4L2
+       select ARM64_DMA_USE_IOMMU
+       select VIDEOBUF2_DMA_CONTIG
diff --git a/drivers/media/platform/msm/vidc/Makefile b/drivers/media/platform/msm/vidc/Makefile
new file mode 100644 (file)
index 0000000..a333e29
--- /dev/null
@@ -0,0 +1,21 @@
+# Makefile for Qualcomm vidc driver
+
+ccflags-y += -Idrivers/media/platform/msm/vidc
+vidc-objs += \
+               msm_v4l2_vidc.o \
+               msm_internal-buffers.o \
+               msm_vidc_common.o \
+               msm_vdec.o \
+               msm_vdec-ctrls.o \
+               msm_venc.o \
+               msm_venc-ctrls.o \
+               msm_smem.o \
+               msm_vidc_debug.o \
+               msm_vidc_resources.o \
+               msm_vidc_load.o \
+               hfi/venus/venus_hfi.o \
+               hfi/hfi_response_handler.o \
+               hfi/hfi_packetization.o \
+               hfi/vidc_hfi.o \
+
+obj-$(CONFIG_MSM_VIDC_V4L2) += vidc.o
diff --git a/drivers/media/platform/msm/vidc/hfi/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi/hfi_packetization.c
new file mode 100644 (file)
index 0000000..7c6d123
--- /dev/null
@@ -0,0 +1,1799 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/log2.h>
+#include <linux/hash.h>
+
+#include "hfi_packetization.h"
+#include "msm_vidc_debug.h"
+
+/*
+ * Set up look-up tables to convert HAL_* to HFI_*.
+ * The tables below mostly take advantage of the fact that most
+ * HAL_* types are defined bitwise. So if we index them normally
+ * when declaring the tables, we end up with huge arrays with wasted
+ * space.  So before indexing them, we apply log2 to use a more
+ * sensible index.
+ */
+static int profile_table[] = {
+       [ilog2(HAL_H264_PROFILE_BASELINE)] = HFI_H264_PROFILE_BASELINE,
+       [ilog2(HAL_H264_PROFILE_MAIN)] = HFI_H264_PROFILE_MAIN,
+       [ilog2(HAL_H264_PROFILE_HIGH)] = HFI_H264_PROFILE_HIGH,
+       [ilog2(HAL_H264_PROFILE_CONSTRAINED_BASE)] =
+               HFI_H264_PROFILE_CONSTRAINED_BASE,
+       [ilog2(HAL_H264_PROFILE_CONSTRAINED_HIGH)] =
+               HFI_H264_PROFILE_CONSTRAINED_HIGH,
+       [ilog2(HAL_VPX_PROFILE_VERSION_1)] = HFI_VPX_PROFILE_VERSION_1,
+       [ilog2(HAL_MVC_PROFILE_STEREO_HIGH)] = HFI_H264_PROFILE_STEREO_HIGH,
+};
+
+static int entropy_mode[] = {
+       [ilog2(HAL_H264_ENTROPY_CAVLC)] = HFI_H264_ENTROPY_CAVLC,
+       [ilog2(HAL_H264_ENTROPY_CABAC)] = HFI_H264_ENTROPY_CABAC,
+};
+
+static int cabac_model[] = {
+       [ilog2(HAL_H264_CABAC_MODEL_0)] = HFI_H264_CABAC_MODEL_0,
+       [ilog2(HAL_H264_CABAC_MODEL_1)] = HFI_H264_CABAC_MODEL_1,
+       [ilog2(HAL_H264_CABAC_MODEL_2)] = HFI_H264_CABAC_MODEL_2,
+};
+
+static int color_format[] = {
+       [ilog2(HAL_COLOR_FORMAT_MONOCHROME)] = HFI_COLOR_FORMAT_MONOCHROME,
+       [ilog2(HAL_COLOR_FORMAT_NV12)] = HFI_COLOR_FORMAT_NV12,
+       [ilog2(HAL_COLOR_FORMAT_NV21)] = HFI_COLOR_FORMAT_NV21,
+       [ilog2(HAL_COLOR_FORMAT_NV12_4x4TILE)] = HFI_COLOR_FORMAT_NV12_4x4TILE,
+       [ilog2(HAL_COLOR_FORMAT_NV21_4x4TILE)] = HFI_COLOR_FORMAT_NV21_4x4TILE,
+       [ilog2(HAL_COLOR_FORMAT_YUYV)] = HFI_COLOR_FORMAT_YUYV,
+       [ilog2(HAL_COLOR_FORMAT_YVYU)] = HFI_COLOR_FORMAT_YVYU,
+       [ilog2(HAL_COLOR_FORMAT_UYVY)] = HFI_COLOR_FORMAT_UYVY,
+       [ilog2(HAL_COLOR_FORMAT_VYUY)] = HFI_COLOR_FORMAT_VYUY,
+       [ilog2(HAL_COLOR_FORMAT_RGB565)] = HFI_COLOR_FORMAT_RGB565,
+       [ilog2(HAL_COLOR_FORMAT_BGR565)] = HFI_COLOR_FORMAT_BGR565,
+       [ilog2(HAL_COLOR_FORMAT_RGB888)] = HFI_COLOR_FORMAT_RGB888,
+       [ilog2(HAL_COLOR_FORMAT_BGR888)] = HFI_COLOR_FORMAT_BGR888,
+       /* UBWC Color formats*/
+       [ilog2(HAL_COLOR_FORMAT_NV12_UBWC)] =  HFI_COLOR_FORMAT_NV12_UBWC,
+       [ilog2(HAL_COLOR_FORMAT_NV12_TP10_UBWC)] =
+                       HFI_COLOR_FORMAT_YUV420_TP10_UBWC,
+};
+
+static int nal_type[] = {
+       [ilog2(HAL_NAL_FORMAT_STARTCODES)] = HFI_NAL_FORMAT_STARTCODES,
+       [ilog2(HAL_NAL_FORMAT_ONE_NAL_PER_BUFFER)] =
+               HFI_NAL_FORMAT_ONE_NAL_PER_BUFFER,
+       [ilog2(HAL_NAL_FORMAT_ONE_BYTE_LENGTH)] =
+               HFI_NAL_FORMAT_ONE_BYTE_LENGTH,
+       [ilog2(HAL_NAL_FORMAT_TWO_BYTE_LENGTH)] =
+               HFI_NAL_FORMAT_TWO_BYTE_LENGTH,
+       [ilog2(HAL_NAL_FORMAT_FOUR_BYTE_LENGTH)] =
+               HFI_NAL_FORMAT_FOUR_BYTE_LENGTH,
+};
+
+static inline int to_hfi_type(int property, int hal_type)
+{
+       if (hal_type && roundup_pow_of_two(hal_type) != hal_type) {
+               /* Not a power of 2, it's not going
+                * to be in any of the tables anyway */
+               return -EINVAL;
+       }
+
+       if (hal_type)
+               hal_type = ilog2(hal_type);
+
+       switch (property) {
+       case HAL_PARAM_PROFILE_LEVEL_CURRENT:
+               return (hal_type >= ARRAY_SIZE(profile_table)) ?
+                       -ENOTSUPP : profile_table[hal_type];
+       case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
+               return (hal_type >= ARRAY_SIZE(entropy_mode)) ?
+                       -ENOTSUPP : entropy_mode[hal_type];
+       case HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL:
+               return (hal_type >= ARRAY_SIZE(cabac_model)) ?
+                       -ENOTSUPP : cabac_model[hal_type];
+       case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT:
+               return (hal_type >= ARRAY_SIZE(color_format)) ?
+                       -ENOTSUPP : color_format[hal_type];
+       case HAL_PARAM_NAL_STREAM_FORMAT_SELECT:
+               return (hal_type >= ARRAY_SIZE(nal_type)) ?
+                       -ENOTSUPP : nal_type[hal_type];
+       default:
+               return -ENOTSUPP;
+       }
+}
+
+static inline u32 to_hfi_layout(enum hal_buffer_layout_type hal_buf_layout)
+{
+       switch (hal_buf_layout) {
+       case HAL_BUFFER_LAYOUT_TOP_BOTTOM:
+               return HFI_MVC_BUFFER_LAYOUT_TOP_BOTTOM;
+       case HAL_BUFFER_LAYOUT_SEQ:
+               return HFI_MVC_BUFFER_LAYOUT_SEQ;
+       default:
+               dprintk(VIDC_ERR, "Invalid buffer layout: %#x\n",
+                       hal_buf_layout);
+               return HFI_MVC_BUFFER_LAYOUT_SEQ;
+       }
+
+       return 0;
+}
+
+static inline u32 to_hfi_codec(enum hal_video_codec hal_codec)
+{
+       switch (hal_codec) {
+       case HAL_VIDEO_CODEC_MVC:
+       case HAL_VIDEO_CODEC_H264:
+               return HFI_VIDEO_CODEC_H264;
+       case HAL_VIDEO_CODEC_H263:
+               return HFI_VIDEO_CODEC_H263;
+       case HAL_VIDEO_CODEC_MPEG1:
+               return HFI_VIDEO_CODEC_MPEG1;
+       case HAL_VIDEO_CODEC_MPEG2:
+               return HFI_VIDEO_CODEC_MPEG2;
+       case HAL_VIDEO_CODEC_MPEG4:
+               return HFI_VIDEO_CODEC_MPEG4;
+       case HAL_VIDEO_CODEC_DIVX_311:
+               return HFI_VIDEO_CODEC_DIVX_311;
+       case HAL_VIDEO_CODEC_DIVX:
+               return HFI_VIDEO_CODEC_DIVX;
+       case HAL_VIDEO_CODEC_VC1:
+               return HFI_VIDEO_CODEC_VC1;
+       case HAL_VIDEO_CODEC_SPARK:
+               return HFI_VIDEO_CODEC_SPARK;
+       case HAL_VIDEO_CODEC_VP8:
+               return HFI_VIDEO_CODEC_VP8;
+       case HAL_VIDEO_CODEC_HEVC:
+               return HFI_VIDEO_CODEC_HEVC;
+       case HAL_VIDEO_CODEC_HEVC_HYBRID:
+               return HFI_VIDEO_CODEC_HEVC_HYBRID;
+       default:
+               dprintk(VIDC_ERR, "Invalid codec %#x\n", hal_codec);
+               break;
+       }
+
+       return 0;
+}
+
+static int pkt_sys_init(struct hfi_sys_init_pkt *pkt, u32 arch_type)
+{
+       pkt->packet_type = HFI_CMD_SYS_INIT;
+       pkt->size = sizeof(*pkt);
+       pkt->arch_type = arch_type;
+
+       return 0;
+}
+
+static int pkt_sys_pc_prep(struct hfi_sys_pc_prep_pkt *pkt)
+{
+       pkt->packet_type = HFI_CMD_SYS_PC_PREP;
+       pkt->size = sizeof(*pkt);
+
+       return 0;
+}
+
+static int pkt_sys_idle_indicator(struct hfi_sys_set_property_pkt *pkt,
+                                 u32 enable)
+{
+       struct hfi_enable *hfi;
+
+       pkt->size = sizeof(*pkt) + sizeof(struct hfi_enable) + sizeof(u32);
+       pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
+       pkt->num_properties = 1;
+       pkt->rg_property_data[0] = HFI_PROPERTY_SYS_IDLE_INDICATOR;
+       hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+       hfi->enable = enable;
+
+       return 0;
+}
+
+static int pkt_sys_debug_config(struct hfi_sys_set_property_pkt *pkt,
+                               u32 mode)
+{
+       struct hfi_debug_config *hfi;
+
+       pkt->size = sizeof(*pkt) + sizeof(struct hfi_debug_config) +
+                   sizeof(u32);
+       pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
+       pkt->num_properties = 1;
+       pkt->rg_property_data[0] = HFI_PROPERTY_SYS_DEBUG_CONFIG;
+       hfi = (struct hfi_debug_config *) &pkt->rg_property_data[1];
+       hfi->debug_config = mode;
+       hfi->debug_mode = HFI_DEBUG_MODE_QUEUE;
+
+       if (vidc_fw_debug_mode <= HFI_DEBUG_MODE_QDSS)
+               hfi->debug_mode = vidc_fw_debug_mode;
+
+       return 0;
+}
+
+static int pkt_sys_coverage_config(struct hfi_sys_set_property_pkt *pkt,
+                                  u32 mode)
+{
+       pkt->size = sizeof(*pkt) + sizeof(u32);
+       pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
+       pkt->num_properties = 1;
+       pkt->rg_property_data[0] = HFI_PROPERTY_SYS_CONFIG_COVERAGE;
+       pkt->rg_property_data[1] = mode;
+
+       dprintk(VIDC_DBG, "Firmware coverage mode %d\n",
+               pkt->rg_property_data[1]);
+
+       return 0;
+}
+
+static int pkt_sys_set_resource(struct hfi_sys_set_resource_pkt *pkt,
+                               struct vidc_resource_hdr *resource_hdr,
+                               void *resource_value)
+{
+       if (!pkt || !resource_hdr || !resource_value)
+               return -EINVAL;
+
+       pkt->packet_type = HFI_CMD_SYS_SET_RESOURCE;
+       pkt->size = sizeof(*pkt);
+       pkt->resource_handle = hash32_ptr(resource_hdr->resource_handle);
+
+       switch (resource_hdr->resource_id) {
+       case VIDC_RESOURCE_OCMEM:
+       case VIDC_RESOURCE_VMEM: {
+               struct hfi_resource_ocmem *hfioc_mem =
+                       (struct hfi_resource_ocmem *) &pkt->rg_resource_data[0];
+               phys_addr_t imem_addr = (phys_addr_t)resource_value;
+
+               pkt->resource_type = HFI_RESOURCE_OCMEM;
+               pkt->size += sizeof(struct hfi_resource_ocmem) - sizeof(u32);
+               hfioc_mem->size = (u32)resource_hdr->size;
+               hfioc_mem->mem = imem_addr;
+               break;
+       }
+       default:
+               return -ENOTSUPP;
+       }
+
+       return 0;
+}
+
+static int
+pkt_sys_release_resource(struct hfi_sys_release_resource_pkt *pkt,
+                        struct vidc_resource_hdr *resource_hdr)
+{
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SYS_RELEASE_RESOURCE;
+       pkt->resource_handle = hash32_ptr(resource_hdr->resource_handle);
+
+       switch (resource_hdr->resource_id) {
+       case VIDC_RESOURCE_OCMEM:
+       case VIDC_RESOURCE_VMEM:
+               pkt->resource_type = HFI_RESOURCE_OCMEM;
+               break;
+       default:
+               return -ENOTSUPP;
+       }
+
+       return 0;
+}
+
+static int pkt_sys_ping(struct hfi_cmd_sys_ping_packet *pkt)
+{
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SYS_PING;
+
+       return 0;
+}
+
+static int pkt_session_init(struct hfi_session_init_pkt *pkt,
+                           struct hal_session *session,
+                           u32 session_domain, u32 session_codec)
+{
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SYS_SESSION_INIT;
+       pkt->session_id = hash32_ptr(session);
+       pkt->session_domain = session_domain;
+       pkt->session_codec = to_hfi_codec(session_codec);
+
+       if (!pkt->session_codec)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int pkt_session_cmd(struct vidc_hal_session_cmd_pkt *pkt,
+                          int pkt_type, struct hal_session *session)
+{
+       pkt->size = sizeof(struct vidc_hal_session_cmd_pkt);
+       pkt->packet_type = pkt_type;
+       pkt->session_id = hash32_ptr(session);
+
+       return 0;
+}
+
+static int pkt_sys_power_control(struct hfi_sys_set_property_pkt *pkt,
+                                u32 enable)
+{
+       struct hfi_enable *hfi;
+
+       pkt->size = sizeof(*pkt) + sizeof(struct hfi_enable) + sizeof(u32);
+       pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
+       pkt->num_properties = 1;
+       pkt->rg_property_data[0] = HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL;
+       hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+       hfi->enable = enable;
+
+       return 0;
+}
+
+static u32 to_hfi_buffer(int hal_buffer)
+{
+       switch (hal_buffer) {
+       case HAL_BUFFER_INPUT:
+               return HFI_BUFFER_INPUT;
+       case HAL_BUFFER_OUTPUT:
+               return HFI_BUFFER_OUTPUT;
+       case HAL_BUFFER_OUTPUT2:
+               return HFI_BUFFER_OUTPUT2;
+       case HAL_BUFFER_EXTRADATA_INPUT:
+               return HFI_BUFFER_EXTRADATA_INPUT;
+       case HAL_BUFFER_EXTRADATA_OUTPUT:
+               return HFI_BUFFER_EXTRADATA_OUTPUT;
+       case HAL_BUFFER_EXTRADATA_OUTPUT2:
+               return HFI_BUFFER_EXTRADATA_OUTPUT2;
+       case HAL_BUFFER_INTERNAL_SCRATCH:
+               return HFI_BUFFER_INTERNAL_SCRATCH;
+       case HAL_BUFFER_INTERNAL_SCRATCH_1:
+               return HFI_BUFFER_INTERNAL_SCRATCH_1;
+       case HAL_BUFFER_INTERNAL_SCRATCH_2:
+               return HFI_BUFFER_INTERNAL_SCRATCH_2;
+       case HAL_BUFFER_INTERNAL_PERSIST:
+               return HFI_BUFFER_INTERNAL_PERSIST;
+       case HAL_BUFFER_INTERNAL_PERSIST_1:
+               return HFI_BUFFER_INTERNAL_PERSIST_1;
+       default:
+               break;
+       }
+
+       return HAL_BUFFER_NONE;
+}
+
+static int to_hfi_extradata_index(enum hal_extradata_id index)
+{
+       switch (index) {
+       case HAL_EXTRADATA_MB_QUANTIZATION:
+               return HFI_PROPERTY_PARAM_VDEC_MB_QUANTIZATION;
+       case HAL_EXTRADATA_INTERLACE_VIDEO:
+               return HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA;
+       case HAL_EXTRADATA_VC1_FRAMEDISP:
+               return HFI_PROPERTY_PARAM_VDEC_VC1_FRAMEDISP_EXTRADATA;
+       case HAL_EXTRADATA_VC1_SEQDISP:
+               return HFI_PROPERTY_PARAM_VDEC_VC1_SEQDISP_EXTRADATA;
+       case HAL_EXTRADATA_TIMESTAMP:
+               return HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA;
+       case HAL_EXTRADATA_S3D_FRAME_PACKING:
+               return HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA;
+       case HAL_EXTRADATA_FRAME_RATE:
+               return HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA;
+       case HAL_EXTRADATA_PANSCAN_WINDOW:
+               return HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA;
+       case HAL_EXTRADATA_RECOVERY_POINT_SEI:
+               return HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA;
+       case HAL_EXTRADATA_MULTISLICE_INFO:
+               return HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_INFO;
+       case HAL_EXTRADATA_NUM_CONCEALED_MB:
+               return HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB;
+       case HAL_EXTRADATA_ASPECT_RATIO:
+       case HAL_EXTRADATA_INPUT_CROP:
+       case HAL_EXTRADATA_DIGITAL_ZOOM:
+               return HFI_PROPERTY_PARAM_INDEX_EXTRADATA;
+       case HAL_EXTRADATA_MPEG2_SEQDISP:
+               return HFI_PROPERTY_PARAM_VDEC_MPEG2_SEQDISP_EXTRADATA;
+       case HAL_EXTRADATA_STREAM_USERDATA:
+               return HFI_PROPERTY_PARAM_VDEC_STREAM_USERDATA_EXTRADATA;
+       case HAL_EXTRADATA_FRAME_QP:
+               return HFI_PROPERTY_PARAM_VDEC_FRAME_QP_EXTRADATA;
+       case HAL_EXTRADATA_FRAME_BITS_INFO:
+               return HFI_PROPERTY_PARAM_VDEC_FRAME_BITS_INFO_EXTRADATA;
+       case HAL_EXTRADATA_LTR_INFO:
+               return HFI_PROPERTY_PARAM_VENC_LTR_INFO;
+       case HAL_EXTRADATA_METADATA_MBI:
+               return HFI_PROPERTY_PARAM_VENC_MBI_DUMPING;
+       default:
+               dprintk(VIDC_WARN, "extradata index not found:%d\n", index);
+               break;
+       }
+
+       return 0;
+}
+
+static int to_hfi_extradata_id(enum hal_extradata_id index)
+{
+       switch (index) {
+       case HAL_EXTRADATA_ASPECT_RATIO:
+               return VIDC_EXTRADATA_ASPECT_RATIO;
+       case HAL_EXTRADATA_INPUT_CROP:
+               return VIDC_EXTRADATA_INPUT_CROP;
+       case HAL_EXTRADATA_DIGITAL_ZOOM:
+               return VIDC_EXTRADATA_DIGITAL_ZOOM;
+       default:
+               return to_hfi_extradata_index(index);
+       }
+
+       return 0;
+}
+
+static u32 to_hfi_buf_mode(enum hal_buffer_mode_type hal_buf_mode)
+{
+       switch (hal_buf_mode) {
+       case HAL_BUFFER_MODE_STATIC:
+               return HFI_BUFFER_MODE_STATIC;
+       case HAL_BUFFER_MODE_RING:
+               return HFI_BUFFER_MODE_RING;
+       case HAL_BUFFER_MODE_DYNAMIC:
+               return HFI_BUFFER_MODE_DYNAMIC;
+       default:
+               dprintk(VIDC_ERR, "invalid buffer mode:%x\n", hal_buf_mode);
+               return 0;
+       }
+
+       return 0;
+}
+
+static u32 to_hfi_ltr_mode(enum ltr_mode ltr_mode_type)
+{
+       switch (ltr_mode_type) {
+       case HAL_LTR_MODE_DISABLE:
+               return HFI_LTR_MODE_DISABLE;
+       case HAL_LTR_MODE_MANUAL:
+               return HFI_LTR_MODE_MANUAL;
+       case HAL_LTR_MODE_PERIODIC:
+               return HFI_LTR_MODE_PERIODIC;
+       default:
+               dprintk(VIDC_ERR, "invalid ltr mode:%x\n", ltr_mode_type);
+               return HFI_LTR_MODE_DISABLE;
+       }
+
+       return 0;
+}
+
+static int
+pkt_session_set_buffers(struct hfi_session_set_buffers_pkt *pkt,
+                       struct hal_session *session,
+                       struct vidc_buffer_addr_info *bai)
+{
+       int i;
+
+       if (!session)
+               return -EINVAL;
+
+       pkt->packet_type = HFI_CMD_SESSION_SET_BUFFERS;
+       pkt->session_id = hash32_ptr(session);
+       pkt->buffer_size = bai->buffer_size;
+       pkt->min_buffer_size = bai->buffer_size;
+       pkt->num_buffers = bai->num_buffers;
+
+       if (bai->buffer_type == HAL_BUFFER_OUTPUT ||
+           bai->buffer_type == HAL_BUFFER_OUTPUT2) {
+               struct hfi_buffer_info *bi;
+
+               pkt->extra_data_size = bai->extradata_size;
+               pkt->size = sizeof(*pkt) - sizeof(u32) +
+                       (bai->num_buffers * sizeof(struct hfi_buffer_info));
+               bi = (struct hfi_buffer_info *) pkt->rg_buffer_info;
+               for (i = 0; i < pkt->num_buffers; i++) {
+                       bi->buffer_addr = bai->device_addr;
+                       bi->extra_data_addr = bai->extradata_addr;
+               }
+       } else {
+               pkt->extra_data_size = 0;
+               pkt->size = sizeof(*pkt) +
+                       ((bai->num_buffers - 1) * sizeof(u32));
+               for (i = 0; i < pkt->num_buffers; i++)
+                       pkt->rg_buffer_info[i] = bai->device_addr;
+       }
+
+       pkt->buffer_type = to_hfi_buffer(bai->buffer_type);
+       if (!pkt->buffer_type)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int
+pkt_session_release_buffers(struct hfi_cmd_session_release_buffer_packet *pkt,
+                           struct hal_session *session,
+                           struct vidc_buffer_addr_info *bai)
+{
+       int i;
+
+       if (!session)
+               return -EINVAL;
+
+       pkt->packet_type = HFI_CMD_SESSION_RELEASE_BUFFERS;
+       pkt->session_id = hash32_ptr(session);
+       pkt->buffer_size = bai->buffer_size;
+       pkt->num_buffers = bai->num_buffers;
+
+       if (bai->buffer_type == HAL_BUFFER_OUTPUT ||
+           bai->buffer_type == HAL_BUFFER_OUTPUT2) {
+               struct hfi_buffer_info *bi;
+
+               bi = (struct hfi_buffer_info *) pkt->rg_buffer_info;
+               for (i = 0; i < pkt->num_buffers; i++) {
+                       bi->buffer_addr = bai->device_addr;
+                       bi->extra_data_addr = bai->extradata_addr;
+               }
+               pkt->size = sizeof(struct hfi_session_set_buffers_pkt) -
+                           sizeof(u32) +
+                           (bai->num_buffers * sizeof(struct hfi_buffer_info));
+       } else {
+               for (i = 0; i < pkt->num_buffers; i++)
+                       pkt->rg_buffer_info[i] = bai->device_addr;
+
+               pkt->extra_data_size = 0;
+               pkt->size = sizeof(struct hfi_session_set_buffers_pkt) +
+                               ((bai->num_buffers - 1) * sizeof(u32));
+       }
+
+       pkt->response_req = bai->response_required;
+       pkt->buffer_type = to_hfi_buffer(bai->buffer_type);
+       if (!pkt->buffer_type)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int pkt_session_etb_decoder(
+       struct hfi_cmd_session_empty_buffer_compressed_packet *pkt,
+       struct hal_session *session, struct vidc_frame_data *in_frame)
+{
+       if (!session || !in_frame->device_addr)
+               return -EINVAL;
+
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+       pkt->session_id = hash32_ptr(session);
+       pkt->time_stamp_hi = upper_32_bits(in_frame->timestamp);
+       pkt->time_stamp_lo = lower_32_bits(in_frame->timestamp);
+       pkt->flags = in_frame->flags;
+       pkt->mark_target = in_frame->mark_target;
+       pkt->mark_data = in_frame->mark_data;
+       pkt->offset = in_frame->offset;
+       pkt->alloc_len = in_frame->alloc_len;
+       pkt->filled_len = in_frame->filled_len;
+       pkt->input_tag = in_frame->clnt_data;
+       pkt->packet_buffer = in_frame->device_addr;
+
+       return 0;
+}
+
+static int pkt_session_etb_encoder(
+       struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet *pkt,
+       struct hal_session *session, struct vidc_frame_data *in_frame)
+{
+       if (!session || !in_frame->device_addr)
+               return -EINVAL;
+
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+       pkt->session_id = hash32_ptr(session);
+       pkt->view_id = 0;
+       pkt->time_stamp_hi = upper_32_bits(in_frame->timestamp);
+       pkt->time_stamp_lo = lower_32_bits(in_frame->timestamp);
+       pkt->flags = in_frame->flags;
+       pkt->mark_target = in_frame->mark_target;
+       pkt->mark_data = in_frame->mark_data;
+       pkt->offset = in_frame->offset;
+       pkt->alloc_len = in_frame->alloc_len;
+       pkt->filled_len = in_frame->filled_len;
+       pkt->input_tag = in_frame->clnt_data;
+       pkt->packet_buffer = in_frame->device_addr;
+       pkt->extra_data_buffer = in_frame->extradata_addr;
+
+       return 0;
+}
+
+static int pkt_session_ftb(struct hfi_cmd_session_fill_buffer_packet *pkt,
+                          struct hal_session *session,
+                          struct vidc_frame_data *out_frame)
+{
+       if (!session || !out_frame || !out_frame->device_addr)
+               return -EINVAL;
+
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SESSION_FILL_BUFFER;
+       pkt->session_id = hash32_ptr(session);
+
+       if (out_frame->buffer_type == HAL_BUFFER_OUTPUT)
+               pkt->stream_id = 0;
+       else if (out_frame->buffer_type == HAL_BUFFER_OUTPUT2)
+               pkt->stream_id = 1;
+
+       pkt->packet_buffer = out_frame->device_addr;
+       pkt->extra_data_buffer = out_frame->extradata_addr;
+       pkt->alloc_len = out_frame->alloc_len;
+       pkt->filled_len = out_frame->filled_len;
+       pkt->offset = out_frame->offset;
+       pkt->rgData[0] = out_frame->extradata_size;
+
+       return 0;
+}
+
+static int pkt_session_parse_seq_header(
+               struct hfi_cmd_session_parse_sequence_header_packet *pkt,
+               struct hal_session *session, struct vidc_seq_hdr *seq_hdr)
+{
+       if (!session || !seq_hdr || !seq_hdr->seq_hdr)
+               return -EINVAL;
+
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER;
+       pkt->session_id = hash32_ptr(session);
+       pkt->header_len = seq_hdr->seq_hdr_len;
+       pkt->packet_buffer = seq_hdr->seq_hdr;
+
+       return 0;
+}
+
+static int
+pkt_session_get_seq_hdr(struct hfi_session_get_sequence_header_pkt *pkt,
+                       struct hal_session *session,
+                       struct vidc_seq_hdr *seq_hdr)
+{
+       if (!session || !seq_hdr || !seq_hdr->seq_hdr)
+               return -EINVAL;
+
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SESSION_GET_SEQUENCE_HEADER;
+       pkt->session_id = hash32_ptr(session);
+       pkt->buffer_len = seq_hdr->seq_hdr_len;
+       pkt->packet_buffer = seq_hdr->seq_hdr;
+
+       return 0;
+}
+
+static int pkt_session_flush(struct hfi_cmd_session_flush_packet *pkt,
+                            struct hal_session *session, enum hal_flush type)
+{
+       if (!session)
+               return -EINVAL;
+
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SESSION_FLUSH;
+       pkt->session_id = hash32_ptr(session);
+
+       switch (type) {
+       case HAL_FLUSH_INPUT:
+               pkt->flush_type = HFI_FLUSH_INPUT;
+               break;
+       case HAL_FLUSH_OUTPUT:
+               pkt->flush_type = HFI_FLUSH_OUTPUT;
+               break;
+       case HAL_FLUSH_OUTPUT2:
+               pkt->flush_type = HFI_FLUSH_OUTPUT2;
+               break;
+       case HAL_FLUSH_ALL:
+               pkt->flush_type = HFI_FLUSH_ALL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+pkt_session_get_property(struct hfi_cmd_session_get_property_packet *pkt,
+                        struct hal_session *session, enum hal_property ptype)
+{
+       if (!session)
+               return -EINVAL;
+
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SESSION_GET_PROPERTY;
+       pkt->session_id = hash32_ptr(session);
+       pkt->num_properties = 1;
+
+       switch (ptype) {
+       case HAL_PARAM_PROFILE_LEVEL_CURRENT:
+               pkt->rg_property_data[0] =
+                               HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;
+               break;
+       case HAL_PARAM_GET_BUFFER_REQUIREMENTS:
+               pkt->rg_property_data[0] =
+                               HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS;
+               break;
+       default:
+               return -ENOTSUPP;
+       }
+
+       return 0;
+}
+
+static int
+pkt_session_set_property(struct hfi_session_set_property_pkt *pkt,
+                        struct hal_session *session, enum hal_property ptype,
+                        void *pdata)
+{
+       int ret = 0;
+
+       if (!session)
+               return -EINVAL;
+
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SESSION_SET_PROPERTY;
+       pkt->session_id = hash32_ptr(session);
+       pkt->num_properties = 1;
+
+       switch (ptype) {
+       case HAL_CONFIG_FRAME_RATE: {
+               struct hal_frame_rate *prop = pdata;
+               struct hfi_frame_rate *hfi;
+               u32 buffer_type;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_FRAME_RATE;
+               hfi = (struct hfi_frame_rate *) &pkt->rg_property_data[1];
+               buffer_type = to_hfi_buffer(prop->buffer_type);
+               if (!buffer_type)
+                       return -EINVAL;
+               hfi->buffer_type = buffer_type;
+               hfi->frame_rate = prop->frame_rate;
+               pkt->size += sizeof(u32) + sizeof(struct hfi_frame_rate);
+               break;
+       }
+       case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT: {
+               struct hal_uncompressed_format_select *prop = pdata;
+               struct hfi_uncompressed_format_select *hfi;
+               u32 buffer_type;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
+
+               hfi = (struct hfi_uncompressed_format_select *)
+                                       &pkt->rg_property_data[1];
+               buffer_type = to_hfi_buffer(prop->buffer_type);
+               if (!buffer_type)
+                       return -EINVAL;
+               hfi->buffer_type = buffer_type;
+               hfi->format = to_hfi_type(HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT,
+                                         prop->format);
+               pkt->size += sizeof(u32) +
+                       sizeof(struct hfi_uncompressed_format_select);
+               break;
+       }
+       case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO:
+               break;
+       case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO:
+               break;
+       case HAL_PARAM_EXTRA_DATA_HEADER_CONFIG:
+               break;
+       case HAL_PARAM_FRAME_SIZE: {
+               struct hal_frame_size *prop = pdata;
+               struct hfi_frame_size *hfi;
+               u32 buffer_type;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_FRAME_SIZE;
+               hfi = (struct hfi_frame_size *) &pkt->rg_property_data[1];
+               buffer_type = to_hfi_buffer(prop->buffer_type);
+               if (!buffer_type)
+                       return -EINVAL;
+               hfi->buffer_type = buffer_type;
+               hfi->height = prop->height;
+               hfi->width = prop->width;
+               pkt->size += sizeof(u32) + sizeof(struct hfi_frame_size);
+               break;
+       }
+       case HAL_CONFIG_REALTIME: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_REALTIME;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hfi_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_BUFFER_COUNT_ACTUAL: {
+               struct hal_buffer_count_actual *prop = pdata;
+               struct hfi_buffer_count_actual *hfi;
+               u32 buf_type;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
+
+               hfi = (struct hfi_buffer_count_actual *)
+                       &pkt->rg_property_data[1];
+
+               hfi->count_actual = prop->count_actual;
+               buf_type = to_hfi_buffer(prop->type);
+               if (!buf_type)
+                       return -EINVAL;
+               hfi->type = buf_type;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_BUFFER_SIZE_ACTUAL: {
+               struct hal_buffer_size_actual *prop = pdata;
+               struct hfi_buffer_size_actual *hfi;
+               u32 buf_type;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL;
+
+               hfi = (struct hfi_buffer_size_actual *)
+                       &pkt->rg_property_data[1];
+
+               hfi->size = prop->size;
+               buf_type = to_hfi_buffer(prop->type);
+               if (!buf_type)
+                       return -EINVAL;
+               hfi->type = buf_type;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_BUFFER_DISPLAY_HOLD_COUNT_ACTUAL: {
+               struct hal_buffer_display_hold_count_actual *prop = pdata;
+               struct hfi_buffer_display_hold_count_actual *hfi;
+               u32 buffer_type;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_BUFFER_DISPLAY_HOLD_COUNT_ACTUAL;
+
+               hfi = (struct hfi_buffer_display_hold_count_actual *)
+                       &pkt->rg_property_data[1];
+               hfi->hold_count = prop->hold_count;
+               buffer_type = to_hfi_buffer(prop->buffer_type);
+               if (!buffer_type)
+                       return -EINVAL;
+               hfi->type = buffer_type;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_NAL_STREAM_FORMAT_SELECT: {
+               struct hal_nal_stream_format_select *prop = pdata;
+               struct hfi_nal_stream_format_select *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT;
+               hfi = (struct hfi_nal_stream_format_select *)
+                       &pkt->rg_property_data[1];
+               hfi->nal_stream_format_select =
+                       to_hfi_type(HAL_PARAM_NAL_STREAM_FORMAT_SELECT,
+                                   prop->nal_stream_format_select);
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VDEC_OUTPUT_ORDER: {
+               int *data = pdata;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER;
+               switch (*data) {
+               case HAL_OUTPUT_ORDER_DECODE:
+                       pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DECODE;
+                       break;
+               case HAL_OUTPUT_ORDER_DISPLAY:
+                       pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DISPLAY;
+                       break;
+               default:
+                       dprintk(VIDC_ERR, "invalid output order: %#x\n", *data);
+                       break;
+               }
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VDEC_PICTURE_TYPE_DECODE: {
+               struct hfi_enable_picture *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE;
+               hfi = (struct hfi_enable_picture *) &pkt->rg_property_data[1];
+               hfi->picture_type =
+                       ((struct hfi_enable_picture *)pdata)->picture_type;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hfi_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hfi_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VDEC_MULTI_STREAM: {
+               struct hal_multi_stream *prop = pdata;
+               struct hfi_multi_stream *hfi;
+               u32 buffer_type;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
+               hfi = (struct hfi_multi_stream *) &pkt->rg_property_data[1];
+
+               buffer_type = to_hfi_buffer(prop->buffer_type);
+               if (!buffer_type)
+                       return -EINVAL;
+               hfi->buffer_type = buffer_type;
+               hfi->enable = prop->enable;
+               hfi->width = prop->width;
+               hfi->height = prop->height;
+               pkt->size += sizeof(u32) + sizeof(struct hfi_multi_stream);
+               break;
+       }
+       case HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT: {
+               struct hal_display_picture_buffer_count *prop = pdata;
+               struct hfi_display_picture_buffer_count *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT;
+               hfi = (struct hfi_display_picture_buffer_count *)
+                       &pkt->rg_property_data[1];
+               hfi->count = prop->count;
+               hfi->enable = prop->enable;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_DIVX_FORMAT: {
+               int *data = pdata;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_DIVX_FORMAT;
+               switch (*data) {
+               case HAL_DIVX_FORMAT_4:
+                       pkt->rg_property_data[1] = HFI_DIVX_FORMAT_4;
+                       break;
+               case HAL_DIVX_FORMAT_5:
+                       pkt->rg_property_data[1] = HFI_DIVX_FORMAT_5;
+                       break;
+               case HAL_DIVX_FORMAT_6:
+                       pkt->rg_property_data[1] = HFI_DIVX_FORMAT_6;
+                       break;
+               default:
+                       dprintk(VIDC_ERR, "Invalid divx format: %#x\n", *data);
+                       break;
+               }
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP_REPORTING;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hfi_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hfi_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VDEC_SYNC_FRAME_DECODE: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hfi_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hfi_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_CONFIG_VENC_REQUEST_IFRAME:
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VENC_REQUEST_SYNC_FRAME;
+               pkt->size += sizeof(u32);
+               break;
+       case HAL_PARAM_VENC_MPEG4_SHORT_HEADER:
+               break;
+       case HAL_PARAM_VENC_MPEG4_AC_PREDICTION:
+               break;
+       case HAL_CONFIG_VENC_TARGET_BITRATE: {
+               struct hfi_bitrate *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
+               hfi = (struct hfi_bitrate *) &pkt->rg_property_data[1];
+               hfi->bit_rate = ((struct hal_bitrate *)pdata)->bit_rate;
+               hfi->layer_id = ((struct hal_bitrate *)pdata)->layer_id;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_CONFIG_VENC_MAX_BITRATE: {
+               struct hfi_bitrate *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE;
+               hfi = (struct hfi_bitrate *) &pkt->rg_property_data[1];
+               hfi->bit_rate = ((struct hal_bitrate *)pdata)->bit_rate;
+               hfi->layer_id = ((struct hal_bitrate *)pdata)->layer_id;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_PROFILE_LEVEL_CURRENT: {
+               struct hal_profile_level *prop = pdata;
+               struct hfi_profile_level *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;
+               hfi = (struct hfi_profile_level *) &pkt->rg_property_data[1];
+               hfi->level = prop->level;
+               hfi->profile = to_hfi_type(HAL_PARAM_PROFILE_LEVEL_CURRENT,
+                                          prop->profile);
+               if (hfi->profile <= 0) {
+                       hfi->profile = HFI_H264_PROFILE_HIGH;
+                       dprintk(VIDC_WARN,
+                               "Profile %d not supported, falling back to high\n",
+                               prop->profile);
+               }
+
+               if (!hfi->level) {
+                       hfi->level = 1;
+                       dprintk(VIDC_WARN,
+                               "Level %d not supported, falling back to high\n",
+                               prop->level);
+               }
+
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_H264_ENTROPY_CONTROL: {
+               struct hal_h264_entropy_control *prop = pdata;
+               struct hfi_h264_entropy_control *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
+               hfi = (struct hfi_h264_entropy_control *)
+                       &pkt->rg_property_data[1];
+               hfi->entropy_mode = to_hfi_type(
+                                       HAL_PARAM_VENC_H264_ENTROPY_CONTROL,
+                                       prop->entropy_mode);
+               if (hfi->entropy_mode == HAL_H264_ENTROPY_CABAC)
+                       hfi->cabac_model = to_hfi_type(
+                                       HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL,
+                                       prop->cabac_model);
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_RATE_CONTROL: {
+               u32 *rc;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
+               rc = (u32 *)pdata;
+               switch ((enum hal_rate_control) *rc) {
+               case HAL_RATE_CONTROL_OFF:
+                       pkt->rg_property_data[1] = HFI_RATE_CONTROL_OFF;
+                       break;
+               case HAL_RATE_CONTROL_CBR_CFR:
+                       pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_CFR;
+                       break;
+               case HAL_RATE_CONTROL_CBR_VFR:
+                       pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_VFR;
+                       break;
+               case HAL_RATE_CONTROL_VBR_CFR:
+                       pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_CFR;
+                       break;
+               case HAL_RATE_CONTROL_VBR_VFR:
+                       pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_VFR;
+                       break;
+               default:
+                       dprintk(VIDC_ERR, "Invalid Rate control setting: %p\n",
+                               pdata);
+                       break;
+               }
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION: {
+               struct hfi_mpeg4_time_resolution *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_MPEG4_TIME_RESOLUTION;
+               hfi = (struct hfi_mpeg4_time_resolution *)
+                       &pkt->rg_property_data[1];
+               hfi->time_increment_resolution =
+                       ((struct hal_mpeg4_time_resolution *)pdata)->
+                                       time_increment_resolution;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION: {
+               struct hfi_mpeg4_header_extension *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_MPEG4_HEADER_EXTENSION;
+               hfi = (struct hfi_mpeg4_header_extension *)
+                       &pkt->rg_property_data[1];
+               hfi->header_extension = (u32)(unsigned long) pdata;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VENC_H264_DEBLOCK_CONTROL: {
+               struct hal_h264_db_control *prop = pdata;
+               struct hfi_h264_db_control *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL;
+               hfi = (struct hfi_h264_db_control *) &pkt->rg_property_data[1];
+               switch (prop->mode) {
+               case HAL_H264_DB_MODE_DISABLE:
+                       hfi->mode = HFI_H264_DB_MODE_DISABLE;
+                       break;
+               case HAL_H264_DB_MODE_SKIP_SLICE_BOUNDARY:
+                       hfi->mode = HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
+                       break;
+               case HAL_H264_DB_MODE_ALL_BOUNDARY:
+                       hfi->mode = HFI_H264_DB_MODE_ALL_BOUNDARY;
+                       break;
+               default:
+                       dprintk(VIDC_ERR, "Invalid deblocking mode: %#x\n",
+                               prop->mode);
+                       break;
+               }
+               hfi->slice_alpha_offset = prop->slice_alpha_offset;
+               hfi->slice_beta_offset = prop->slice_beta_offset;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_SESSION_QP: {
+               struct hal_quantization *hal_quant = pdata;
+               struct hfi_quantization *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_SESSION_QP;
+               hfi = (struct hfi_quantization *) &pkt->rg_property_data[1];
+               hfi->qp_i = hal_quant->qpi;
+               hfi->qp_p = hal_quant->qpp;
+               hfi->qp_b = hal_quant->qpb;
+               hfi->layer_id = hal_quant->layer_id;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_SESSION_QP_RANGE: {
+               struct hfi_quantization_range *hal_range = pdata;
+               struct hfi_quantization_range *hfi;
+               u32 min_qp, max_qp;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE;
+               hfi = (struct hfi_quantization_range *)
+                               &pkt->rg_property_data[1];
+
+               min_qp = hal_range->min_qp;
+               max_qp = hal_range->max_qp;
+
+               /* We'll be packing in the qp, so make sure we
+                * won't be losing data when masking */
+               if (min_qp > 0xff || max_qp > 0xff) {
+                       dprintk(VIDC_ERR, "qp value out of range\n");
+                       ret = -ERANGE;
+                       break;
+               }
+
+               /* When creating the packet, pack the qp value as
+                * 0xiippbb, where ii = qp range for I-frames,
+                * pp = qp range for P-frames, etc. */
+               hfi->min_qp = min_qp | min_qp << 8 | min_qp << 16;
+               hfi->max_qp = max_qp | max_qp << 8 | max_qp << 16;
+               hfi->layer_id = hal_range->layer_id;
+
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_SEARCH_RANGE: {
+               struct hal_vc1e_perf_cfg_type *hal_mv_searchrange = pdata;
+               struct hfi_vc1e_perf_cfg_type *hfi;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_VENC_VC1_PERF_CFG;
+               hfi = (struct hfi_vc1e_perf_cfg_type *)
+                               &pkt->rg_property_data[1];
+               hfi->search_range_x_subsampled[0] =
+                       hal_mv_searchrange->i_frame.x_subsampled;
+               hfi->search_range_x_subsampled[1] =
+                       hal_mv_searchrange->p_frame.x_subsampled;
+               hfi->search_range_x_subsampled[2] =
+                       hal_mv_searchrange->b_frame.x_subsampled;
+               hfi->search_range_y_subsampled[0] =
+                       hal_mv_searchrange->i_frame.y_subsampled;
+               hfi->search_range_y_subsampled[1] =
+                       hal_mv_searchrange->p_frame.y_subsampled;
+               hfi->search_range_y_subsampled[2] =
+                       hal_mv_searchrange->b_frame.y_subsampled;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_MAX_NUM_B_FRAMES: {
+               struct hfi_max_num_b_frames *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES;
+               hfi = (struct hfi_max_num_b_frames *) &pkt->rg_property_data[1];
+               memcpy(hfi, (struct hfi_max_num_b_frames *) pdata,
+                       sizeof(struct hfi_max_num_b_frames));
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_CONFIG_VENC_INTRA_PERIOD: {
+               struct hfi_intra_period *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD;
+               hfi = (struct hfi_intra_period *) &pkt->rg_property_data[1];
+               memcpy(hfi, (struct hfi_intra_period *) pdata,
+                       sizeof(struct hfi_intra_period));
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_CONFIG_VENC_IDR_PERIOD: {
+               struct hfi_idr_period *hfi;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD;
+               hfi = (struct hfi_idr_period *) &pkt->rg_property_data[1];
+               hfi->idr_period = ((struct hfi_idr_period *) pdata)->idr_period;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VDEC_CONCEAL_COLOR: {
+               struct hfi_conceal_color *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR;
+               hfi = (struct hfi_conceal_color *) &pkt->rg_property_data[1];
+               if (hfi)
+                       hfi->conceal_color =
+                               ((struct hfi_conceal_color *) pdata)->
+                               conceal_color;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_CONFIG_VPE_OPERATIONS: {
+               struct hal_operations *prop = pdata;
+               struct hfi_operations_type *hfi;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_VPE_OPERATIONS;
+               hfi = (struct hfi_operations_type *) &pkt->rg_property_data[1];
+               switch (prop->rotate) {
+               case HAL_ROTATE_NONE:
+                       hfi->rotation = HFI_ROTATE_NONE;
+                       break;
+               case HAL_ROTATE_90:
+                       hfi->rotation = HFI_ROTATE_90;
+                       break;
+               case HAL_ROTATE_180:
+                       hfi->rotation = HFI_ROTATE_180;
+                       break;
+               case HAL_ROTATE_270:
+                       hfi->rotation = HFI_ROTATE_270;
+                       break;
+               default:
+                       dprintk(VIDC_ERR, "Invalid rotation setting: %#x\n",
+                               prop->rotate);
+                       ret = -EINVAL;
+                       break;
+               }
+               switch (prop->flip) {
+               case HAL_FLIP_NONE:
+                       hfi->flip = HFI_FLIP_NONE;
+                       break;
+               case HAL_FLIP_HORIZONTAL:
+                       hfi->flip = HFI_FLIP_HORIZONTAL;
+                       break;
+               case HAL_FLIP_VERTICAL:
+                       hfi->flip = HFI_FLIP_VERTICAL;
+                       break;
+               default:
+                       dprintk(VIDC_ERR, "Invalid flip setting: %#x\n",
+                               prop->flip);
+                       ret = -EINVAL;
+                       break;
+               }
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_INTRA_REFRESH: {
+               struct hal_intra_refresh *prop = pdata;
+               struct hfi_intra_refresh *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
+               hfi = (struct hfi_intra_refresh *) &pkt->rg_property_data[1];
+               switch (prop->mode) {
+               case HAL_INTRA_REFRESH_NONE:
+                       hfi->mode = HFI_INTRA_REFRESH_NONE;
+                       break;
+               case HAL_INTRA_REFRESH_ADAPTIVE:
+                       hfi->mode = HFI_INTRA_REFRESH_ADAPTIVE;
+                       break;
+               case HAL_INTRA_REFRESH_CYCLIC:
+                       hfi->mode = HFI_INTRA_REFRESH_CYCLIC;
+                       break;
+               case HAL_INTRA_REFRESH_CYCLIC_ADAPTIVE:
+                       hfi->mode = HFI_INTRA_REFRESH_CYCLIC_ADAPTIVE;
+                       break;
+               case HAL_INTRA_REFRESH_RANDOM:
+                       hfi->mode = HFI_INTRA_REFRESH_RANDOM;
+                       break;
+               default:
+                       dprintk(VIDC_ERR,
+                               "Invalid intra refresh setting: %#x\n",
+                               prop->mode);
+                       break;
+               }
+               hfi->air_mbs = prop->air_mbs;
+               hfi->air_ref = prop->air_ref;
+               hfi->cir_mbs = prop->cir_mbs;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_MULTI_SLICE_CONTROL: {
+               struct hal_multi_slice_control *prop = pdata;
+               struct hfi_multi_slice_control *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_CONTROL;
+               hfi = (struct hfi_multi_slice_control *)
+                       &pkt->rg_property_data[1];
+               switch (prop->multi_slice) {
+               case HAL_MULTI_SLICE_OFF:
+                       hfi->multi_slice = HFI_MULTI_SLICE_OFF;
+                       break;
+               case HAL_MULTI_SLICE_GOB:
+                       hfi->multi_slice = HFI_MULTI_SLICE_GOB;
+                       break;
+               case HAL_MULTI_SLICE_BY_MB_COUNT:
+                       hfi->multi_slice = HFI_MULTI_SLICE_BY_MB_COUNT;
+                       break;
+               case HAL_MULTI_SLICE_BY_BYTE_COUNT:
+                       hfi->multi_slice = HFI_MULTI_SLICE_BY_BYTE_COUNT;
+                       break;
+               default:
+                       dprintk(VIDC_ERR, "Invalid slice settings: %#x\n",
+                               prop->multi_slice);
+                       break;
+               }
+               hfi->slice_size = prop->slice_size;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_INDEX_EXTRADATA: {
+               struct hal_extradata_enable *extra = pdata;
+               struct hfi_index_extradata_config *hfi;
+               int id = 0;
+
+               pkt->rg_property_data[0] =
+                       to_hfi_extradata_index(extra->index);
+               hfi = (struct hfi_index_extradata_config *)
+                       &pkt->rg_property_data[1];
+               hfi->enable = extra->enable;
+               id = to_hfi_extradata_id(extra->index);
+               if (id) {
+                       hfi->index_extra_data_id = id;
+               } else {
+                       dprintk(VIDC_WARN, "failed to find extradata id: %d\n",
+                               id);
+                       ret = -EINVAL;
+               }
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_SLICE_DELIVERY_MODE: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_SLICE_DELIVERY_MODE;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hal_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_H264_VUI_TIMING_INFO: {
+               struct hal_h264_vui_timing_info *timing_info = pdata;
+               struct hfi_h264_vui_timing_info *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO;
+
+               hfi = (struct hfi_h264_vui_timing_info *)
+                               &pkt->rg_property_data[1];
+               hfi->enable = timing_info->enable;
+               hfi->fixed_frame_rate = timing_info->fixed_frame_rate;
+               hfi->time_scale = timing_info->time_scale;
+
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_CONFIG_VPE_DEINTERLACE: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VPE_DEINTERLACE;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hal_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_H264_GENERATE_AUDNAL: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_H264_GENERATE_AUDNAL;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hal_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_BUFFER_ALLOC_MODE: {
+               struct hal_buffer_alloc_mode *hal = pdata;
+               struct hfi_buffer_alloc_mode *hfi;
+               u32 buf_type, buf_mode;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE;
+               hfi = (struct hfi_buffer_alloc_mode *)
+                               &pkt->rg_property_data[1];
+               buf_type = to_hfi_buffer(hal->type);
+               if (!buf_type)
+                       return -EINVAL;
+               hfi->type = buf_type;
+               buf_mode = to_hfi_buf_mode(hal->mode);
+               if (!buf_mode)
+                       return -EINVAL;
+               hfi->mode = buf_mode;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VDEC_FRAME_ASSEMBLY: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VDEC_FRAME_ASSEMBLY;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hfi_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_H264_VUI_BITSTREAM_RESTRC: {
+               struct hal_h264_vui_bitstream_restrc *hal = pdata;
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_H264_VUI_BITSTREAM_RESTRC;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = hal->enable;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_PRESERVE_TEXT_QUALITY: {
+               struct hal_preserve_text_quality *hal = pdata;
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_PRESERVE_TEXT_QUALITY;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = hal->enable;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VDEC_SCS_THRESHOLD: {
+               struct hfi_scs_threshold *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VDEC_SCS_THRESHOLD;
+               hfi = (struct hfi_scs_threshold *) &pkt->rg_property_data[1];
+               hfi->threshold_value =
+                       ((struct hfi_scs_threshold *) pdata)->threshold_value;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_MVC_BUFFER_LAYOUT: {
+               struct hal_mvc_buffer_layout *layout_info = pdata;
+               struct hfi_mvc_buffer_layout_descp_type *hfi;
+
+               pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_MVC_BUFFER_LAYOUT;
+               hfi = (struct hfi_mvc_buffer_layout_descp_type *)
+                       &pkt->rg_property_data[1];
+               hfi->layout_type = to_hfi_layout(layout_info->layout_type);
+               hfi->bright_view_first = layout_info->bright_view_first;
+               hfi->ngap = layout_info->ngap;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_LTRMODE: {
+               struct hal_ltr_mode *hal = pdata;
+               struct hfi_ltr_mode *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_LTRMODE;
+               hfi = (struct hfi_ltr_mode *) &pkt->rg_property_data[1];
+               hfi->ltr_mode = to_hfi_ltr_mode(hal->mode);
+               hfi->ltr_count = hal->count;
+               hfi->trust_mode = hal->trust_mode;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_CONFIG_VENC_USELTRFRAME: {
+               struct hal_ltr_use *hal = pdata;
+               struct hfi_ltr_use *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VENC_USELTRFRAME;
+               hfi = (struct hfi_ltr_use *) &pkt->rg_property_data[1];
+               hfi->frames = hal->frames;
+               hfi->ref_ltr = hal->ref_ltr;
+               hfi->use_constrnt = hal->use_constraint;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_CONFIG_VENC_MARKLTRFRAME: {
+               struct hal_ltr_mark *hal = pdata;
+               struct hfi_ltr_mark *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VENC_MARKLTRFRAME;
+               hfi = (struct hfi_ltr_mark *) &pkt->rg_property_data[1];
+               hfi->mark_frame = hal->mark_frame;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_HIER_P_MAX_ENH_LAYERS: {
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER;
+               pkt->rg_property_data[1] = *(u32 *)pdata;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_CONFIG_VENC_HIER_P_NUM_FRAMES: {
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER;
+               pkt->rg_property_data[1] = *(u32 *)pdata;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VENC_DISABLE_RC_TIMESTAMP: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_DISABLE_RC_TIMESTAMP;
+               hfi = (struct hfi_enable *)&pkt->rg_property_data[1];
+               hfi->enable = ((struct hfi_enable *)pdata)->enable;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VENC_ENABLE_INITIAL_QP: {
+               struct hal_initial_quantization *quant = pdata;
+               struct hfi_initial_quantization *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_INITIAL_QP;
+               hfi = (struct hfi_initial_quantization *)
+                       &pkt->rg_property_data[1];
+               hfi->init_qp_enable = quant->init_qp_enable;
+               hfi->qp_i = quant->qpi;
+               hfi->qp_p = quant->qpp;
+               hfi->qp_b = quant->qpb;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VPE_COLOR_SPACE_CONVERSION: {
+               struct hal_vpe_color_space_conversion *hal = pdata;
+               struct hfi_vpe_color_space_conversion *hfi;
+
+               pkt->rg_property_data[0] =
+                               HFI_PROPERTY_PARAM_VPE_COLOR_SPACE_CONVERSION;
+               hfi = (struct hfi_vpe_color_space_conversion *)
+                       &pkt->rg_property_data[1];
+               memcpy(hfi->csc_matrix, hal->csc_matrix,
+                               sizeof(hfi->csc_matrix));
+               memcpy(hfi->csc_bias, hal->csc_bias, sizeof(hfi->csc_bias));
+               memcpy(hfi->csc_limit, hal->csc_limit, sizeof(hfi->csc_limit));
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_VPX_ERROR_RESILIENCE_MODE: {
+               struct hal_enable *err_res = pdata;
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_VPX_ERROR_RESILIENCE_MODE;
+               hfi = (struct hfi_enable *)&pkt->rg_property_data[1];
+               hfi->enable = err_res->enable;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_H264_NAL_SVC_EXT: {
+               struct hal_enable *svc_nal = pdata;
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_H264_NAL_SVC_EXT;
+               hfi = (struct hfi_enable *)&pkt->rg_property_data[1];
+               hfi->enable = svc_nal->enable;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_CONFIG_VENC_PERF_MODE: {
+               pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_VENC_PERF_MODE;
+               pkt->rg_property_data[1] = *(u32 *)pdata;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VENC_HIER_B_MAX_ENH_LAYERS: {
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_HIER_B_MAX_NUM_ENH_LAYER;
+               pkt->rg_property_data[1] = *(u32 *)pdata;
+               pkt->size += sizeof(u32) * 2;
+               break;
+       }
+       case HAL_PARAM_VDEC_NON_SECURE_OUTPUT2: {
+               struct hfi_enable *hfi;
+
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VDEC_NONCP_OUTPUT2;
+               hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+               hfi->enable = ((struct hfi_enable *) pdata)->enable;
+               pkt->size += sizeof(u32) + sizeof(*hfi);
+               break;
+       }
+       case HAL_PARAM_VENC_HIER_P_HYBRID_MODE: {
+               pkt->rg_property_data[0] =
+                       HFI_PROPERTY_PARAM_VENC_HIER_P_HYBRID_MODE;
+               pkt->rg_property_data[1] =
+                       ((struct hfi_hybrid_hierp *)pdata)->layers;
+               pkt->size += sizeof(u32) + sizeof(struct hfi_hybrid_hierp);
+               break;
+       }
+       /* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
+       case HAL_CONFIG_BUFFER_REQUIREMENTS:
+       case HAL_CONFIG_PRIORITY:
+       case HAL_CONFIG_BATCH_INFO:
+       case HAL_PARAM_METADATA_PASS_THROUGH:
+       case HAL_SYS_IDLE_INDICATOR:
+       case HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
+       case HAL_PARAM_INTERLACE_FORMAT_SUPPORTED:
+       case HAL_PARAM_CHROMA_SITE:
+       case HAL_PARAM_PROPERTIES_SUPPORTED:
+       case HAL_PARAM_PROFILE_LEVEL_SUPPORTED:
+       case HAL_PARAM_CAPABILITY_SUPPORTED:
+       case HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
+       case HAL_PARAM_MULTI_VIEW_FORMAT:
+       case HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE:
+       case HAL_PARAM_CODEC_SUPPORTED:
+       case HAL_PARAM_VDEC_MULTI_VIEW_SELECT:
+       case HAL_PARAM_VDEC_MB_QUANTIZATION:
+       case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
+       case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
+       case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
+       case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
+       case HAL_CONFIG_VDEC_MULTI_STREAM:
+       case HAL_PARAM_VENC_MULTI_SLICE_INFO:
+       case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
+       case HAL_PARAM_VENC_LOW_LATENCY:
+       default:
+               return -ENOTSUPP;
+       }
+
+       return ret;
+}
+
+static u32 to_hfi_ssr_type(enum hal_ssr_trigger_type type)
+{
+       switch (type) {
+       case SSR_ERR_FATAL:
+               return HFI_TEST_SSR_SW_ERR_FATAL;
+       case SSR_SW_DIV_BY_ZERO:
+               return HFI_TEST_SSR_SW_DIV_BY_ZERO;
+       case SSR_HW_WDOG_IRQ:
+               return HFI_TEST_SSR_HW_WDOG_IRQ;
+       default:
+               dprintk(VIDC_WARN,
+                       "SSR trigger type not recognized, using WDOG.\n");
+               break;
+       }
+
+       return HFI_TEST_SSR_HW_WDOG_IRQ;
+}
+
+static int pkt_ssr_cmd(enum hal_ssr_trigger_type type,
+                      struct hfi_sys_test_ssr_pkt *pkt)
+{
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SYS_TEST_SSR;
+       pkt->trigger_type = to_hfi_ssr_type(type);
+
+       return 0;
+}
+
+static int pkt_sys_image_version(struct hfi_sys_get_property_pkt *pkt)
+{
+       pkt->size = sizeof(*pkt);
+       pkt->packet_type = HFI_CMD_SYS_GET_PROPERTY;
+       pkt->num_properties = 1;
+       pkt->rg_property_data[0] = HFI_PROPERTY_SYS_IMAGE_VERSION;
+
+       return 0;
+}
+
+static const struct hfi_packetization_ops hfi_default = {
+       .sys_init = pkt_sys_init,
+       .sys_pc_prep = pkt_sys_pc_prep,
+       .sys_idle_indicator = pkt_sys_idle_indicator,
+       .sys_power_control = pkt_sys_power_control,
+       .sys_set_resource = pkt_sys_set_resource,
+       .sys_debug_config = pkt_sys_debug_config,
+       .sys_coverage_config = pkt_sys_coverage_config,
+       .sys_release_resource = pkt_sys_release_resource,
+       .sys_ping = pkt_sys_ping,
+       .sys_image_version = pkt_sys_image_version,
+       .ssr_cmd = pkt_ssr_cmd,
+       .session_init = pkt_session_init,
+       .session_cmd = pkt_session_cmd,
+       .session_set_buffers = pkt_session_set_buffers,
+       .session_release_buffers = pkt_session_release_buffers,
+       .session_etb_decoder = pkt_session_etb_decoder,
+       .session_etb_encoder = pkt_session_etb_encoder,
+       .session_ftb = pkt_session_ftb,
+       .session_parse_seq_header = pkt_session_parse_seq_header,
+       .session_get_seq_hdr = pkt_session_get_seq_hdr,
+       .session_flush = pkt_session_flush,
+       .session_get_property = pkt_session_get_property,
+       .session_set_property = pkt_session_set_property,
+};
+
+static const struct hfi_packetization_ops *get_venus_3_x_ops(void)
+{
+       static const struct hfi_packetization_ops *hfi_venus_3_x;
+
+       hfi_venus_3_x = &hfi_default;
+
+       /* Override new HFI functions for HFI_PACKETIZATION_3XX here. */
+
+       return hfi_venus_3_x;
+}
+
+const struct hfi_packetization_ops *
+hfi_get_pkt_ops(enum hfi_packetization_type type)
+{
+       dprintk(VIDC_DBG, "%s selected\n",
+               type == HFI_PACKETIZATION_LEGACY ? "legacy packetization" :
+               type == HFI_PACKETIZATION_3XX ? "3xx packetization" :
+               "Unknown hfi");
+
+       switch (type) {
+       case HFI_PACKETIZATION_LEGACY:
+               return &hfi_default;
+       case HFI_PACKETIZATION_3XX:
+               return get_venus_3_x_ops();
+       }
+
+       return NULL;
+}
diff --git a/drivers/media/platform/msm/vidc/hfi/hfi_packetization.h b/drivers/media/platform/msm/vidc/hfi/hfi_packetization.h
new file mode 100644 (file)
index 0000000..3386145
--- /dev/null
@@ -0,0 +1,91 @@
+/* Copyright (c) 2012-2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __HFI_PACKETIZATION__
+#define __HFI_PACKETIZATION__
+
+#include <linux/types.h>
+#include "vidc_hfi_helper.h"
+#include "vidc_hfi.h"
+#include "vidc_hfi_api.h"
+
+#define call_hfi_pkt_op(q, op, args...)                        \
+       (((q) && (q)->pkt_ops && (q)->pkt_ops->op) ?    \
+       ((q)->pkt_ops->op(args)) : -EINVAL)
+
+enum hfi_packetization_type {
+       HFI_PACKETIZATION_LEGACY,
+       HFI_PACKETIZATION_3XX,
+};
+
+struct hfi_packetization_ops {
+       int (*sys_init)(struct hfi_sys_init_pkt *pkt, u32 arch_type);
+       int (*sys_pc_prep)(struct hfi_sys_pc_prep_pkt *pkt);
+       int (*sys_idle_indicator)(struct hfi_sys_set_property_pkt *pkt,
+                                 u32 enable);
+       int (*sys_power_control)(struct hfi_sys_set_property_pkt *pkt,
+                                u32 enable);
+       int (*sys_set_resource)(struct hfi_sys_set_resource_pkt *pkt,
+                               struct vidc_resource_hdr *resource_hdr,
+                               void *resource_value);
+       int (*sys_debug_config)(struct hfi_sys_set_property_pkt *pkt, u32 mode);
+       int (*sys_coverage_config)(struct hfi_sys_set_property_pkt *pkt,
+                                  u32 mode);
+       int (*sys_release_resource)(struct hfi_sys_release_resource_pkt *pkt,
+                                   struct vidc_resource_hdr *resource_hdr);
+       int (*sys_ping)(struct hfi_cmd_sys_ping_packet *pkt);
+       int (*sys_image_version)(struct hfi_sys_get_property_pkt *pkt);
+       int (*ssr_cmd)(enum hal_ssr_trigger_type type,
+                      struct hfi_sys_test_ssr_pkt *pkt);
+       int (*session_init)(struct hfi_session_init_pkt *pkt,
+                           struct hal_session *session,
+                           u32 session_domain, u32 session_codec);
+       int (*session_cmd)(struct vidc_hal_session_cmd_pkt *pkt,
+               int pkt_type, struct hal_session *session);
+       int (*session_set_buffers)(struct hfi_session_set_buffers_pkt *pkt,
+                                  struct hal_session *session,
+                                  struct vidc_buffer_addr_info *buffer_info);
+       int (*session_release_buffers)(
+               struct hfi_cmd_session_release_buffer_packet *pkt,
+               struct hal_session *session,
+               struct vidc_buffer_addr_info *buffer_info);
+       int (*session_etb_decoder)(
+               struct hfi_cmd_session_empty_buffer_compressed_packet *pkt,
+               struct hal_session *session,
+               struct vidc_frame_data *input_frame);
+       int (*session_etb_encoder)(
+               struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
+               *pkt, struct hal_session *session,
+               struct vidc_frame_data *input_frame);
+       int (*session_ftb)(struct hfi_cmd_session_fill_buffer_packet *pkt,
+               struct hal_session *session,
+               struct vidc_frame_data *output_frame);
+       int (*session_parse_seq_header)(
+               struct hfi_cmd_session_parse_sequence_header_packet *pkt,
+               struct hal_session *session, struct vidc_seq_hdr *seq_hdr);
+       int (*session_get_seq_hdr)(
+               struct hfi_session_get_sequence_header_pkt *pkt,
+               struct hal_session *session, struct vidc_seq_hdr *seq_hdr);
+       int (*session_flush)(struct hfi_cmd_session_flush_packet *pkt,
+               struct hal_session *session, enum hal_flush flush_mode);
+       int (*session_get_property)(
+               struct hfi_cmd_session_get_property_packet *pkt,
+               struct hal_session *session, enum hal_property ptype);
+       int (*session_set_property)(struct hfi_session_set_property_pkt *pkt,
+                                   struct hal_session *session,
+                                   enum hal_property ptype, void *pdata);
+};
+
+const struct hfi_packetization_ops *
+hfi_get_pkt_ops(enum hfi_packetization_type);
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/hfi/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi/hfi_response_handler.c
new file mode 100644 (file)
index 0000000..5843bc0
--- /dev/null
@@ -0,0 +1,1292 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/hash.h>
+
+#include "msm_vidc_debug.h"
+#include "msm_vidc_common.h"
+
+#include "hfi/vidc_hfi_helper.h"
+#include "hfi/vidc_hfi.h"
+
+static enum vidc_error to_vidc_error(u32 hfi_err)
+{
+       switch (hfi_err) {
+       case HFI_ERR_NONE:
+       case HFI_ERR_SESSION_SAME_STATE_OPERATION:
+               return VIDC_ERR_NONE;
+       case HFI_ERR_SYS_FATAL:
+               return VIDC_ERR_HW_FATAL;
+       case HFI_ERR_SYS_VERSION_MISMATCH:
+       case HFI_ERR_SYS_INVALID_PARAMETER:
+       case HFI_ERR_SYS_SESSION_ID_OUT_OF_RANGE:
+       case HFI_ERR_SESSION_INVALID_PARAMETER:
+       case HFI_ERR_SESSION_INVALID_SESSION_ID:
+       case HFI_ERR_SESSION_INVALID_STREAM_ID:
+               return VIDC_ERR_BAD_PARAM;
+       case HFI_ERR_SYS_INSUFFICIENT_RESOURCES:
+       case HFI_ERR_SYS_UNSUPPORTED_DOMAIN:
+       case HFI_ERR_SYS_UNSUPPORTED_CODEC:
+       case HFI_ERR_SESSION_UNSUPPORTED_PROPERTY:
+       case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
+       case HFI_ERR_SESSION_INSUFFICIENT_RESOURCES:
+       case HFI_ERR_SESSION_UNSUPPORTED_STREAM:
+               return VIDC_ERR_NOT_SUPPORTED;
+       case HFI_ERR_SYS_MAX_SESSIONS_REACHED:
+               return VIDC_ERR_MAX_CLIENTS;
+       case HFI_ERR_SYS_SESSION_IN_USE:
+               return VIDC_ERR_CLIENT_PRESENT;
+       case HFI_ERR_SESSION_FATAL:
+               return VIDC_ERR_CLIENT_FATAL;
+       case HFI_ERR_SESSION_BAD_POINTER:
+               return VIDC_ERR_BAD_PARAM;
+       case HFI_ERR_SESSION_INCORRECT_STATE_OPERATION:
+               return VIDC_ERR_BAD_STATE;
+       case HFI_ERR_SESSION_STREAM_CORRUPT:
+       case HFI_ERR_SESSION_STREAM_CORRUPT_OUTPUT_STALLED:
+               return VIDC_ERR_BITSTREAM_ERR;
+       case HFI_ERR_SESSION_SYNC_FRAME_NOT_DETECTED:
+               return VIDC_ERR_IFRAME_EXPECTED;
+       case HFI_ERR_SESSION_START_CODE_NOT_FOUND:
+               return VIDC_ERR_START_CODE_NOT_FOUND;
+       case HFI_ERR_SESSION_EMPTY_BUFFER_DONE_OUTPUT_PENDING:
+       default:
+               return VIDC_ERR_FAIL;
+       }
+
+       return VIDC_ERR_FAIL;
+}
+
+static struct hal_session *
+to_hal_session(struct list_head *sessions, u32 session_id)
+{
+       struct hal_session *session = NULL;
+       bool found = false;
+
+       list_for_each_entry(session, sessions, list) {
+               if (hash32_ptr(session) == session_id) {
+                       found = true;
+                       break;
+               }
+       }
+
+       return found ? session : NULL;
+}
+
+static void event_seq_changed(u32 device_id, struct hal_session *session,
+                             struct hfi_msg_event_notify_pkt *pkt)
+{
+       struct vidc_inst *inst = session->session_id;
+       struct vidc_cb_event event = {0};
+       int num_properties_changed;
+       struct hfi_frame_size *frame_sz;
+       struct hfi_profile_level *profile_level;
+       u8 *data_ptr;
+       u32 prop_id;
+
+       switch (pkt->event_data1) {
+       case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES:
+               event.hal_event_type =
+                       HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES;
+               break;
+       case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUFFER_RESOURCES:
+               event.hal_event_type =
+                       HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES;
+               break;
+       default:
+               break;
+       }
+
+       num_properties_changed = pkt->event_data2;
+       if (!num_properties_changed)
+               goto done;
+
+       data_ptr = (u8 *) &pkt->rg_ext_event_data[0];
+       do {
+               prop_id = *((u32 *)data_ptr);
+               switch (prop_id) {
+               case HFI_PROPERTY_PARAM_FRAME_SIZE:
+                       data_ptr += sizeof(u32);
+                       frame_sz = (struct hfi_frame_size *) data_ptr;
+                       event.width = frame_sz->width;
+                       event.height = frame_sz->height;
+                       data_ptr += sizeof(frame_sz);
+                       break;
+               case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
+                       data_ptr += sizeof(u32);
+                       profile_level = (struct hfi_profile_level *) data_ptr;
+                       event.profile = profile_level->profile;
+                       event.level = profile_level->level;
+                       data_ptr += sizeof(profile_level);
+                       break;
+               default:
+                       dprintk(VIDC_DBG, "%s cmd: %#x not supported\n",
+                               __func__, prop_id);
+                       break;
+               }
+               num_properties_changed--;
+       } while (num_properties_changed > 0);
+
+done:
+       if (!inst->event_notify)
+               return;
+
+       inst->error = VIDC_ERR_NONE;
+       inst->event_notify(inst, SYS_EVENT_CHANGE, &event);
+}
+
+static void event_release_buffer_ref(u32 device_id, struct hal_session *session,
+                                    struct hfi_msg_event_notify_pkt *pkt)
+{
+       struct vidc_inst *inst = session->session_id;
+       struct vidc_cb_event event = {0};
+       struct hfi_msg_event_release_buffer_ref_pkt *data;
+
+       data = (struct hfi_msg_event_release_buffer_ref_pkt *)
+               pkt->rg_ext_event_data;
+
+       event.hal_event_type = HAL_EVENT_RELEASE_BUFFER_REFERENCE;
+       event.packet_buffer = data->packet_buffer;
+       event.extra_data_buffer = data->extra_data_buffer;
+
+       if (!inst->event_notify)
+               return;
+
+       inst->error = VIDC_ERR_NONE;
+       inst->event_notify(inst, SYS_EVENT_CHANGE, &event);
+}
+
+static void event_sys_error(u32 device_id, u32 event)
+{
+       struct vidc_core *core;
+
+       core = vidc_get_core(device_id);
+       if (IS_ERR(core)) {
+               dprintk(VIDC_ERR, "Got SYS_ERR but unable to identify core\n");
+               return;
+       }
+
+       if (!core->event_notify)
+               return;
+
+       core->event_notify(core, device_id, event);
+}
+
+static void event_session_error(u32 device_id, struct hal_session *session,
+                               struct hfi_msg_event_notify_pkt *pkt)
+{
+       struct vidc_inst *inst = session->session_id;
+
+       dprintk(VIDC_INFO, "received: SESSION_ERROR with event id:%d\n",
+               pkt->event_data1);
+
+       if (!inst->event_notify)
+               return;
+
+       switch (pkt->event_data1) {
+       /* non fatal session errors */
+       case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
+       case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
+       case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
+       case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
+               inst->error = VIDC_ERR_NONE;
+               break;
+       default:
+               inst->error = to_vidc_error(pkt->event_data1);
+               inst->event_notify(inst, SESSION_ERROR, NULL);
+               break;
+       }
+}
+
+static void hfi_event_notify(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct hfi_msg_event_notify_pkt *pkt = packet;
+
+       switch (pkt->event_id) {
+       case HFI_EVENT_SYS_ERROR:
+               dprintk(VIDC_ERR, "HFI_EVENT_SYS_ERROR: %d, %#x\n",
+                       pkt->event_data1, pkt->event_data2);
+               event_sys_error(device_id, SYS_ERROR);
+               break;
+       }
+
+       if (!session) {
+               dprintk(VIDC_ERR, "%s: got invalid session id\n", __func__);
+               return;
+       }
+
+       switch (pkt->event_id) {
+       case HFI_EVENT_SESSION_ERROR:
+               event_session_error(device_id, session, pkt);
+               break;
+       case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
+               event_seq_changed(device_id, session, pkt);
+               break;
+       case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
+               event_release_buffer_ref(device_id, session, pkt);
+               break;
+       case HFI_EVENT_SESSION_PROPERTY_CHANGED:
+               break;
+       default:
+               break;
+       }
+}
+
+static void hfi_sys_init_done(u32 device_id, void *sess, void *packet)
+{
+       struct hfi_msg_sys_init_done_pkt *pkt = packet;
+       struct vidc_hal_sys_init_done sys_init_done = {0};
+       u32 rem_bytes, read_bytes = 0, num_properties;
+       struct vidc_core *core;
+       enum vidc_error error;
+       u8 *data_ptr;
+       u32 prop_id;
+
+       error = to_vidc_error(pkt->error_type);
+       if (error != VIDC_ERR_NONE)
+               goto err_no_prop;
+
+       if (!pkt->num_properties) {
+               dprintk(VIDC_ERR, "%s: no properties\n", __func__);
+               error = VIDC_ERR_FAIL;
+               goto err_no_prop;
+       }
+
+       rem_bytes = pkt->size;
+       rem_bytes -= sizeof(struct hfi_msg_sys_init_done_pkt);
+       rem_bytes += sizeof(u32);
+
+       if (!rem_bytes) {
+               dprintk(VIDC_ERR, "%s: missing property data\n", __func__);
+               error = VIDC_ERR_FAIL;
+               goto err_no_prop;
+       }
+
+       data_ptr = (u8 *) &pkt->rg_property_data[0];
+       num_properties = pkt->num_properties;
+
+       while (num_properties && rem_bytes >= sizeof(u32)) {
+               prop_id = *((u32 *)data_ptr);
+               data_ptr += sizeof(u32);
+
+               switch (prop_id) {
+               case HFI_PROPERTY_PARAM_CODEC_SUPPORTED: {
+                       struct hfi_codec_supported *prop;
+
+                       prop = (struct hfi_codec_supported *) data_ptr;
+
+                       if (rem_bytes < sizeof(*prop)) {
+                               error = VIDC_ERR_BAD_PARAM;
+                               break;
+                       }
+                       sys_init_done.dec_codec_supported =
+                               prop->decoder_codec_supported;
+                       sys_init_done.enc_codec_supported =
+                               prop->encoder_codec_supported;
+                       break;
+               }
+               default:
+                       dprintk(VIDC_ERR, "%s: bad property id: %x\n", __func__,
+                               prop_id);
+                       error = VIDC_ERR_BAD_PARAM;
+                       break;
+               }
+
+               if (!error) {
+                       rem_bytes -= read_bytes;
+                       data_ptr += read_bytes;
+                       num_properties--;
+               }
+       }
+
+err_no_prop:
+       core = vidc_get_core(device_id);
+       if (IS_ERR(core)) {
+               dprintk(VIDC_ERR, "wrong device id received\n");
+               return;
+       }
+
+       core->enc_codecs = sys_init_done.enc_codec_supported;
+       core->dec_codecs = sys_init_done.dec_codec_supported;
+
+       if (core->id == VIDC_CORE_VENUS &&
+          (core->dec_codecs & HAL_VIDEO_CODEC_H264))
+               core->dec_codecs |= HAL_VIDEO_CODEC_MVC;
+
+       dprintk(VIDC_DBG, "supported_codecs: enc = %#x, dec = %#x\n",
+               core->enc_codecs, core->dec_codecs);
+
+       core->error = error;
+       complete(&core->done);
+}
+
+static void
+sys_get_prop_image_version(struct hfi_msg_sys_property_info_packet *pkt)
+{
+       int i = 0;
+       char version[256];
+       const u32 version_string_size = 128;
+       u8 *str_image_version;
+       int req_bytes;
+
+       req_bytes = pkt->size - sizeof(*pkt);
+
+       if (req_bytes < version_string_size || !pkt->rg_property_data[1] ||
+           pkt->num_properties > 1) {
+               dprintk(VIDC_ERR, "%s: bad packet: %d\n", __func__, req_bytes);
+               return;
+       }
+
+       str_image_version = (u8 *)&pkt->rg_property_data[1];
+
+       /*
+        * The version string returned by firmware includes null
+        * characters at the start and in between. Replace the null
+        * characters with space, to print the version info.
+        */
+       for (i = 0; i < version_string_size; i++) {
+               if (str_image_version[i] != '\0')
+                       version[i] = str_image_version[i];
+               else
+                       version[i] = ' ';
+       }
+
+       version[i] = '\0';
+
+       dprintk(VIDC_DBG, "F/W version: %s\n", version);
+}
+
+static void hfi_sys_property_info(u32 device_id, void *sess, void *packet)
+{
+       struct hfi_msg_sys_property_info_packet *pkt = packet;
+
+       if (!pkt->num_properties) {
+               dprintk(VIDC_ERR, "%s: no properties\n", __func__);
+               return;
+       }
+
+       switch (pkt->rg_property_data[0]) {
+       case HFI_PROPERTY_SYS_IMAGE_VERSION:
+               sys_get_prop_image_version(pkt);
+               break;
+       default:
+               dprintk(VIDC_ERR, "%s: unknown_property data: %x\n", __func__,
+                       pkt->rg_property_data[0]);
+               break;
+       }
+}
+
+static void hfi_sys_rel_resource_done(u32 device_id, void *sess, void *packet)
+{
+       struct hfi_msg_sys_release_resource_done_pkt *pkt = packet;
+       struct vidc_core *core;
+
+       core = vidc_get_core(device_id);
+       if (IS_ERR(core)) {
+               dprintk(VIDC_ERR, "wrong core id received\n");
+               return;
+       }
+
+       core->error = to_vidc_error(pkt->error_type);
+       complete(&core->done);
+}
+
+static void hfi_copy_cap_prop(struct hfi_capability_supported *in,
+                             struct vidc_hal_session_init_done *sess_init_done)
+{
+       struct hal_capability_supported *out;
+
+       if (!in || !sess_init_done) {
+               dprintk(VIDC_ERR, "%s: invalid input parameter\n", __func__);
+               return;
+       }
+
+       switch (in->capability_type) {
+       case HFI_CAPABILITY_FRAME_WIDTH:
+               out = &sess_init_done->width;
+               break;
+       case HFI_CAPABILITY_FRAME_HEIGHT:
+               out = &sess_init_done->height;
+               break;
+       case HFI_CAPABILITY_MBS_PER_FRAME:
+               out = &sess_init_done->mbs_per_frame;
+               break;
+       case HFI_CAPABILITY_MBS_PER_SECOND:
+               out = &sess_init_done->mbs_per_sec;
+               break;
+       case HFI_CAPABILITY_FRAMERATE:
+               out = &sess_init_done->frame_rate;
+               break;
+       case HFI_CAPABILITY_SCALE_X:
+               out = &sess_init_done->scale_x;
+               break;
+       case HFI_CAPABILITY_SCALE_Y:
+               out = &sess_init_done->scale_y;
+               break;
+       case HFI_CAPABILITY_BITRATE:
+               out = &sess_init_done->bitrate;
+               break;
+       case HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS:
+               out = &sess_init_done->hier_p;
+               break;
+       case HFI_CAPABILITY_ENC_LTR_COUNT:
+               out = &sess_init_done->ltr_count;
+               break;
+       case HFI_CAPABILITY_CP_OUTPUT2_THRESH:
+               out = &sess_init_done->secure_output2_threshold;
+               break;
+       default:
+               out = NULL;
+               break;
+       }
+
+       if (out) {
+               out->min = in->min;
+               out->max = in->max;
+               out->step_size = in->step_size;
+       }
+}
+
+static void
+session_get_prop_profile_level(struct hfi_msg_session_property_info_packet *pkt,
+                              struct hfi_profile_level *profile_level)
+{
+       struct hfi_profile_level *hfi_profile_level;
+       u32 req_bytes;
+
+       req_bytes = pkt->size - sizeof(*pkt);
+
+       if (!req_bytes || req_bytes % sizeof(struct hfi_profile_level)) {
+               dprintk(VIDC_ERR, "%s: bad packet\n", __func__);
+               return;
+       }
+
+       hfi_profile_level =
+               (struct hfi_profile_level *) &pkt->rg_property_data[1];
+       profile_level->profile = hfi_profile_level->profile;
+       profile_level->level = hfi_profile_level->level;
+
+       dprintk(VIDC_DBG, "%s profile: %d level: %d\n",
+               __func__, profile_level->profile, profile_level->level);
+}
+
+static void
+session_get_prop_buf_req(struct hfi_msg_session_property_info_packet *pkt,
+                        struct buffer_requirements *buffreq)
+{
+       struct hfi_buffer_requirements *buf_req;
+       u32 req_bytes;
+
+       req_bytes = pkt->size - sizeof(*pkt);
+
+       if (!req_bytes || req_bytes % sizeof(*buf_req) ||
+           !pkt->rg_property_data[1]) {
+               dprintk(VIDC_ERR, "%s: bad packet\n", __func__);
+               return;
+       }
+
+       buf_req = (struct hfi_buffer_requirements *) &pkt->rg_property_data[1];
+
+       if (!buf_req) {
+               dprintk(VIDC_ERR, "%s: invalid req buffer\n", __func__);
+               return;
+       }
+
+       while (req_bytes) {
+               if (buf_req->size && buf_req->count_min > buf_req->count_actual)
+                       dprintk(VIDC_WARN, "%s: bad req buffer\n", __func__);
+
+               dprintk(VIDC_DBG, "got buffer requirements for: %x\n",
+                       buf_req->type);
+
+               switch (buf_req->type) {
+               case HFI_BUFFER_INPUT:
+                       memcpy(&buffreq->buffer[0], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[0].type = HAL_BUFFER_INPUT;
+                       break;
+               case HFI_BUFFER_OUTPUT:
+                       memcpy(&buffreq->buffer[1], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[1].type = HAL_BUFFER_OUTPUT;
+                       break;
+               case HFI_BUFFER_OUTPUT2:
+                       memcpy(&buffreq->buffer[2], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[2].type = HAL_BUFFER_OUTPUT2;
+                       break;
+               case HFI_BUFFER_EXTRADATA_INPUT:
+                       memcpy(&buffreq->buffer[3], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[3].type = HAL_BUFFER_EXTRADATA_INPUT;
+                       break;
+               case HFI_BUFFER_EXTRADATA_OUTPUT:
+                       memcpy(&buffreq->buffer[4], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[4].type = HAL_BUFFER_EXTRADATA_OUTPUT;
+                       break;
+               case HFI_BUFFER_EXTRADATA_OUTPUT2:
+                       memcpy(&buffreq->buffer[5], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[5].type = HAL_BUFFER_EXTRADATA_OUTPUT2;
+                       break;
+               case HFI_BUFFER_INTERNAL_SCRATCH:
+                       memcpy(&buffreq->buffer[6], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[6].type = HAL_BUFFER_INTERNAL_SCRATCH;
+                       break;
+               case HFI_BUFFER_INTERNAL_SCRATCH_1:
+                       memcpy(&buffreq->buffer[7], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[7].type = HAL_BUFFER_INTERNAL_SCRATCH_1;
+                       break;
+               case HFI_BUFFER_INTERNAL_SCRATCH_2:
+                       memcpy(&buffreq->buffer[8], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[8].type = HAL_BUFFER_INTERNAL_SCRATCH_2;
+                       break;
+               case HFI_BUFFER_INTERNAL_PERSIST:
+                       memcpy(&buffreq->buffer[9], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[9].type = HAL_BUFFER_INTERNAL_PERSIST;
+                       break;
+               case HFI_BUFFER_INTERNAL_PERSIST_1:
+                       memcpy(&buffreq->buffer[10], buf_req, sizeof(*buf_req));
+                       buffreq->buffer[10].type =
+                               HAL_BUFFER_INTERNAL_PERSIST_1;
+                       break;
+               default:
+                       dprintk(VIDC_ERR, "%s: bad buffer type: %d\n", __func__,
+                               buf_req->type);
+                       break;
+               }
+
+               req_bytes -= sizeof(struct hfi_buffer_requirements);
+               buf_req++;
+       }
+}
+
+static void hfi_session_prop_info(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_session_property_info_packet *pkt = packet;
+       struct hfi_profile_level profile_level = {0};
+       struct buffer_requirements bufreq;
+       struct getprop_buf *getprop;
+       void *data;
+       size_t len;
+
+       inst->error = VIDC_ERR_NONE;
+
+       if (!pkt->num_properties) {
+               dprintk(VIDC_ERR, "%s: no properties\n", __func__);
+               return;
+       }
+
+       switch (pkt->rg_property_data[0]) {
+       case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
+               memset(&bufreq, 0, sizeof(bufreq));
+               session_get_prop_buf_req(pkt, &bufreq);
+               data = &bufreq;
+               len = sizeof(bufreq);
+               break;
+       case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT:
+               session_get_prop_profile_level(pkt, &profile_level);
+               data = &profile_level;
+               len = sizeof(profile_level);
+               break;
+       default:
+               dprintk(VIDC_DBG, "%s: unknown property id:%x\n", __func__,
+                       pkt->rg_property_data[0]);
+               return;
+       }
+
+       getprop = kzalloc(sizeof(*getprop), GFP_KERNEL);
+       if (!getprop) {
+               dprintk(VIDC_ERR, "%s: getprop kzalloc failed\n", __func__);
+               return;
+       }
+
+       getprop->data = kmemdup(data, len, GFP_KERNEL);
+       if (!getprop->data) {
+               dprintk(VIDC_ERR, "%s: kmemdup failed\n", __func__);
+               kfree(getprop);
+               return;
+       }
+
+       mutex_lock(&inst->pending_getpropq.lock);
+       list_add_tail(&getprop->list, &inst->pending_getpropq.list);
+       mutex_unlock(&inst->pending_getpropq.lock);
+
+       complete(&inst->done);
+}
+
+static enum vidc_error
+session_init_done_prop_read(struct hfi_msg_session_init_done_pkt *pkt,
+                           struct vidc_hal_session_init_done *sess_init_done)
+{
+       u32 rem_bytes, num_properties;
+       u32 prop_id, next_offset = 0;
+       enum vidc_error error;
+       u32 prop_count = 0;
+       u8 *data_ptr;
+
+       rem_bytes = pkt->size - sizeof(*pkt) + sizeof(u32);
+
+       if (!rem_bytes) {
+               dprintk(VIDC_ERR, "%s: missing property info\n", __func__);
+               return VIDC_ERR_FAIL;
+       }
+
+       error = to_vidc_error(pkt->error_type);
+       if (error)
+               return error;
+
+       data_ptr = (u8 *) &pkt->rg_property_data[0];
+       num_properties = pkt->num_properties;
+
+       while (error == VIDC_ERR_NONE && num_properties &&
+              rem_bytes >= sizeof(u32)) {
+               prop_id = *((u32 *)data_ptr);
+               next_offset = sizeof(u32);
+
+               switch (prop_id) {
+               case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED: {
+                       struct hfi_capability_supported_info *prop =
+                               (struct hfi_capability_supported_info *)
+                               (data_ptr + next_offset);
+                       u32 num_caps;
+                       struct hfi_capability_supported *cap_ptr;
+
+                       if ((rem_bytes - next_offset) < sizeof(*cap_ptr)) {
+                               error = VIDC_ERR_BAD_PARAM;
+                               break;
+                       }
+
+                       num_caps = prop->num_capabilities;
+                       cap_ptr = &prop->rg_data[0];
+                       next_offset += sizeof(u32);
+
+                       while (num_caps &&
+                             (rem_bytes - next_offset) >= sizeof(u32)) {
+                               hfi_copy_cap_prop(cap_ptr, sess_init_done);
+                               cap_ptr++;
+                               next_offset += sizeof(*cap_ptr);
+                               num_caps--;
+                       }
+                       num_properties--;
+                       break;
+               }
+               case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED: {
+                       struct hfi_uncompressed_format_supported *prop =
+                               (struct hfi_uncompressed_format_supported *)
+                               (data_ptr + next_offset);
+                       u32 num_format_entries;
+                       char *fmt_ptr;
+                       struct hfi_uncompressed_plane_info *plane_info;
+
+                       if ((rem_bytes - next_offset) < sizeof(*prop)) {
+                               error = VIDC_ERR_BAD_PARAM;
+                               break;
+                       }
+
+                       num_format_entries = prop->format_entries;
+                       next_offset = sizeof(*prop) - sizeof(u32);
+                       fmt_ptr = (char *)&prop->rg_format_info[0];
+
+                       while (num_format_entries) {
+                               u32 bytes_to_skip;
+                               plane_info =
+                               (struct hfi_uncompressed_plane_info *) fmt_ptr;
+
+                               if ((rem_bytes - next_offset) <
+                                    sizeof(*plane_info)) {
+                                       error = VIDC_ERR_BAD_PARAM;
+                                       break;
+                               }
+
+                               bytes_to_skip = sizeof(*plane_info) -
+                                       sizeof(struct
+                                       hfi_uncompressed_plane_constraints) +
+                                       plane_info->num_planes *
+                                       sizeof(struct
+                                       hfi_uncompressed_plane_constraints);
+
+                               fmt_ptr +=  bytes_to_skip;
+                               next_offset += bytes_to_skip;
+                               num_format_entries--;
+                       }
+                       num_properties--;
+                       break;
+               }
+               case HFI_PROPERTY_PARAM_PROPERTIES_SUPPORTED: {
+                       struct hfi_properties_supported *prop =
+                               (struct hfi_properties_supported *)
+                               (data_ptr + next_offset);
+
+                       next_offset += sizeof(*prop) - sizeof(u32)
+                                       + prop->num_properties * sizeof(u32);
+                       num_properties--;
+                       break;
+               }
+               case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED: {
+                       char *ptr = NULL;
+                       int count = 0;
+                       struct hfi_profile_level *prop_level;
+                       struct hfi_profile_level_supported *prop =
+                               (struct hfi_profile_level_supported *)
+                               (data_ptr + next_offset);
+
+                       ptr = (char *) &prop->rg_profile_level[0];
+                       dprintk(VIDC_DBG, "prop->profile_count: %d\n",
+                               prop->profile_count);
+                       prop_count = prop->profile_count;
+                       if (prop_count > MAX_PROFILE_COUNT) {
+                               prop_count = MAX_PROFILE_COUNT;
+                               dprintk(VIDC_WARN,
+                                       "prop count exceeds max profile count\n");
+                       }
+                       while (prop_count) {
+                               ptr++;
+                               prop_level = (struct hfi_profile_level *) ptr;
+                               sess_init_done->
+                               profile_level.profile_level[count].profile
+                                       = prop_level->profile;
+                               sess_init_done->
+                               profile_level.profile_level[count].level
+                                       = prop_level->level;
+                               prop_count--;
+                               count++;
+                               ptr +=
+                               sizeof(struct hfi_profile_level) / sizeof(u32);
+                       }
+                       next_offset += sizeof(*prop) -
+                               sizeof(struct hfi_profile_level) +
+                               prop->profile_count *
+                               sizeof(struct hfi_profile_level);
+                       num_properties--;
+                       break;
+               }
+               case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED: {
+                       next_offset +=
+                               sizeof(struct hfi_nal_stream_format_supported);
+                       num_properties--;
+                       break;
+               }
+               case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT: {
+                       next_offset += sizeof(u32);
+                       num_properties--;
+                       break;
+               }
+               case HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE: {
+                       next_offset += sizeof(u32);
+                       num_properties--;
+                       break;
+               }
+               case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH: {
+                       next_offset += sizeof(struct hfi_intra_refresh);
+                       num_properties--;
+                       break;
+               }
+               case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED: {
+                       struct hfi_buffer_alloc_mode_supported *prop =
+                               (struct hfi_buffer_alloc_mode_supported *)
+                               (data_ptr + next_offset);
+                       int i;
+
+                       if (prop->buffer_type == HFI_BUFFER_OUTPUT ||
+                           prop->buffer_type == HFI_BUFFER_OUTPUT2) {
+                               sess_init_done->alloc_mode_out = 0;
+
+                               for (i = 0; i < prop->num_entries; i++) {
+                                       switch (prop->rg_data[i]) {
+                                       case HFI_BUFFER_MODE_STATIC:
+                                               sess_init_done->alloc_mode_out
+                                               |= HAL_BUFFER_MODE_STATIC;
+                                               break;
+                                       case HFI_BUFFER_MODE_DYNAMIC:
+                                               sess_init_done->alloc_mode_out
+                                               |= HAL_BUFFER_MODE_DYNAMIC;
+                                               break;
+                                       }
+
+                                       if (i >= 32) {
+                                               dprintk(VIDC_ERR,
+                                               "%s - num_entries: %d from f/w seems suspect\n",
+                                               __func__, prop->num_entries);
+                                               break;
+                                       }
+                               }
+                       }
+                       next_offset += sizeof(*prop) -
+                               sizeof(u32) + prop->num_entries * sizeof(u32);
+                       num_properties--;
+                       break;
+               }
+               default:
+                       dprintk(VIDC_DBG, "%s: default case %#x\n", __func__,
+                               prop_id);
+                       break;
+               }
+
+               rem_bytes -= next_offset;
+               data_ptr += next_offset;
+       }
+
+       return error;
+}
+
+static void hfi_session_init_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_device *hdev = inst->core->hfidev;
+       struct hfi_msg_session_init_done_pkt *pkt = packet;
+       struct vidc_core_capability *cap = &inst->capability;
+       struct vidc_hal_session_init_done init_done;
+       enum vidc_error error;
+
+       error = to_vidc_error(pkt->error_type);
+       if (error != VIDC_ERR_NONE)
+               goto done;
+
+       memset(&init_done, 0, sizeof(init_done));
+
+       error = session_init_done_prop_read(pkt, &init_done);
+       if (error != VIDC_ERR_NONE)
+               goto done;
+
+       cap->width = init_done.width;
+       cap->height = init_done.height;
+       cap->frame_rate = init_done.frame_rate;
+       cap->scale_x = init_done.scale_x;
+       cap->scale_y = init_done.scale_y;
+       cap->hier_p = init_done.hier_p;
+       cap->ltr_count = init_done.ltr_count;
+       cap->pixelprocess_capabilities =
+                       call_hfi_op(hdev, get_core_capabilities);
+       cap->mbs_per_frame = init_done.mbs_per_frame;
+       cap->buffer_mode[CAPTURE_PORT] = init_done.alloc_mode_out;
+       cap->secure_output2_threshold = init_done.secure_output2_threshold;
+       cap->capability_set = true;
+
+done:
+       inst->error = error;
+       complete(&inst->done);
+}
+
+static void hfi_session_load_res_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_session_load_resources_done_packet *pkt = packet;
+
+       inst->error = to_vidc_error(pkt->error_type);
+       complete(&inst->done);
+}
+
+static void hfi_session_flush_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_session_flush_done_packet *pkt = packet;
+
+       inst->error = to_vidc_error(pkt->error_type);
+       complete(&inst->done);
+}
+
+static void hfi_session_etb_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_session_empty_buffer_done_packet *pkt = packet;
+       u32 flags = 0;
+
+       inst->error = to_vidc_error(pkt->error_type);
+
+       if (inst->error == VIDC_ERR_NOT_SUPPORTED)
+               flags |= V4L2_QCOM_BUF_INPUT_UNSUPPORTED;
+       if (inst->error == VIDC_ERR_BITSTREAM_ERR)
+               flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
+       if (inst->error == VIDC_ERR_START_CODE_NOT_FOUND)
+               flags |= V4L2_MSM_VIDC_BUF_START_CODE_NOT_FOUND;
+
+       if (!inst->empty_buf_done)
+               return;
+
+       inst->empty_buf_done(inst, pkt->input_tag, pkt->filled_len, pkt->offset,
+                            flags);
+}
+
+static void hfi_session_ftb_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       bool is_decoder = session->is_decoder;
+       struct vidc_hal_fbd fbd = {0};
+       enum hal_buffer buffer_type;
+       struct timeval timestamp;
+       int64_t time_usec = 0;
+       unsigned int error;
+       u32 flags = 0;
+
+       if (!is_decoder) {
+               struct hfi_msg_session_fbd_compressed_packet *pkt = packet;
+
+               fbd.timestamp_hi = pkt->time_stamp_hi;
+               fbd.timestamp_lo = pkt->time_stamp_lo;
+               fbd.flags1 = pkt->flags;
+               fbd.offset1 = pkt->offset;
+               fbd.alloc_len1 = pkt->alloc_len;
+               fbd.filled_len1 = pkt->filled_len;
+               fbd.picture_type = pkt->picture_type;
+               fbd.packet_buffer1 = pkt->packet_buffer;
+               fbd.extra_data_buffer = pkt->extra_data_buffer;
+               fbd.buffer_type = HAL_BUFFER_OUTPUT;
+
+               error = to_vidc_error(pkt->error_type);
+       } else {
+               struct hfi_msg_session_fbd_uncompressed_plane0_packet *pkt;
+
+               pkt = packet;
+
+               fbd.timestamp_hi = pkt->time_stamp_hi;
+               fbd.timestamp_lo = pkt->time_stamp_lo;
+               fbd.flags1 = pkt->flags;
+               fbd.offset1 = pkt->offset;
+               fbd.alloc_len1 = pkt->alloc_len;
+               fbd.filled_len1 = pkt->filled_len;
+               fbd.picture_type = pkt->picture_type;
+               fbd.packet_buffer1 = pkt->packet_buffer;
+               fbd.extra_data_buffer = pkt->extra_data_buffer;
+
+               if (pkt->stream_id == 0)
+                       fbd.buffer_type = HAL_BUFFER_OUTPUT;
+               else if (pkt->stream_id == 1)
+                       fbd.buffer_type = HAL_BUFFER_OUTPUT2;
+
+               error = to_vidc_error(pkt->error_type);
+       }
+
+       buffer_type = vidc_comm_get_hal_output_buffer(inst);
+
+       if (fbd.buffer_type != buffer_type)
+               return;
+
+       if (fbd.flags1 & HAL_BUFFERFLAG_READONLY)
+               flags |= V4L2_QCOM_BUF_FLAG_READONLY;
+       if (fbd.flags1 & HAL_BUFFERFLAG_EOS)
+               flags |= V4L2_QCOM_BUF_FLAG_EOS;
+       if (fbd.flags1 & HAL_BUFFERFLAG_CODECCONFIG)
+               flags &= ~V4L2_QCOM_BUF_FLAG_CODECCONFIG;
+       if (fbd.flags1 & HAL_BUFFERFLAG_SYNCFRAME)
+               flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
+       if (fbd.flags1 & HAL_BUFFERFLAG_EOSEQ)
+               flags |= V4L2_QCOM_BUF_FLAG_EOSEQ;
+       if (fbd.flags1 & HAL_BUFFERFLAG_DECODEONLY)
+               flags |= V4L2_QCOM_BUF_FLAG_DECODEONLY;
+       if (fbd.flags1 & HAL_BUFFERFLAG_DATACORRUPT)
+               flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
+       if (fbd.flags1 & HAL_BUFFERFLAG_DROP_FRAME)
+               flags |= V4L2_QCOM_BUF_DROP_FRAME;
+       if (fbd.flags1 & HAL_BUFFERFLAG_MBAFF)
+               flags |= V4L2_MSM_BUF_FLAG_MBAFF;
+       if (fbd.flags1 & HAL_BUFFERFLAG_TS_DISCONTINUITY)
+               flags |= V4L2_QCOM_BUF_TS_DISCONTINUITY;
+       if (fbd.flags1 & HAL_BUFFERFLAG_TS_ERROR)
+               flags |= V4L2_QCOM_BUF_TS_ERROR;
+
+       switch (fbd.picture_type) {
+       case HAL_PICTURE_IDR:
+               flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
+               flags |= V4L2_BUF_FLAG_KEYFRAME;
+               break;
+       case HAL_PICTURE_I:
+               flags |= V4L2_BUF_FLAG_KEYFRAME;
+               break;
+       case HAL_PICTURE_P:
+               flags |= V4L2_BUF_FLAG_PFRAME;
+               break;
+       case HAL_PICTURE_B:
+               flags |= V4L2_BUF_FLAG_BFRAME;
+               break;
+       case HAL_FRAME_NOTCODED:
+       case HAL_UNUSED_PICT:
+       case HAL_FRAME_YUV:
+               break;
+       default:
+               break;
+       }
+
+       if (!(fbd.flags1 & HAL_BUFFERFLAG_TIMESTAMPINVALID) &&
+             fbd.filled_len1) {
+               time_usec = fbd.timestamp_hi;
+               time_usec = (time_usec << 32) | fbd.timestamp_lo;
+       }
+
+       timestamp = ns_to_timeval(time_usec * NSEC_PER_USEC);
+
+       if (!inst->fill_buf_done)
+               return;
+
+       inst->error = error;
+       inst->fill_buf_done(inst, fbd.packet_buffer1, fbd.filled_len1,
+                           fbd.offset1, flags, &timestamp);
+}
+
+static void hfi_session_start_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_session_start_done_packet *pkt = packet;
+
+       inst->error = to_vidc_error(pkt->error_type);
+       complete(&inst->done);
+}
+
+static void hfi_session_stop_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_session_stop_done_packet *pkt = packet;
+
+       inst->error = to_vidc_error(pkt->error_type);
+       complete(&inst->done);
+}
+
+static void hfi_session_rel_res_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_session_release_resources_done_packet *pkt = packet;
+
+       inst->error = to_vidc_error(pkt->error_type);
+       complete(&inst->done);
+}
+
+static void hfi_session_rel_buf_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_session_release_buffers_done_packet *pkt = packet;
+
+       /*
+        * the address of the released buffer can be extracted:
+        * if (pkt->rg_buffer_info) {
+        *      cmd.data = &pkt->rg_buffer_info;
+        *      cmd.size = sizeof(struct hfi_buffer_info);
+        * }
+        */
+       inst->error = to_vidc_error(pkt->error_type);
+       complete(&inst->done);
+}
+
+static void hfi_session_end_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_session_end_done_pkt *pkt = packet;
+
+       inst->error = to_vidc_error(pkt->error_type);
+       complete(&inst->done);
+}
+
+static void hfi_session_abort_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_sys_session_abort_done_packet *pkt = packet;
+
+       inst->error = to_vidc_error(pkt->error_type);
+       complete(&inst->done);
+}
+
+static void
+hfi_session_get_seq_hdr_done(u32 device_id, void *sess, void *packet)
+{
+       struct hal_session *session = sess;
+       struct vidc_inst *inst = session->session_id;
+       struct hfi_msg_session_get_sequence_hdr_done_pkt *pkt = packet;
+
+       /*
+        * output_done.packet_buffer1 = pkt->sequence_header;
+        * output_done.filled_len1 = pkt->header_len;
+        */
+
+       inst->error = to_vidc_error(pkt->error_type);
+       complete(&inst->done);
+}
+
+typedef void (*done_handler)(u32, void *, void *);
+
+struct hfi_done_handler {
+       const char *name;
+       u32 packet;
+       u32 packet_sz;
+       u32 packet_sz2;
+       done_handler done;
+       bool is_sys_pkt;
+};
+
+static const struct hfi_done_handler handlers[] = {
+       {.name = "event_notify",
+        .packet = HFI_MSG_EVENT_NOTIFY,
+        .packet_sz = sizeof(struct hfi_msg_event_notify_pkt),
+        .done = hfi_event_notify,
+       },
+       {.name = "sys_init_done",
+        .packet = HFI_MSG_SYS_INIT_DONE,
+        .packet_sz = sizeof(struct hfi_msg_sys_init_done_pkt),
+        .done = hfi_sys_init_done,
+        .is_sys_pkt = true,
+       },
+       {.name = "sys_property_info",
+        .packet = HFI_MSG_SYS_PROPERTY_INFO,
+        .packet_sz = sizeof(struct hfi_msg_sys_property_info_packet),
+        .done = hfi_sys_property_info,
+        .is_sys_pkt = true,
+       },
+       {.name = "sys_release_resource",
+        .packet = HFI_MSG_SYS_RELEASE_RESOURCE,
+        .packet_sz = sizeof(struct hfi_msg_sys_release_resource_done_pkt),
+        .done = hfi_sys_rel_resource_done,
+        .is_sys_pkt = true,
+       },
+       {.name = "session_init_done",
+        .packet = HFI_MSG_SYS_SESSION_INIT_DONE,
+        .packet_sz = sizeof(struct hfi_msg_session_init_done_pkt),
+        .done = hfi_session_init_done,
+       },
+       {.name = "session_end_done",
+        .packet = HFI_MSG_SYS_SESSION_END_DONE,
+        .packet_sz = sizeof(struct hfi_msg_session_end_done_pkt),
+        .done = hfi_session_end_done,
+       },
+       {.name = "session_load_resources_done",
+        .packet = HFI_MSG_SESSION_LOAD_RESOURCES_DONE,
+        .packet_sz = sizeof(struct hfi_msg_session_load_resources_done_packet),
+        .done = hfi_session_load_res_done,
+       },
+       {.name = "session_start_done",
+        .packet = HFI_MSG_SESSION_START_DONE,
+        .packet_sz = sizeof(struct hfi_msg_session_start_done_packet),
+        .done = hfi_session_start_done,
+       },
+       {.name = "session_stop_done",
+        .packet = HFI_MSG_SESSION_STOP_DONE,
+        .packet_sz = sizeof(struct hfi_msg_session_stop_done_packet),
+        .done = hfi_session_stop_done,
+       },
+       {.name = "session_abort_done",
+        .packet = HFI_MSG_SYS_SESSION_ABORT_DONE,
+        .packet_sz = sizeof(struct hfi_msg_sys_session_abort_done_packet),
+        .done = hfi_session_abort_done,
+       },
+       {.name = "session_empty_buffer_done",
+        .packet = HFI_MSG_SESSION_EMPTY_BUFFER_DONE,
+        .packet_sz = sizeof(struct hfi_msg_session_empty_buffer_done_packet),
+        .done = hfi_session_etb_done,
+       },
+       {.name = "session_fill_buffer_done",
+        .packet = HFI_MSG_SESSION_FILL_BUFFER_DONE,
+        .packet_sz =
+               sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_packet),
+        .packet_sz2 = sizeof(struct hfi_msg_session_fbd_compressed_packet),
+        .done = hfi_session_ftb_done,
+       },
+       {.name = "session_flush_done",
+        .packet = HFI_MSG_SESSION_FLUSH_DONE,
+        .packet_sz = sizeof(struct hfi_msg_session_flush_done_packet),
+        .done = hfi_session_flush_done,
+       },
+       {.name = "session_propery_info",
+        .packet = HFI_MSG_SESSION_PROPERTY_INFO,
+        .packet_sz = sizeof(struct hfi_msg_session_property_info_packet),
+        .done = hfi_session_prop_info,
+       },
+       {.name = "session_release_resources_done",
+        .packet = HFI_MSG_SESSION_RELEASE_RESOURCES_DONE,
+        .packet_sz =
+               sizeof(struct hfi_msg_session_release_resources_done_packet),
+        .done = hfi_session_rel_res_done,
+       },
+       {.name = "session_get_sequence_header_done",
+        .packet = HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE,
+        .packet_sz = sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt),
+        .done = hfi_session_get_seq_hdr_done,
+       },
+       {.name = "session_release_buffers_done",
+        .packet = HFI_MSG_SESSION_RELEASE_BUFFERS_DONE,
+        .packet_sz =
+               sizeof(struct hfi_msg_session_release_buffers_done_packet),
+        .done = hfi_session_rel_buf_done,
+       },
+};
+
+void hfi_process_watchdog_timeout(u32 device_id)
+{
+       event_sys_error(device_id, SYS_WATCHDOG_TIMEOUT);
+}
+
+u32 hfi_process_msg_packet(u32 device_id, struct vidc_hal_msg_pkt_hdr *hdr,
+                          struct list_head *sessions,
+                          struct mutex *session_lock)
+{
+       struct hal_session *session;
+       const struct hfi_done_handler *handler;
+       unsigned int i;
+       bool found = false;
+
+       for (i = 0; i < ARRAY_SIZE(handlers); i++) {
+               handler = &handlers[i];
+
+               if (handler->packet != hdr->packet)
+                       continue;
+
+               found = true;
+               break;
+       }
+
+       if (found == false)
+               return hdr->packet;
+
+       if (hdr->size && hdr->size < handler->packet_sz &&
+           hdr->size < handler->packet_sz2) {
+               pr_err("%s: bad packet size (%d should be %d, pkt type:%x)\n",
+                       __func__, hdr->size, handler->packet_sz, hdr->packet);
+
+               return hdr->packet;
+       }
+
+       mutex_lock(session_lock);
+       if (handler->is_sys_pkt) {
+               session = NULL;
+       } else {
+               struct vidc_hal_session_cmd_pkt *pkt;
+
+               pkt = (struct vidc_hal_session_cmd_pkt *)hdr;
+               session = to_hal_session(sessions, pkt->session_id);
+
+               /*
+                * Event of type HFI_EVENT_SYS_ERROR will not have any session
+                * associated with it
+                */
+               if (!session && hdr->packet != HFI_MSG_EVENT_NOTIFY) {
+                       pr_err("%s: got invalid session id:%d\n", __func__,
+                               pkt->session_id);
+                       goto invalid_session;
+               }
+       }
+
+       handler->done(device_id, session, hdr);
+
+invalid_session:
+       mutex_unlock(session_lock);
+
+       return hdr->packet;
+}
diff --git a/drivers/media/platform/msm/vidc/hfi/venus/venus_hfi.c b/drivers/media/platform/msm/vidc/hfi/venus/venus_hfi.c
new file mode 100644 (file)
index 0000000..9b6bb44
--- /dev/null
@@ -0,0 +1,1890 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/qcom_scm.h>
+
+#include <linux/soc/qcom/smem.h>
+
+#include "hfi/hfi_packetization.h"
+#include "msm_vidc_debug.h"
+#include "venus_hfi.h"
+#include "vidc_hfi_io.h"
+#include "msm_smem.h"
+
+static struct hal_device_data hal_ctxt;
+
+/* Poll interval in uS */
+#define POLL_INTERVAL_US       50
+
+enum tzbsp_video_state {
+       TZBSP_VIDEO_STATE_SUSPEND = 0,
+       TZBSP_VIDEO_STATE_RESUME
+};
+
+static int venus_hfi_session_clean(void *session);
+
+static void venus_pm_handler(struct work_struct *work);
+static DECLARE_DELAYED_WORK(venus_hfi_pm_work, venus_pm_handler);
+static int venus_hfi_resume(void *dev);
+static inline int venus_power_on(struct venus_hfi_device *device);
+static void venus_flush_debug_queue(struct venus_hfi_device *device,
+                                   void *packet);
+static int venus_hfi_initialize_packetization(struct venus_hfi_device *device);
+
+static DECLARE_COMPLETION(release_resources_done);
+static DECLARE_COMPLETION(pc_prep_done);
+
+static inline void venus_set_state(struct venus_hfi_device *hdev,
+                                  enum venus_state state)
+{
+       mutex_lock(&hdev->lock);
+       hdev->state = state;
+       mutex_unlock(&hdev->lock);
+}
+
+static inline bool venus_is_valid_state(struct venus_hfi_device *hdev)
+{
+       return hdev->state != VENUS_STATE_DEINIT;
+}
+
+static void venus_dump_packet(u8 *packet)
+{
+       u32 c = 0, packet_size = *(u32 *)packet;
+       const int row_size = 32;
+       /*
+        * row must contain enough for 0xdeadbaad * 8 to be converted into
+        * "de ad ba ab " * 8 + '\0'
+        */
+       char row[3 * row_size];
+
+       for (c = 0; c * row_size < packet_size; ++c) {
+               int bytes_to_read = ((c + 1) * row_size > packet_size) ?
+                       packet_size % row_size : row_size;
+               hex_dump_to_buffer(packet + c * row_size, bytes_to_read,
+                                  row_size, 4, row, sizeof(row), false);
+               dprintk(VIDC_PKT, "%s\n", row);
+       }
+}
+
+static int venus_write_queue(struct iface_queue *queue, u8 *packet,
+                            u32 *rx_req_is_set)
+{
+       struct hfi_queue_header *qhdr;
+       u32 packet_size_in_words, new_write_idx;
+       u32 empty_space, read_idx, write_idx;
+       u32 *write_ptr;
+
+       if (!queue->qarray.kva)
+               return -EINVAL;
+
+       qhdr = queue->qhdr;
+       if (!qhdr)
+               return -ENOMEM;
+
+       if (vidc_debug & VIDC_PKT)
+               venus_dump_packet(packet);
+
+       packet_size_in_words = (*(u32 *)packet) >> 2;
+       if (!packet_size_in_words)
+               return -EINVAL;
+
+       read_idx = qhdr->read_idx;
+       write_idx = qhdr->write_idx;
+
+       if (write_idx >= read_idx)
+               empty_space = qhdr->q_size - (write_idx - read_idx);
+       else
+               empty_space = read_idx - write_idx;
+
+       if (empty_space <= packet_size_in_words) {
+               qhdr->tx_req = 1;
+               return -ENOSPC;
+       }
+
+       qhdr->tx_req = 0;
+
+       new_write_idx = write_idx + packet_size_in_words;
+       write_ptr = (u32 *)(queue->qarray.kva + (write_idx << 2));
+       if (new_write_idx < qhdr->q_size) {
+               memcpy(write_ptr, packet, packet_size_in_words << 2);
+       } else {
+               new_write_idx -= qhdr->q_size;
+               memcpy(write_ptr, packet,
+                      (packet_size_in_words - new_write_idx) << 2);
+               memcpy((void *)queue->qarray.kva,
+                       packet + ((packet_size_in_words - new_write_idx) << 2),
+                       new_write_idx << 2);
+       }
+
+       /* Memory barrier to make sure packet is written before updating the
+        * write index
+        */
+       mb();
+
+       qhdr->write_idx = new_write_idx;
+       *rx_req_is_set = (1 == qhdr->rx_req) ? 1 : 0;
+
+       /* Memory barrier to make sure write index is updated before an
+        * interupt is raised on venus.
+        */
+       mb();
+
+       return 0;
+}
+
+static int venus_read_queue(struct iface_queue *queue, u8 *packet,
+                           u32 *pb_tx_req_is_set)
+{
+       struct hfi_queue_header *qhdr;
+       u32 packet_size_in_words, new_read_idx;
+       u32 *read_ptr;
+       u32 receive_request = 0;
+       int ret = 0;
+
+       if (!queue->qarray.kva)
+               return -EINVAL;
+
+       /* Memory barrier to make sure data is valid before reading it */
+       mb();
+
+       qhdr = queue->qhdr;
+       if (!qhdr)
+               return -ENOMEM;
+
+       /*
+        * Do not set receive request for debug queue, if set,
+        * Venus generates interrupt for debug messages even
+        * when there is no response message available.
+        * In general debug queue will not become full as it
+        * is being emptied out for every interrupt from Venus.
+        * Venus will anyway generates interrupt if it is full.
+        */
+       if (qhdr->type & HFI_Q_ID_CTRL_TO_HOST_MSG_Q)
+               receive_request = 1;
+
+       if (qhdr->read_idx == qhdr->write_idx) {
+               qhdr->rx_req = receive_request;
+               *pb_tx_req_is_set = 0;
+               return -ENODATA;
+       }
+
+       read_ptr = (u32 *)(queue->qarray.kva + (qhdr->read_idx << 2));
+       packet_size_in_words = (*read_ptr) >> 2;
+       if (!packet_size_in_words)
+               return -EINVAL;
+
+       new_read_idx = qhdr->read_idx + packet_size_in_words;
+       if (((packet_size_in_words << 2) <= VIDC_IFACEQ_VAR_HUGE_PKT_SIZE) &&
+           qhdr->read_idx <= qhdr->q_size) {
+               if (new_read_idx < qhdr->q_size) {
+                       memcpy(packet, read_ptr, packet_size_in_words << 2);
+               } else {
+                       new_read_idx -= qhdr->q_size;
+                       memcpy(packet, read_ptr,
+                              (packet_size_in_words - new_read_idx) << 2);
+                       memcpy(packet +
+                              ((packet_size_in_words - new_read_idx) << 2),
+                              (u8 *)queue->qarray.kva,
+                              new_read_idx << 2);
+               }
+       } else {
+               /* bad packet received, dropping */
+               new_read_idx = qhdr->write_idx;
+               ret = -EBADMSG;
+       }
+
+       qhdr->read_idx = new_read_idx;
+
+       if (qhdr->read_idx != qhdr->write_idx)
+               qhdr->rx_req = 0;
+       else
+               qhdr->rx_req = receive_request;
+
+       *pb_tx_req_is_set = (1 == qhdr->tx_req) ? 1 : 0;
+
+       if (vidc_debug & VIDC_PKT)
+               venus_dump_packet(packet);
+
+       return ret;
+}
+
+static int venus_alloc(struct venus_hfi_device *hdev, struct mem_desc *vmem,
+                      u32 size, u32 align, u32 flags, u32 usage)
+{
+       struct smem *mem;
+       int ret;
+
+       venus_hfi_resume(hdev);
+
+       mem = smem_alloc(hdev->mem_client, size, align, flags, usage, 1);
+       if (IS_ERR(mem))
+               return PTR_ERR(mem);
+
+       ret = smem_cache_operations(hdev->mem_client, mem, SMEM_CACHE_CLEAN);
+       if (ret) {
+               dprintk(VIDC_WARN, "Failed to clean cache\n");
+               dprintk(VIDC_WARN, "This may result in undefined behavior\n");
+       }
+
+       vmem->size = mem->size;
+       vmem->smem = mem;
+       vmem->kva = mem->kvaddr;
+       vmem->da = mem->da;
+
+       return 0;
+}
+
+static void venus_free(struct venus_hfi_device *hdev, struct smem *mem)
+{
+       smem_free(hdev->mem_client, mem);
+}
+
+static void venus_writel(struct venus_hfi_device *hdev, u32 reg, u32 value)
+{
+       writel(value, hdev->hal_data->base + reg);
+}
+
+static u32 venus_readl(struct venus_hfi_device *hdev, u32 reg)
+{
+       return readl(hdev->hal_data->base + reg);
+}
+
+static void venus_set_registers(struct venus_hfi_device *hdev)
+{
+       struct reg_set *regs = &hdev->res->reg_set;
+       const struct reg_value_pair *tbl = regs->reg_tbl;
+       int i;
+
+       for (i = 0; i < regs->count; i++)
+               venus_writel(hdev, tbl[i].reg, tbl[i].value);
+}
+
+static int venus_iface_cmdq_write_nolock(struct venus_hfi_device *hdev,
+                                        void *pkt)
+{
+       u32 rx_req_is_set = 0;
+       struct iface_queue *queue;
+       struct vidc_hal_cmd_pkt_hdr *cmd_packet;
+       int ret;
+
+       WARN(!mutex_is_locked(&hdev->lock),
+            "Cmd queue write lock must be acquired");
+
+       if (!venus_is_valid_state(hdev)) {
+               dprintk(VIDC_DBG, "%s: fw not in init state\n", __func__);
+               return -EINVAL;
+       }
+
+       cmd_packet = (struct vidc_hal_cmd_pkt_hdr *)pkt;
+       hdev->last_packet_type = cmd_packet->packet_type;
+
+       queue = &hdev->queues[IFACEQ_CMD_IDX];
+
+       ret = venus_write_queue(queue, pkt, &rx_req_is_set);
+       if (ret) {
+               dprintk(VIDC_ERR, "iface cmdq queue is full\n");
+               return ret;
+       }
+
+       ret = venus_power_on(hdev);
+       if (ret)
+               return ret;
+
+       if (rx_req_is_set)
+               venus_writel(hdev, VIDC_CPU_IC_SOFTINT,
+                            1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT);
+
+       if (hdev->res->sw_power_collapsible) {
+               dprintk(VIDC_DBG, "cancel and queue delayed work again\n");
+
+               cancel_delayed_work(&venus_hfi_pm_work);
+
+               if (!queue_delayed_work(hdev->venus_pm_workq,
+                                       &venus_hfi_pm_work,
+                                       msecs_to_jiffies(
+                                       vidc_pwr_collapse_delay))) {
+                       dprintk(VIDC_DBG,
+                               "PM work already scheduled\n");
+               }
+       }
+
+       return 0;
+}
+
+static int venus_iface_cmdq_write(struct venus_hfi_device *hdev, void *pkt)
+{
+       int ret;
+
+       mutex_lock(&hdev->lock);
+       ret = venus_iface_cmdq_write_nolock(hdev, pkt);
+       mutex_unlock(&hdev->lock);
+
+       return ret;
+}
+
+static int
+venus_hfi_core_set_resource(void *device, struct vidc_resource_hdr *hdr,
+                           void *resource_value, bool locked)
+{
+       struct venus_hfi_device *hdev = device;
+       struct hfi_sys_set_resource_pkt *pkt;
+       u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+       int ret;
+
+       pkt = (struct hfi_sys_set_resource_pkt *) packet;
+
+       ret = call_hfi_pkt_op(hdev, sys_set_resource, pkt, hdr, resource_value);
+       if (ret)
+               return ret;
+
+       ret = locked ? venus_iface_cmdq_write(hdev, pkt) :
+                      venus_iface_cmdq_write_nolock(hdev, pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int
+venus_hfi_core_release_resource(void *device, struct vidc_resource_hdr *hdr)
+{
+       struct hfi_sys_release_resource_pkt pkt;
+       struct venus_hfi_device *hdev = device;
+       int ret;
+
+       ret = call_hfi_pkt_op(hdev, sys_release_resource, &pkt, hdr);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, &pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_tzbsp_set_video_state(enum tzbsp_video_state state)
+{
+       return qcom_scm_set_video_state(state, 0);
+}
+
+static int venus_reset_core(struct venus_hfi_device *hdev)
+{
+       u32 ctrl_status = 0, count = 0;
+       int max_tries = 100, ret = 0;
+
+       venus_writel(hdev, VIDC_CTRL_INIT, 0x1);
+
+       venus_writel(hdev, VIDC_WRAPPER_INTR_MASK,
+                    VIDC_WRAPPER_INTR_MASK_A2HVCODEC_BMSK);
+
+       while (!ctrl_status && count < max_tries) {
+               ctrl_status = venus_readl(hdev, VIDC_CPU_CS_SCIACMDARG0);
+               if ((ctrl_status & 0xfe) == 0x4) {
+                       dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
+                       ret = -EINVAL;
+                       break;
+               }
+
+               usleep_range(500, 1000);
+               count++;
+       }
+
+       if (count >= max_tries)
+               ret = -ETIMEDOUT;
+
+       return ret;
+}
+
+static int venus_run(struct venus_hfi_device *hdev)
+{
+       int ret;
+
+       /*
+        * Re-program all of the registers that get reset as a result of
+        * regulator_disable() and _enable()
+        */
+       venus_set_registers(hdev);
+
+       venus_writel(hdev, VIDC_UC_REGION_ADDR, hdev->ifaceq_table.da);
+       venus_writel(hdev, VIDC_UC_REGION_SIZE, SHARED_QSIZE);
+       venus_writel(hdev, VIDC_CPU_CS_SCIACMDARG2, hdev->ifaceq_table.da);
+       venus_writel(hdev, VIDC_CPU_CS_SCIACMDARG1, 0x01);
+       if (hdev->sfr.da)
+               venus_writel(hdev, VIDC_SFR_ADDR, hdev->sfr.da);
+
+       venus_writel(hdev, VIDC_WRAPPER_CLOCK_CONFIG, 0);
+       venus_writel(hdev, VIDC_WRAPPER_CPU_CLOCK_CONFIG, 0);
+
+       ret = venus_reset_core(hdev);
+       if (ret) {
+               dprintk(VIDC_ERR, "Failed to reset venus core\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int venus_halt_axi(struct venus_hfi_device *hdev)
+{
+       void __iomem *base = hdev->hal_data->base;
+       u32 val;
+       int ret;
+
+       /* Halt AXI and AXI IMEM VBIF Access */
+       val = venus_readl(hdev, VENUS_VBIF_AXI_HALT_CTRL0);
+       val |= VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ;
+       venus_writel(hdev, VENUS_VBIF_AXI_HALT_CTRL0, val);
+
+       /* Request for AXI bus port halt */
+       ret = readl_poll_timeout(base + VENUS_VBIF_AXI_HALT_CTRL1, val,
+                                val & VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK,
+                                POLL_INTERVAL_US,
+                                VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US);
+       if (ret) {
+               dprintk(VIDC_WARN, "AXI bus port halt timeout\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int venus_power_off(struct venus_hfi_device *hdev)
+{
+       int ret;
+
+       if (!hdev->power_enabled)
+               return 0;
+
+       ret = venus_halt_axi(hdev);
+       if (ret) {
+               dprintk(VIDC_WARN, "Failed to halt AXI\n");
+               return ret;
+       }
+
+       dprintk(VIDC_DBG, "Entering power collapse\n");
+
+       ret = venus_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND);
+       if (ret) {
+               dprintk(VIDC_WARN, "Failed to suspend video core %d\n", ret);
+               return ret;
+       }
+
+       /*
+        * For some regulators, driver might have transfered the control to HW.
+        * So before touching any clocks, driver should get the regulator
+        * control back. Acquire regulators also makes sure that the regulators
+        * are turned ON. So driver can touch the clocks safely.
+        */
+
+       hdev->power_enabled = false;
+
+       dprintk(VIDC_INFO, "Venus power collapsed\n");
+
+       return 0;
+}
+
+static int venus_power_on(struct venus_hfi_device *hdev)
+{
+       int ret;
+
+       if (hdev->power_enabled)
+               return 0;
+
+       dprintk(VIDC_DBG, "Resuming from power collapse\n");
+
+       /* Reboot the firmware */
+       ret = venus_tzbsp_set_video_state(TZBSP_VIDEO_STATE_RESUME);
+       if (ret)
+               goto err_set_video_state;
+
+       ret = venus_run(hdev);
+       if (ret) {
+               dprintk(VIDC_ERR, "Failed to run venus core\n");
+               goto err_run;
+       }
+
+       /*
+        * Set the flag here to skip venus_power_on() which is
+        * being called again via *_alloc_set_imem() if imem is enabled
+        */
+       hdev->power_enabled = true;
+
+       dprintk(VIDC_INFO, "Resumed from power collapse\n");
+
+       return 0;
+
+err_run:
+       venus_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND);
+err_set_video_state:
+       hdev->power_enabled = false;
+       dprintk(VIDC_ERR, "Failed to resume from power collapse\n");
+       return ret;
+}
+
+static int venus_iface_msgq_read_nolock(struct venus_hfi_device *hdev,
+                                       void *pkt)
+{
+       struct iface_queue *queue;
+       u32 tx_req_is_set = 0;
+       int ret;
+
+       if (!venus_is_valid_state(hdev)) {
+               dprintk(VIDC_DBG, "%s: fw not in init state\n", __func__);
+               return -EINVAL;
+       }
+
+       queue = &hdev->queues[IFACEQ_MSG_IDX];
+
+       ret = venus_read_queue(queue, (u8 *)pkt, &tx_req_is_set);
+       if (ret)
+               return ret;
+
+       if (tx_req_is_set)
+               venus_writel(hdev, VIDC_CPU_IC_SOFTINT,
+                            1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT);
+
+       return 0;
+}
+
+static int venus_iface_msgq_read(struct venus_hfi_device *hdev, void *pkt)
+{
+       int ret;
+
+       mutex_lock(&hdev->lock);
+       ret = venus_iface_msgq_read_nolock(hdev, pkt);
+       mutex_unlock(&hdev->lock);
+
+       return ret;
+}
+
+static int venus_iface_dbgq_read_nolock(struct venus_hfi_device *hdev,
+                                       void *pkt)
+{
+       struct iface_queue *queue;
+       u32 tx_req_is_set = 0, value;
+       int ret;
+
+       ret = venus_is_valid_state(hdev);
+       if (!ret) {
+               dprintk(VIDC_DBG, "%s: fw not in init state\n", __func__);
+               return -EINVAL;
+       }
+
+       queue = &hdev->queues[IFACEQ_DBG_IDX];
+
+       ret = venus_read_queue(queue, pkt, &tx_req_is_set);
+       if (ret)
+               return ret;
+
+       if (tx_req_is_set) {
+               value = 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT;
+               venus_writel(hdev, VIDC_CPU_IC_SOFTINT, value);
+       }
+
+       return 0;
+}
+
+static int venus_iface_dbgq_read(struct venus_hfi_device *hdev, void *pkt)
+{
+       int ret;
+
+       if (!pkt)
+               return -EINVAL;
+
+       mutex_lock(&hdev->lock);
+       ret = venus_iface_dbgq_read_nolock(hdev, pkt);
+       mutex_unlock(&hdev->lock);
+
+       return ret;
+}
+
+static void venus_set_qhdr_defaults(struct hfi_queue_header *qhdr)
+{
+       qhdr->status = 1;
+       qhdr->type = IFACEQ_DFLT_QHDR;
+       qhdr->q_size = IFACEQ_QUEUE_SIZE / 4;
+       qhdr->pkt_size = 0;
+       qhdr->rx_wm = 1;
+       qhdr->tx_wm = 1;
+       qhdr->rx_req = 1;
+       qhdr->tx_req = 0;
+       qhdr->rx_irq_status = 0;
+       qhdr->tx_irq_status = 0;
+       qhdr->read_idx = 0;
+       qhdr->write_idx = 0;
+}
+
+static void venus_interface_queues_release(struct venus_hfi_device *hdev)
+{
+       mutex_lock(&hdev->lock);
+
+       venus_free(hdev, hdev->ifaceq_table.smem);
+       venus_free(hdev, hdev->sfr.smem);
+
+       memset(hdev->queues, 0, sizeof(hdev->queues));
+       memset(&hdev->ifaceq_table, 0, sizeof(hdev->ifaceq_table));
+       memset(&hdev->sfr, 0, sizeof(hdev->sfr));
+
+       smem_delete_client(hdev->mem_client);
+
+       hdev->mem_client = NULL;
+
+       mutex_unlock(&hdev->lock);
+}
+
+static int venus_interface_queues_init(struct venus_hfi_device *hdev)
+{
+       struct hfi_queue_table_header *tbl_hdr;
+       struct hfi_queue_header *hdr;
+       struct iface_queue *queue;
+       struct hfi_sfr *sfr;
+       struct mem_desc mem;
+       int offset = 0, ret;
+       u32 i, size;
+
+       size = SHARED_QSIZE - ALIGNED_SFR_SIZE - ALIGNED_QDSS_SIZE;
+
+       ret = venus_alloc(hdev, &mem, size, 1, 0,
+                         HAL_BUFFER_INTERNAL_CMD_QUEUE);
+       if (ret)
+               return ret;
+
+       hdev->ifaceq_table.kva = mem.kva;
+       hdev->ifaceq_table.da = mem.da;
+       hdev->ifaceq_table.size = IFACEQ_TABLE_SIZE;
+       hdev->ifaceq_table.smem = mem.smem;
+       offset += hdev->ifaceq_table.size;
+
+       for (i = 0; i < IFACEQ_NUM; i++) {
+               queue = &hdev->queues[i];
+               queue->qarray.da = mem.da + offset;
+               queue->qarray.kva = mem.kva + offset;
+               queue->qarray.size = IFACEQ_QUEUE_SIZE;
+               queue->qarray.smem = NULL;
+               offset += queue->qarray.size;
+               queue->qhdr =
+                       IFACEQ_GET_QHDR_START_ADDR(hdev->ifaceq_table.kva, i);
+               venus_set_qhdr_defaults(queue->qhdr);
+       }
+
+       ret = venus_alloc(hdev, &mem, ALIGNED_SFR_SIZE, 1, 0,
+                         HAL_BUFFER_INTERNAL_CMD_QUEUE);
+       if (ret) {
+               hdev->sfr.da = 0;
+       } else {
+               hdev->sfr.da = mem.da;
+               hdev->sfr.kva = mem.kva;
+               hdev->sfr.size = ALIGNED_SFR_SIZE;
+               hdev->sfr.smem = mem.smem;
+       }
+
+       tbl_hdr = hdev->ifaceq_table.kva;
+       tbl_hdr->version = 0;
+       tbl_hdr->size = IFACEQ_TABLE_SIZE;
+       tbl_hdr->qhdr0_offset = sizeof(struct hfi_queue_table_header);
+       tbl_hdr->qhdr_size = sizeof(struct hfi_queue_header);
+       tbl_hdr->num_q = IFACEQ_NUM;
+       tbl_hdr->num_active_q = IFACEQ_NUM;
+
+       queue = &hdev->queues[IFACEQ_CMD_IDX];
+       hdr = queue->qhdr;
+       hdr->start_addr = queue->qarray.da;
+       hdr->type |= HFI_Q_ID_HOST_TO_CTRL_CMD_Q;
+
+       queue = &hdev->queues[IFACEQ_MSG_IDX];
+       hdr = queue->qhdr;
+       hdr->start_addr = queue->qarray.da;
+       hdr->type |= HFI_Q_ID_CTRL_TO_HOST_MSG_Q;
+
+       queue = &hdev->queues[IFACEQ_DBG_IDX];
+       hdr = queue->qhdr;
+       hdr->start_addr = queue->qarray.da;
+       hdr->type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
+
+       /*
+        * Set receive request to zero on debug queue as there is no
+        * need of interrupt from video hardware for debug messages
+        */
+       hdr->rx_req = 0;
+
+       sfr = hdev->sfr.kva;
+       sfr->buf_size = ALIGNED_SFR_SIZE;
+
+       return 0;
+}
+
+static int venus_sys_set_debug(struct venus_hfi_device *hdev, u32 debug)
+{
+       struct hfi_sys_set_property_pkt *pkt;
+       u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+       int ret;
+
+       pkt = (struct hfi_sys_set_property_pkt *) &packet;
+
+       ret = call_hfi_pkt_op(hdev, sys_debug_config, pkt, debug);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_sys_set_coverage(struct venus_hfi_device *hdev, u32 mode)
+{
+       struct hfi_sys_set_property_pkt *pkt;
+       u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+       int ret;
+
+       pkt = (struct hfi_sys_set_property_pkt *) packet;
+
+       ret = call_hfi_pkt_op(hdev, sys_coverage_config, pkt, mode);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_sys_set_idle_message(struct venus_hfi_device *hdev,
+                                     bool enable)
+{
+       struct hfi_sys_set_property_pkt *pkt;
+       u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+       int ret;
+
+       if (!enable)
+               return 0;
+
+       pkt = (struct hfi_sys_set_property_pkt *) packet;
+
+       ret = call_hfi_pkt_op(hdev, sys_idle_indicator, pkt, enable);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_sys_set_power_control(struct venus_hfi_device *hdev,
+                                      bool enable)
+{
+       struct hfi_sys_set_property_pkt *pkt;
+       u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+       bool supported = false;
+       int ret;
+
+       if (!supported)
+               return 0;
+
+       pkt = (struct hfi_sys_set_property_pkt *) packet;
+
+       ret = call_hfi_pkt_op(hdev, sys_power_control, pkt, enable);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_get_queue_size(struct venus_hfi_device *hdev,
+                               unsigned int index)
+{
+       struct hfi_queue_header *qhdr;
+
+       if (index >= IFACEQ_NUM) {
+               dprintk(VIDC_ERR, "Invalid index: %d\n", index);
+               return -EINVAL;
+       }
+
+       qhdr = hdev->queues[index].qhdr;
+       if (!qhdr) {
+               dprintk(VIDC_ERR, "queue not present\n");
+               return -EINVAL;
+       }
+
+       return qhdr->read_idx - qhdr->write_idx;
+}
+
+static void venus_set_default_sys_properties(struct venus_hfi_device *hdev)
+{
+       if (venus_sys_set_debug(hdev, vidc_fw_debug))
+               dprintk(VIDC_WARN, "Setting fw_debug msg ON failed\n");
+
+       if (venus_sys_set_idle_message(hdev,
+               hdev->res->sys_idle_indicator || vidc_sys_idle_indicator))
+               dprintk(VIDC_WARN, "Setting idle response ON failed\n");
+
+       if (venus_sys_set_power_control(hdev, vidc_fw_low_power_mode))
+               dprintk(VIDC_WARN, "Setting h/w power collapse ON failed\n");
+}
+
+static int venus_send_session_cmd(void *session, int pkt_type)
+{
+       struct vidc_hal_session_cmd_pkt pkt;
+       struct hal_session *sess = session;
+       struct venus_hfi_device *hdev = sess->device;
+       int ret;
+
+       ret = call_hfi_pkt_op(hdev, session_cmd, &pkt, pkt_type, session);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, &pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_prepare_power_collapse(struct venus_hfi_device *hdev)
+{
+       unsigned long timeout = msecs_to_jiffies(vidc_hw_rsp_timeout);
+       struct hfi_sys_pc_prep_pkt pkt;
+       int ret;
+
+       init_completion(&pc_prep_done);
+
+       ret = call_hfi_pkt_op(hdev, sys_pc_prep, &pkt);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, &pkt);
+       if (ret)
+               return ret;
+
+       ret = wait_for_completion_timeout(&pc_prep_done, timeout);
+       if (!ret) {
+               venus_flush_debug_queue(hdev, NULL);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static void venus_pm_handler(struct work_struct *work)
+{
+       struct venus_hfi_device *hdev;
+       u32 ctrl_status = 0;
+       int ret;
+
+       hdev = list_first_entry(&hal_ctxt.dev_head, struct venus_hfi_device,
+                               list);
+       if (!hdev) {
+               dprintk(VIDC_ERR, "%s: NULL device\n", __func__);
+               return;
+       }
+
+       if (!hdev->power_enabled) {
+               dprintk(VIDC_DBG, "%s: Power already disabled\n", __func__);
+               return;
+       }
+
+       mutex_lock(&hdev->lock);
+       ret = venus_is_valid_state(hdev);
+       mutex_unlock(&hdev->lock);
+
+       if (!ret) {
+               dprintk(VIDC_WARN,
+                       "Core is in bad state, Skipping power collapse\n");
+               return;
+       }
+
+       dprintk(VIDC_DBG, "Prepare for power collapse\n");
+
+       ret = venus_prepare_power_collapse(hdev);
+       if (ret) {
+               dprintk(VIDC_ERR, "Failed to prepare for PC %d\n", ret);
+               goto err_prepare_pc;
+       }
+
+       mutex_lock(&hdev->lock);
+
+       if (hdev->last_packet_type != HFI_CMD_SYS_PC_PREP) {
+               dprintk(VIDC_DBG,
+                       "Last command (%#x) is not PC_PREP cmd\n",
+                       hdev->last_packet_type);
+               goto skip_power_off;
+       }
+
+       if (venus_get_queue_size(hdev, IFACEQ_MSG_IDX) ||
+           venus_get_queue_size(hdev, IFACEQ_CMD_IDX)) {
+               dprintk(VIDC_DBG, "Cmd/msg queues are not empty\n");
+               goto skip_power_off;
+       }
+
+       ctrl_status = venus_readl(hdev, VIDC_CPU_CS_SCIACMDARG0);
+       if (!(ctrl_status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY)) {
+               dprintk(VIDC_DBG,
+                       "Venus is not ready for power collapse (%#x)\n",
+                       ctrl_status);
+               goto skip_power_off;
+       }
+
+       ret = venus_power_off(hdev);
+       if (ret) {
+               dprintk(VIDC_ERR, "Failed venus power off\n");
+               goto err_power_off;
+       }
+
+       /* Cancel pending delayed works if any */
+       cancel_delayed_work(&venus_hfi_pm_work);
+
+       mutex_unlock(&hdev->lock);
+
+       return;
+
+err_power_off:
+skip_power_off:
+
+       /*
+       * When power collapse is escaped, driver no need to inform Venus.
+       * Venus is self-sufficient to come out of the power collapse at
+       * any stage. Driver can skip power collapse and continue with
+       * normal execution.
+       */
+
+       /* Cancel pending delayed works if any */
+       cancel_delayed_work(&venus_hfi_pm_work);
+       dprintk(VIDC_WARN, "Power off skipped (last pkt %#x, status: %#x)\n",
+               hdev->last_packet_type, ctrl_status);
+
+       mutex_unlock(&hdev->lock);
+err_prepare_pc:
+       return;
+}
+
+static void venus_sfr_print(struct venus_hfi_device *hdev)
+{
+       struct hfi_sfr *sfr = hdev->sfr.kva;
+       void *p;
+
+       if (!sfr)
+               return;
+
+       p = memchr(sfr->rg_data, '\0', sfr->buf_size);
+       /*
+        * SFR isn't guaranteed to be NULL terminated since SYS_ERROR indicates
+        * that Venus is in the process of crashing.
+        */
+       if (p == NULL)
+               sfr->rg_data[sfr->buf_size - 1] = '\0';
+
+       dprintk(VIDC_ERR, "SFR Message from FW: %s\n", sfr->rg_data);
+}
+
+static void venus_process_msg_sys_error(struct venus_hfi_device *hdev,
+                                       void *packet)
+{
+       struct hfi_msg_event_notify_pkt *event_pkt = packet;
+
+       if (event_pkt->event_id != HFI_EVENT_SYS_ERROR)
+               return;
+
+       venus_set_state(hdev, VENUS_STATE_DEINIT);
+
+       /*
+        * Once SYS_ERROR received from HW, it is safe to halt the AXI.
+        * With SYS_ERROR, Venus FW may have crashed and HW might be
+        * active and causing unnecessary transactions. Hence it is
+        * safe to stop all AXI transactions from venus subsystem.
+        */
+       venus_halt_axi(hdev);
+       venus_sfr_print(hdev);
+}
+
+static void venus_flush_debug_queue(struct venus_hfi_device *hdev, void *packet)
+{
+       bool local_packet = false;
+
+       if (!hdev)
+               return;
+
+       if (!packet) {
+               packet = kzalloc(VIDC_IFACEQ_VAR_HUGE_PKT_SIZE, GFP_TEMPORARY);
+               if (!packet) {
+                       dprintk(VIDC_ERR, "In %s() Fail to allocate mem\n",
+                               __func__);
+                       return;
+               }
+               local_packet = true;
+       }
+
+       while (!venus_iface_dbgq_read(hdev, packet)) {
+               struct hfi_msg_sys_coverage_pkt *pkt = packet;
+
+               if (pkt->packet_type == HFI_MSG_SYS_COV) {
+#ifdef CONFIG_MSM_VIDC_COV
+                       int stm_size = 0;
+                       dprintk(VIDC_DBG, "DbgQ pkt size: %d\n", pkt->msg_size);
+                       stm_size = stm_log_inv_ts(0, 0, pkt->rg_msg_data,
+                                                 pkt->msg_size);
+                       if (stm_size == 0)
+                               dprintk(VIDC_ERR,
+                                       "In %s, stm_log returned size of 0\n",
+                                       __func__);
+#endif
+               } else {
+                       struct hfi_msg_sys_debug_pkt *pkt = packet;
+                       dprintk(VIDC_FW, "%s", pkt->rg_msg_data);
+               }
+       }
+
+       if (local_packet)
+               kfree(packet);
+}
+
+static void venus_response_handler(struct venus_hfi_device *hdev)
+{
+       void *pkt;
+       u32 ret;
+
+       if (!hdev) {
+               dprintk(VIDC_ERR, "SPURIOUS_INTERRUPT\n");
+               return;
+       }
+
+       pkt = hdev->pkt_buf;
+
+       if (hdev->intr_status & VIDC_WRAPPER_INTR_CLEAR_A2HWD_BMSK) {
+               dprintk(VIDC_ERR, "received: watchdog timeout\n");
+               venus_sfr_print(hdev);
+               disable_irq_nosync(hdev->hal_data->irq);
+               hfi_process_watchdog_timeout(hdev->device_id);
+       }
+
+       while (!venus_iface_msgq_read(hdev, pkt)) {
+               ret = hfi_process_msg_packet(hdev->device_id, pkt,
+                                            &hdev->sessions,
+                                            &hdev->session_lock);
+               switch (ret) {
+               case HFI_MSG_EVENT_NOTIFY:
+                       venus_process_msg_sys_error(hdev, pkt);
+                       break;
+               case HFI_MSG_SYS_RELEASE_RESOURCE:
+                       dprintk(VIDC_DBG, "received: HFI_MSG_SYS_RELEASE_RESOURCE\n");
+                       complete(&release_resources_done);
+                       break;
+               case HFI_MSG_SYS_PC_PREP_DONE:
+                       dprintk(VIDC_DBG, "received: HFI_MSG_SYS_PC_PREP_DONE\n");
+                       complete(&pc_prep_done);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       venus_flush_debug_queue(hdev, pkt);
+}
+
+static irqreturn_t venus_isr_thread(int irq, void *dev)
+{
+       struct venus_hfi_device *hdev = dev;
+       int ret;
+
+       ret = venus_hfi_resume(hdev);
+       if (ret) {
+               dprintk(VIDC_ERR, "%s: Power enable failed\n", __func__);
+               return IRQ_NONE;
+       }
+
+       if (hdev->res->sw_power_collapsible) {
+               dprintk(VIDC_DBG, "Cancel and queue delayed work again.\n");
+               cancel_delayed_work(&venus_hfi_pm_work);
+               if (!queue_delayed_work(hdev->venus_pm_workq,
+                                       &venus_hfi_pm_work,
+                       msecs_to_jiffies(vidc_pwr_collapse_delay))) {
+                       dprintk(VIDC_DBG, "PM work already scheduled\n");
+               }
+       }
+
+       venus_response_handler(hdev);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t venus_isr(int irq, void *dev)
+{
+       struct venus_hfi_device *hdev = dev;
+       u32 status;
+
+       status = venus_readl(hdev, VIDC_WRAPPER_INTR_STATUS);
+
+       if (status & VIDC_WRAPPER_INTR_STATUS_A2H_BMSK ||
+           status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK ||
+           status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK) {
+               hdev->intr_status |= status;
+               hdev->reg_count++;
+       } else {
+               hdev->spur_count++;
+       }
+
+       venus_writel(hdev, VIDC_CPU_CS_A2HSOFTINTCLR, 1);
+       venus_writel(hdev, VIDC_WRAPPER_INTR_CLEAR, status);
+
+       return IRQ_WAKE_THREAD;
+}
+
+static int venus_check_core_registered(struct hal_device_data *core,
+                                      void __iomem *reg_base, int irq)
+{
+       struct venus_hfi_device *hdev;
+       struct list_head *curr, *next;
+
+       if (!core->dev_count)
+               return -EINVAL;
+
+       list_for_each_safe(curr, next, &core->dev_head) {
+               hdev = list_entry(curr, struct venus_hfi_device, list);
+               if (hdev && hdev->hal_data->irq == irq &&
+                   hdev->hal_data->base == reg_base)
+                       return 0;
+       }
+
+       dprintk(VIDC_INFO, "Device not registered\n");
+
+       return -ENODEV;
+}
+
+static int venus_request_interrupt(struct venus_hfi_device *hdev,
+                                  struct vidc_resources *res)
+{
+       struct hal_data *hal;
+       int ret;
+
+       if (res->irq < 0 || !res->base)
+               return -EINVAL;
+
+       ret = venus_check_core_registered(&hal_ctxt, res->base, res->irq);
+       if (!ret) {
+               dprintk(VIDC_ERR, "Core present/Already added\n");
+               return -EEXIST;
+       }
+
+       hal = kzalloc(sizeof(struct hal_data), GFP_KERNEL);
+       if (!hal) {
+               dprintk(VIDC_ERR, "Failed to alloc\n");
+               return -ENOMEM;
+       }
+
+       hdev->hal_data = hal;
+       hal->irq = res->irq;
+       hal->base = res->base;
+
+       ret = request_threaded_irq(res->irq, venus_isr,
+                                  venus_isr_thread,
+                                  IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                  "vidc", hdev);
+       if (ret) {
+               dprintk(VIDC_ERR, "request_irq failed\n");
+               goto err;
+       }
+
+       return 0;
+
+err:
+       kfree(hal);
+       return ret;
+
+}
+
+static int venus_protect_cp_mem(struct venus_hfi_device *hdev)
+{
+       u32 cp_nonpixel_start = 0, cp_nonpixel_size = 0;
+       u32 cp_start = 0, cp_size = 0;
+       struct context_bank_info *cb;
+       int ret;
+
+       if (!hdev)
+               return -EINVAL;
+
+       list_for_each_entry(cb, &hdev->res->context_banks, list) {
+               if (!strcmp(cb->name, "venus_ns")) {
+                       cp_size = cb->addr_range.start;
+                       dprintk(VIDC_DBG, "%s memprot.cp_size: %#x\n",
+                               __func__, cp_size);
+               }
+
+               if (!strcmp(cb->name, "venus_sec_non_pixel")) {
+                       cp_nonpixel_start = cb->addr_range.start;
+                       cp_nonpixel_size = cb->addr_range.size;
+                       dprintk(VIDC_DBG,
+                               "%s memprot.cp_start: %#x size: %#x\n",
+                               __func__, cp_nonpixel_start,
+                               cp_nonpixel_size);
+               }
+       }
+
+       ret = qcom_scm_mem_protect_video_var(cp_start, cp_size,
+                                            cp_nonpixel_start,
+                                            cp_nonpixel_size);
+       if (ret) {
+               dprintk(VIDC_ERR, "Failed to protect memory (%d)\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int venus_hfi_core_init(void *device)
+{
+       struct venus_hfi_device *hdev = device;
+       struct hfi_sys_get_property_pkt version_pkt;
+       struct hfi_sys_init_pkt pkt;
+       struct list_head *ptr, *next;
+       struct hal_session *session = NULL;
+       int ret;
+
+       hdev->intr_status = 0;
+       hdev->power_enabled = true;
+
+       mutex_lock(&hdev->session_lock);
+       list_for_each_safe(ptr, next, &hdev->sessions) {
+               /* This means that session list is not empty. Kick stale
+                * sessions out of our valid instance list, but keep the
+                * list_head inited so that list_del (in the future, called
+                * by session_clean()) will be valid. When client doesn't close
+                * them, then it is a genuine leak which driver can't fix. */
+               session = list_entry(ptr, struct hal_session, list);
+               list_del_init(&session->list);
+       }
+       INIT_LIST_HEAD(&hdev->sessions);
+       mutex_unlock(&hdev->session_lock);
+
+       if (hdev->mem_client) {
+               dprintk(VIDC_ERR, "memory client exists\n");
+               return -EINVAL;
+       }
+
+       hdev->mem_client = smem_new_client(hdev->res);
+       if (IS_ERR(hdev->mem_client))
+               return PTR_ERR(hdev->mem_client);
+
+       ret = venus_interface_queues_init(hdev);
+       if (ret) {
+               dprintk(VIDC_ERR, "failed to init queues\n");
+               return ret;
+       }
+
+       ret = venus_run(hdev);
+       if (ret) {
+               dprintk(VIDC_ERR, "run venus core failed (%d)\n", ret);
+               return ret;
+       }
+
+       ret = call_hfi_pkt_op(hdev, sys_init, &pkt, HFI_VIDEO_ARCH_OX);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, &pkt);
+       if (ret)
+               return ret;
+
+       ret = call_hfi_pkt_op(hdev, sys_image_version, &version_pkt);
+       if (ret || venus_iface_cmdq_write(hdev, &version_pkt))
+               dprintk(VIDC_WARN, "Failed to send image version pkt to fw\n");
+
+       ret = venus_protect_cp_mem(hdev);
+       if (ret)
+               return ret;
+
+       venus_set_state(hdev, VENUS_STATE_INIT);
+
+       return 0;
+}
+
+static int venus_hfi_core_release(void *device)
+{
+       struct venus_hfi_device *hdev = device;
+       int ret;
+
+       if (hdev->mem_client) {
+               ret = venus_hfi_resume(device);
+               if (ret)
+                       return ret;
+
+               hdev->intr_status = 0;
+       }
+
+       venus_set_state(hdev, VENUS_STATE_DEINIT);
+
+       cancel_delayed_work(&venus_hfi_pm_work);
+       flush_workqueue(hdev->venus_pm_workq);
+
+       venus_interface_queues_release(hdev);
+
+       /*
+        * Halt the AXI to make sure there are no pending transactions.
+        * Clocks should be unprepared after making sure axi is halted.
+        */
+       venus_halt_axi(hdev);
+
+       hdev->power_enabled = false;
+
+       return 0;
+}
+
+static int venus_hfi_core_ping(void *device)
+{
+       struct venus_hfi_device *hdev = device;
+       struct hfi_cmd_sys_ping_packet pkt;
+       int ret;
+
+       ret = call_hfi_pkt_op(hdev, sys_ping, &pkt);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, &pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_hfi_core_trigger_ssr(void *device,
+                                     enum hal_ssr_trigger_type type)
+{
+       struct hfi_sys_test_ssr_pkt pkt;
+       struct venus_hfi_device *hdev = device;
+       int ret;
+
+       ret = call_hfi_pkt_op(hdev, ssr_cmd, type, &pkt);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, &pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void *venus_hfi_session_init(void *device, void *session_id,
+                                   enum hal_domain session_type,
+                                   enum hal_video_codec codec_type)
+{
+       struct venus_hfi_device *hdev = device;
+       struct hfi_session_init_pkt pkt;
+       struct hal_session *new_session;
+       int ret;
+
+       new_session = kzalloc(sizeof(*new_session), GFP_KERNEL);
+       if (!new_session)
+               return ERR_PTR(-ENOMEM);
+
+       new_session->session_id = session_id;
+       new_session->is_decoder = session_type == HAL_VIDEO_DOMAIN_DECODER;
+       new_session->device = hdev;
+
+       mutex_lock(&hdev->session_lock);
+       list_add_tail(&new_session->list, &hdev->sessions);
+       mutex_unlock(&hdev->session_lock);
+
+       venus_set_default_sys_properties(device);
+
+       ret = call_hfi_pkt_op(hdev, session_init, &pkt, new_session,
+                             session_type, codec_type);
+       if (ret)
+               goto err_session_init_fail;
+
+       ret = venus_iface_cmdq_write(hdev, &pkt);
+       if (ret)
+               goto err_session_init_fail;
+
+       return new_session;
+
+err_session_init_fail:
+       venus_hfi_session_clean(new_session);
+       return ERR_PTR(ret);
+}
+
+static int venus_hfi_session_end(void *session)
+{
+       struct hal_session *sess = session;
+       struct venus_hfi_device *hdev = sess->device;
+
+       if (vidc_fw_coverage) {
+               if (venus_sys_set_coverage(hdev, vidc_fw_coverage))
+                       dprintk(VIDC_WARN, "Fw_coverage msg ON failed\n");
+       }
+
+       return venus_send_session_cmd(session, HFI_CMD_SYS_SESSION_END);
+}
+
+static int venus_hfi_session_abort(void *session)
+{
+       struct hal_session *sess = session;
+       struct venus_hfi_device *hdev = sess->device;
+
+       venus_flush_debug_queue(hdev, NULL);
+
+       return venus_send_session_cmd(session, HFI_CMD_SYS_SESSION_ABORT);
+}
+
+static int venus_hfi_session_clean(void *session)
+{
+       struct hal_session *sess = session;
+       struct venus_hfi_device *hdev = sess->device;
+
+       venus_flush_debug_queue(hdev, NULL);
+
+       mutex_lock(&hdev->session_lock);
+       list_del(&sess->list);
+       kfree(sess);
+       mutex_unlock(&hdev->session_lock);
+
+       return 0;
+}
+
+static int venus_hfi_session_flush(void *sess, enum hal_flush flush_mode)
+{
+       struct hal_session *session = sess;
+       struct venus_hfi_device *hdev = session->device;
+       struct hfi_cmd_session_flush_packet pkt;
+       int ret;
+
+       ret = call_hfi_pkt_op(hdev, session_flush, &pkt, session, flush_mode);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, &pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_hfi_session_start(void *sess)
+{
+       return venus_send_session_cmd(sess, HFI_CMD_SESSION_START);
+}
+
+static int venus_hfi_session_stop(void *sess)
+{
+       return venus_send_session_cmd(sess, HFI_CMD_SESSION_STOP);
+}
+
+static int venus_hfi_session_etb(void *sess, struct vidc_frame_data *in_frame)
+{
+       struct hal_session *session = sess;
+       struct venus_hfi_device *hdev = session->device;
+       int ret;
+
+       if (session->is_decoder) {
+               struct hfi_cmd_session_empty_buffer_compressed_packet pkt;
+
+               ret = call_hfi_pkt_op(hdev, session_etb_decoder,
+                                     &pkt, session, in_frame);
+               if (ret)
+                       return ret;
+
+               ret = venus_iface_cmdq_write(hdev, &pkt);
+       } else {
+               struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
+                       pkt;
+
+               ret = call_hfi_pkt_op(hdev, session_etb_encoder,
+                                     &pkt, session, in_frame);
+               if (ret)
+                       return ret;
+
+               ret = venus_iface_cmdq_write(hdev, &pkt);
+       }
+
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_hfi_session_ftb(void *sess, struct vidc_frame_data *out_frame)
+{
+       struct hal_session *session = sess;
+       struct venus_hfi_device *hdev = session->device;
+       struct hfi_cmd_session_fill_buffer_packet pkt;
+       int ret;
+
+       ret = call_hfi_pkt_op(hdev, session_ftb, &pkt, session, out_frame);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, &pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int
+venus_hfi_session_set_buffers(void *sess, struct vidc_buffer_addr_info *bai)
+{
+       struct hal_session *session = sess;
+       struct venus_hfi_device *hdev = session->device;
+       struct hfi_session_set_buffers_pkt *pkt;
+       u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
+       int ret;
+
+       if (bai->buffer_type == HAL_BUFFER_INPUT)
+               return 0;
+
+       pkt = (struct hfi_session_set_buffers_pkt *)packet;
+
+       ret = call_hfi_pkt_op(hdev, session_set_buffers, pkt, session, bai);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_hfi_session_release_buffers(void *sess,
+                                            struct vidc_buffer_addr_info *bai)
+{
+       struct hal_session *session = sess;
+       struct venus_hfi_device *hdev = session->device;
+       struct hfi_cmd_session_release_buffer_packet *pkt;
+       u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
+       int ret;
+
+       if (bai->buffer_type == HAL_BUFFER_INPUT)
+               return 0;
+
+       pkt = (struct hfi_cmd_session_release_buffer_packet *) packet;
+
+       ret = call_hfi_pkt_op(hdev, session_release_buffers, pkt, session, bai);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_hfi_session_load_res(void *sess)
+{
+       return venus_send_session_cmd(sess, HFI_CMD_SESSION_LOAD_RESOURCES);
+}
+
+static int venus_hfi_session_release_res(void *sess)
+{
+       return venus_send_session_cmd(sess, HFI_CMD_SESSION_RELEASE_RESOURCES);
+}
+
+static int venus_hfi_session_parse_seq_hdr(void *sess,
+                                          struct vidc_seq_hdr *seq_hdr)
+{
+       struct hal_session *session = sess;
+       struct venus_hfi_device *hdev = session->device;
+       struct hfi_cmd_session_parse_sequence_header_packet *pkt;
+       u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+       int ret;
+
+       pkt = (struct hfi_cmd_session_parse_sequence_header_packet *) packet;
+
+       ret = call_hfi_pkt_op(hdev, session_parse_seq_header,
+                             pkt, session, seq_hdr);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int
+venus_hfi_session_get_seq_hdr(void *sess, struct vidc_seq_hdr *seq_hdr)
+{
+       struct hal_session *session = sess;
+       struct venus_hfi_device *hdev = session->device;
+       struct hfi_session_get_sequence_header_pkt *pkt;
+       u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+       int ret;
+
+       pkt = (struct hfi_session_get_sequence_header_pkt *) packet;
+
+       ret = call_hfi_pkt_op(hdev, session_get_seq_hdr, pkt, session, seq_hdr);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, pkt);
+       if (ret)
+               return ret;;
+
+       return 0;
+}
+
+static int venus_hfi_session_set_property(void *sess, enum hal_property ptype,
+                                         void *pdata)
+{
+       struct hal_session *session = sess;
+       struct venus_hfi_device *hdev = session->device;
+       struct hfi_session_set_property_pkt *pkt;
+       u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
+       int ret;
+
+       pkt = (struct hfi_session_set_property_pkt *) packet;
+
+       ret = call_hfi_pkt_op(hdev, session_set_property, pkt, session, ptype,
+                             pdata);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_hfi_session_get_property(void *sess, enum hal_property ptype)
+{
+       struct hal_session *session = sess;
+       struct venus_hfi_device *hdev = session->device;
+       struct hfi_cmd_session_get_property_packet pkt = {0};
+       int ret;
+
+       ret = call_hfi_pkt_op(hdev, session_get_property, &pkt, session, ptype);
+       if (ret)
+               return ret;
+
+       ret = venus_iface_cmdq_write(hdev, &pkt);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int venus_hfi_get_stride_scanline(int color_fmt, int width, int height,
+                                        int *stride, int *scanlines)
+{
+       if (stride)
+               *stride = VENUS_Y_STRIDE(color_fmt, width);
+       if (scanlines)
+               *scanlines = VENUS_Y_SCANLINES(color_fmt, height);
+
+       return 0;
+}
+
+static 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;
+}
+
+static int venus_hfi_resume(void *dev)
+{
+       struct venus_hfi_device *hdev = dev;
+       int ret;
+
+       mutex_lock(&hdev->lock);
+       ret = venus_power_on(hdev);
+       mutex_unlock(&hdev->lock);
+
+       return ret;
+}
+
+static int venus_hfi_suspend(void *dev)
+{
+       struct venus_hfi_device *hdev = dev;
+       int ret;
+
+       if (hdev->power_enabled) {
+               ret = flush_delayed_work(&venus_hfi_pm_work);
+               dprintk(VIDC_INFO, "%s flush delayed work %d\n", __func__, ret);
+       }
+
+       return 0;
+}
+
+static enum hal_default_properties venus_hfi_get_default_properties(void *dev)
+{
+       enum hal_default_properties prop = 0;
+       struct venus_hfi_device *hdev = dev;
+
+       if (hdev->packetization_type == HFI_PACKETIZATION_3XX)
+               prop = HAL_VIDEO_DYNAMIC_BUF_MODE;
+
+       return prop;
+}
+
+static const struct hfi_ops venus_hfi_ops = {
+       .core_init                      = venus_hfi_core_init,
+       .core_release                   = venus_hfi_core_release,
+       .core_ping                      = venus_hfi_core_ping,
+       .core_trigger_ssr               = venus_hfi_core_trigger_ssr,
+
+       .session_init                   = venus_hfi_session_init,
+       .session_end                    = venus_hfi_session_end,
+       .session_abort                  = venus_hfi_session_abort,
+       .session_clean                  = venus_hfi_session_clean,
+       .session_flush                  = venus_hfi_session_flush,
+       .session_start                  = venus_hfi_session_start,
+       .session_stop                   = venus_hfi_session_stop,
+       .session_etb                    = venus_hfi_session_etb,
+       .session_ftb                    = venus_hfi_session_ftb,
+       .session_set_buffers            = venus_hfi_session_set_buffers,
+       .session_release_buffers        = venus_hfi_session_release_buffers,
+       .session_load_res               = venus_hfi_session_load_res,
+       .session_release_res            = venus_hfi_session_release_res,
+       .session_parse_seq_hdr          = venus_hfi_session_parse_seq_hdr,
+       .session_get_seq_hdr            = venus_hfi_session_get_seq_hdr,
+       .session_set_property           = venus_hfi_session_set_property,
+       .session_get_property           = venus_hfi_session_get_property,
+
+       .get_stride_scanline            = venus_hfi_get_stride_scanline,
+       .get_core_capabilities          = venus_hfi_get_core_capabilities,
+       .resume                         = venus_hfi_resume,
+       .suspend                        = venus_hfi_suspend,
+       .get_default_properties         = venus_hfi_get_default_properties,
+};
+
+void venus_hfi_deinitialize(struct hfi_device *hfidev)
+{
+       struct venus_hfi_device *close, *tmp, *dev;
+
+       dev = hfidev->hfi_device_data;
+
+       list_for_each_entry_safe(close, tmp, &hal_ctxt.dev_head, list) {
+               if (close->hal_data->irq != dev->hal_data->irq)
+                       continue;
+
+               hal_ctxt.dev_count--;
+               list_del(&close->list);
+               destroy_workqueue(close->venus_pm_workq);
+               free_irq(dev->hal_data->irq, close);
+               kfree(close->hal_data);
+               kfree(close);
+               break;
+       }
+
+       kfree(hfidev);
+}
+
+static int venus_hfi_initialize_packetization(struct venus_hfi_device *hdev)
+{
+       const char *hfi_version;
+
+       hfi_version = hdev->res->hfi_version;
+
+       if (!hfi_version) {
+               hdev->packetization_type = HFI_PACKETIZATION_LEGACY;
+       } else if (!strcmp(hfi_version, "3xx")) {
+               hdev->packetization_type = HFI_PACKETIZATION_3XX;
+       } else {
+               dprintk(VIDC_ERR, "Unsupported hfi version\n");
+               return -EINVAL;
+       }
+
+       hdev->pkt_ops = hfi_get_pkt_ops(hdev->packetization_type);
+       if (!hdev->pkt_ops) {
+               dprintk(VIDC_ERR, "Failed to get pkt_ops handle\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void *venus_hfi_add_device(u32 device_id, struct vidc_resources *res)
+{
+       struct venus_hfi_device *hdev;
+       int ret;
+
+       hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
+       if (!hdev)
+               return ERR_PTR(-ENOMEM);
+
+       ret = venus_request_interrupt(hdev, res);
+       if (ret)
+               goto err_kfree;
+
+       hdev->res = res;
+       hdev->device_id = device_id;
+
+       ret = venus_hfi_initialize_packetization(hdev);
+       if (ret) {
+               dprintk(VIDC_ERR, "Failed to initialize packetization\n");
+               goto err_kfree;
+       }
+
+       hdev->venus_pm_workq =
+               create_singlethread_workqueue("pm_workerq_venus");
+       if (!hdev->venus_pm_workq) {
+               dprintk(VIDC_ERR, ": create pm workq failed\n");
+               ret = -ENOMEM;
+               goto err_kfree;
+       }
+
+       mutex_init(&hdev->lock);
+       mutex_init(&hdev->session_lock);
+
+       if (!hal_ctxt.dev_count)
+               INIT_LIST_HEAD(&hal_ctxt.dev_head);
+
+       INIT_LIST_HEAD(&hdev->list);
+       INIT_LIST_HEAD(&hdev->sessions);
+       list_add_tail(&hdev->list, &hal_ctxt.dev_head);
+       hal_ctxt.dev_count++;
+
+       return hdev;
+
+err_kfree:
+       kfree(hdev);
+       return ERR_PTR(ret);
+}
+
+struct hfi_device *
+venus_hfi_initialize(u32 device_id, struct vidc_resources *res)
+{
+       struct hfi_device *hfidev;
+
+       if (!res)
+               return ERR_PTR(-EINVAL);
+
+       hfidev = kzalloc(sizeof(*hfidev), GFP_KERNEL);
+       if (!hfidev)
+               return ERR_PTR(-ENOMEM);
+
+       hfidev->hfi_device_data = venus_hfi_add_device(device_id, res);
+       if (IS_ERR(hfidev->hfi_device_data))
+               return ERR_CAST(hfidev->hfi_device_data);
+
+       hfidev->ops = &venus_hfi_ops;
+
+       return hfidev;
+}
diff --git a/drivers/media/platform/msm/vidc/hfi/venus/venus_hfi.h b/drivers/media/platform/msm/vidc/hfi/venus/venus_hfi.h
new file mode 100644 (file)
index 0000000..6cd6d59
--- /dev/null
@@ -0,0 +1,150 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __H_VENUS_HFI_H__
+#define __H_VENUS_HFI_H__
+
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include "msm_vidc_resources.h"
+
+#include "hfi/vidc_hfi_api.h"
+#include "hfi/vidc_hfi_helper.h"
+#include "hfi/hfi_packetization.h"
+
+#define HFI_MASK_QHDR_TX_TYPE                  0xFF000000
+#define HFI_MASK_QHDR_RX_TYPE                  0x00FF0000
+#define HFI_MASK_QHDR_PRI_TYPE                 0x0000FF00
+#define HFI_MASK_QHDR_Q_ID_TYPE                        0x000000FF
+
+#define HFI_Q_ID_HOST_TO_CTRL_CMD_Q            0x00
+#define HFI_Q_ID_CTRL_TO_HOST_MSG_Q            0x01
+#define HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q          0x02
+#define HFI_MASK_QHDR_STATUS                   0x000000FF
+
+#define VIDC_MAX_UNCOMPRESSED_FMT_PLANES       3
+
+#define IFACEQ_NUM                             3
+#define IFACEQ_CMD_IDX                         0
+#define IFACEQ_MSG_IDX                         1
+#define IFACEQ_DBG_IDX                         2
+#define IFACEQ_MAX_BUF_COUNT                   50
+#define IFACEQ_MAX_PARALLEL_CLNTS              16
+#define IFACEQ_DFLT_QHDR                       0x01010000
+
+struct hfi_queue_table_header {
+       u32 version;
+       u32 size;
+       u32 qhdr0_offset;
+       u32 qhdr_size;
+       u32 num_q;
+       u32 num_active_q;
+};
+
+struct hfi_queue_header {
+       u32 status;
+       u32 start_addr;
+       u32 type;
+       u32 q_size;
+       u32 pkt_size;
+       u32 pkt_drop_cnt;
+       u32 rx_wm;
+       u32 tx_wm;
+       u32 rx_req;
+       u32 tx_req;
+       u32 rx_irq_status;
+       u32 tx_irq_status;
+       u32 read_idx;
+       u32 write_idx;
+};
+
+#define IFACEQ_TABLE_SIZE      \
+       (sizeof(struct hfi_queue_table_header) +        \
+        sizeof(struct hfi_queue_header) * IFACEQ_NUM)
+
+#define IFACEQ_QUEUE_SIZE      (VIDC_IFACEQ_MAX_PKT_SIZE *     \
+       IFACEQ_MAX_BUF_COUNT * IFACEQ_MAX_PARALLEL_CLNTS)
+
+#define IFACEQ_GET_QHDR_START_ADDR(ptr, i)     \
+       (void *)((ptr + sizeof(struct hfi_queue_table_header)) +        \
+               (i * sizeof(struct hfi_queue_header)))
+
+#define QDSS_SIZE              4096
+#define SFR_SIZE               4096
+#define QUEUE_SIZE             (IFACEQ_TABLE_SIZE + \
+                               (IFACEQ_QUEUE_SIZE * IFACEQ_NUM))
+
+#define ALIGNED_QDSS_SIZE      ALIGN(QDSS_SIZE, SZ_4K)
+#define ALIGNED_SFR_SIZE       ALIGN(SFR_SIZE, SZ_4K)
+#define ALIGNED_QUEUE_SIZE     ALIGN(QUEUE_SIZE, SZ_4K)
+#define SHARED_QSIZE           ALIGN(ALIGNED_SFR_SIZE + ALIGNED_QUEUE_SIZE + \
+                                     ALIGNED_QDSS_SIZE, SZ_1M)
+
+struct mem_desc {
+       u32 da;         /* device address */
+       void *kva;      /* kernel virtual address */
+       u32 size;
+       struct smem *smem;
+};
+
+struct iface_queue {
+       void *qhdr;
+       struct mem_desc qarray;
+};
+
+/* Internal data used in vidc_hal not exposed to msm_vidc*/
+struct hal_data {
+       u32 irq;
+       void __iomem *base;
+};
+
+enum venus_state {
+       VENUS_STATE_DEINIT = 1,
+       VENUS_STATE_INIT,
+};
+
+struct venus_hfi_device {
+       struct list_head list;
+       struct list_head sessions;
+       u32 intr_status;
+       u32 device_id;
+       u32 clk_load;
+       u32 codecs_enabled;
+       u32 last_packet_type;
+       bool power_enabled;
+       struct mutex lock;
+       struct mutex session_lock;
+       struct mem_desc ifaceq_table;
+       struct mem_desc sfr;
+       struct iface_queue queues[IFACEQ_NUM];
+       struct smem_client *mem_client;
+       struct hal_data *hal_data;
+       struct workqueue_struct *venus_pm_workq;
+       int spur_count;
+       int reg_count;
+       struct vidc_resources *res;
+       enum venus_state state;
+       const struct hfi_packetization_ops *pkt_ops;
+       enum hfi_packetization_type packetization_type;
+       u8 pkt_buf[VIDC_IFACEQ_VAR_HUGE_PKT_SIZE];
+};
+
+void venus_hfi_deinitialize(struct hfi_device *device);
+
+struct hfi_device *
+venus_hfi_initialize(u32 device_id, struct vidc_resources *res);
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/hfi/venus/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/hfi/venus/vidc_hfi_io.h
new file mode 100644 (file)
index 0000000..337291b
--- /dev/null
@@ -0,0 +1,191 @@
+/* Copyright (c) 2012-2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __VIDC_HFI_IO_H__
+#define __VIDC_HFI_IO_H__
+
+#include <linux/io.h>
+
+#define VENUS_VCODEC_SS_CLOCK_HALT     0x0000000C
+#define VENUS_VPP_CORE_SW_RESET        0x00042004
+#define VENUS_VPP_CTRL_CTRL_RESET      0x00041008
+
+#define VIDC_VBIF_BASE_OFFS                    0x00080000
+#define VIDC_VBIF_VERSION                      (VIDC_VBIF_BASE_OFFS + 0x00)
+#define VIDC_VENUS_VBIF_DDR_OUT_MAX_BURST              \
+                       (VIDC_VBIF_BASE_OFFS + 0xD8)
+#define VIDC_VENUS_VBIF_OCMEM_OUT_MAX_BURST            \
+                       (VIDC_VBIF_BASE_OFFS + 0xDC)
+#define VIDC_VENUS_VBIF_ROUND_ROBIN_QOS_ARB            \
+                       (VIDC_VBIF_BASE_OFFS + 0x124)
+
+#define VIDC_CPU_BASE_OFFS                     0x000C0000
+#define VIDC_CPU_CS_BASE_OFFS          (VIDC_CPU_BASE_OFFS + 0x00012000)
+#define VIDC_CPU_IC_BASE_OFFS          (VIDC_CPU_BASE_OFFS + 0x0001F000)
+
+#define VIDC_CPU_CS_REMAP_OFFS         (VIDC_CPU_CS_BASE_OFFS + 0x00)
+#define VIDC_CPU_CS_TIMER_CONTROL      (VIDC_CPU_CS_BASE_OFFS + 0x04)
+#define VIDC_CPU_CS_A2HSOFTINTEN       (VIDC_CPU_CS_BASE_OFFS + 0x10)
+#define VIDC_CPU_CS_A2HSOFTINTENCLR    (VIDC_CPU_CS_BASE_OFFS + 0x14)
+#define VIDC_CPU_CS_A2HSOFTINT         (VIDC_CPU_CS_BASE_OFFS + 0x18)
+#define VIDC_CPU_CS_A2HSOFTINTCLR      (VIDC_CPU_CS_BASE_OFFS + 0x1C)
+#define VIDC_CPU_CS_SCIACMD                    (VIDC_CPU_CS_BASE_OFFS + 0x48)
+
+/* HFI_CTRL_STATUS */
+#define VIDC_CPU_CS_SCIACMDARG0                (VIDC_CPU_CS_BASE_OFFS + 0x4C)
+#define VIDC_CPU_CS_SCIACMDARG0_BMSK   0xff
+#define VIDC_CPU_CS_SCIACMDARG0_SHFT   0x0
+#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK     0xfe
+#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_SHFT     0x1
+#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_BMSK      0x1
+#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_SHFT      0x0
+#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY           0x100
+#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK     0x40000000
+
+/* HFI_QTBL_INFO */
+#define VIDC_CPU_CS_SCIACMDARG1                (VIDC_CPU_CS_BASE_OFFS + 0x50)
+
+/* HFI_QTBL_ADDR */
+#define VIDC_CPU_CS_SCIACMDARG2                (VIDC_CPU_CS_BASE_OFFS + 0x54)
+
+/* HFI_VERSION_INFO */
+#define VIDC_CPU_CS_SCIACMDARG3                (VIDC_CPU_CS_BASE_OFFS + 0x58)
+#define VIDC_CPU_IC_IRQSTATUS          (VIDC_CPU_IC_BASE_OFFS + 0x00)
+#define VIDC_CPU_IC_FIQSTATUS          (VIDC_CPU_IC_BASE_OFFS + 0x04)
+#define VIDC_CPU_IC_RAWINTR                    (VIDC_CPU_IC_BASE_OFFS + 0x08)
+#define VIDC_CPU_IC_INTSELECT          (VIDC_CPU_IC_BASE_OFFS + 0x0C)
+#define VIDC_CPU_IC_INTENABLE          (VIDC_CPU_IC_BASE_OFFS + 0x10)
+#define VIDC_CPU_IC_INTENACLEAR                (VIDC_CPU_IC_BASE_OFFS + 0x14)
+#define VIDC_CPU_IC_SOFTINT                    (VIDC_CPU_IC_BASE_OFFS + 0x18)
+#define VIDC_CPU_IC_SOFTINT_H2A_BMSK   0x8000
+#define VIDC_CPU_IC_SOFTINT_H2A_SHFT   0xF
+#define VIDC_CPU_IC_SOFTINTCLEAR       (VIDC_CPU_IC_BASE_OFFS + 0x1C)
+
+/*---------------------------------------------------------------------------
+ * MODULE: vidc_wrapper
+ *--------------------------------------------------------------------------*/
+#define VIDC_WRAPPER_BASE_OFFS         0x000E0000
+
+#define VIDC_WRAPPER_HW_VERSION                (VIDC_WRAPPER_BASE_OFFS + 0x00)
+#define VIDC_WRAPPER_HW_VERSION_MAJOR_VERSION_MASK  0x78000000
+#define VIDC_WRAPPER_HW_VERSION_MAJOR_VERSION_SHIFT 28
+#define VIDC_WRAPPER_HW_VERSION_MINOR_VERSION_MASK  0xFFF0000
+#define VIDC_WRAPPER_HW_VERSION_MINOR_VERSION_SHIFT 16
+#define VIDC_WRAPPER_HW_VERSION_STEP_VERSION_MASK   0xFFFF
+
+#define VIDC_WRAPPER_CLOCK_CONFIG      (VIDC_WRAPPER_BASE_OFFS + 0x04)
+
+#define VIDC_WRAPPER_INTR_STATUS       (VIDC_WRAPPER_BASE_OFFS + 0x0C)
+#define VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK    0x10
+#define VIDC_WRAPPER_INTR_STATUS_A2HWD_SHFT    0x4
+#define VIDC_WRAPPER_INTR_STATUS_A2H_BMSK      0x4
+#define VIDC_WRAPPER_INTR_STATUS_A2H_SHFT      0x2
+
+#define VIDC_WRAPPER_INTR_MASK         (VIDC_WRAPPER_BASE_OFFS + 0x10)
+#define VIDC_WRAPPER_INTR_MASK_A2HWD_BMSK      0x10
+#define VIDC_WRAPPER_INTR_MASK_A2HWD_SHFT      0x4
+#define VIDC_WRAPPER_INTR_MASK_A2HVCODEC_BMSK  0x8
+#define VIDC_WRAPPER_INTR_MASK_A2HVCODEC_SHFT  0x3
+#define VIDC_WRAPPER_INTR_MASK_A2HCPU_BMSK     0x4
+#define VIDC_WRAPPER_INTR_MASK_A2HCPU_SHFT     0x2
+
+#define VIDC_WRAPPER_INTR_CLEAR                (VIDC_WRAPPER_BASE_OFFS + 0x14)
+#define VIDC_WRAPPER_INTR_CLEAR_A2HWD_BMSK     0x10
+#define VIDC_WRAPPER_INTR_CLEAR_A2HWD_SHFT     0x4
+#define VIDC_WRAPPER_INTR_CLEAR_A2H_BMSK       0x4
+#define VIDC_WRAPPER_INTR_CLEAR_A2H_SHFT       0x2
+
+#define VIDC_WRAPPER_VBIF_XIN_SW_RESET (VIDC_WRAPPER_BASE_OFFS + 0x18)
+#define VIDC_WRAPPER_VBIF_XIN_STATUS   (VIDC_WRAPPER_BASE_OFFS + 0x1C)
+#define VIDC_WRAPPER_CPU_CLOCK_CONFIG  (VIDC_WRAPPER_BASE_OFFS + 0x2000)
+#define VIDC_WRAPPER_VBIF_XIN_CPU_SW_RESET     \
+                               (VIDC_WRAPPER_BASE_OFFS + 0x2004)
+#define VIDC_WRAPPER_AXI_HALT          (VIDC_WRAPPER_BASE_OFFS + 0x2008)
+#define VIDC_WRAPPER_AXI_HALT_STATUS   (VIDC_WRAPPER_BASE_OFFS + 0x200C)
+#define VIDC_WRAPPER_CPU_CGC_DIS       (VIDC_WRAPPER_BASE_OFFS + 0x2010)
+#define VIDC_VENUS_VBIF_CLK_ON         (VIDC_VBIF_BASE_OFFS + 0x4)
+#define VIDC_VBIF_IN_RD_LIM_CONF0       (VIDC_VBIF_BASE_OFFS + 0xB0)
+#define VIDC_VBIF_IN_RD_LIM_CONF1       (VIDC_VBIF_BASE_OFFS + 0xB4)
+#define VIDC_VBIF_IN_RD_LIM_CONF2       (VIDC_VBIF_BASE_OFFS + 0xB8)
+#define VIDC_VBIF_IN_RD_LIM_CONF3       (VIDC_VBIF_BASE_OFFS + 0xBC)
+#define VIDC_VBIF_IN_WR_LIM_CONF0       (VIDC_VBIF_BASE_OFFS + 0xC0)
+#define VIDC_VBIF_IN_WR_LIM_CONF1       (VIDC_VBIF_BASE_OFFS + 0xC4)
+#define VIDC_VBIF_IN_WR_LIM_CONF2       (VIDC_VBIF_BASE_OFFS + 0xC8)
+#define VIDC_VBIF_IN_WR_LIM_CONF3       (VIDC_VBIF_BASE_OFFS + 0xCC)
+#define VIDC_VBIF_OUT_RD_LIM_CONF0      (VIDC_VBIF_BASE_OFFS + 0xD0)
+#define VIDC_VBIF_OUT_WR_LIM_CONF0      (VIDC_VBIF_BASE_OFFS + 0xD4)
+#define VIDC_VBIF_DDR_OUT_MAX_BURST     (VIDC_VBIF_BASE_OFFS + 0xD8)
+#define VIDC_VBIF_OCMEM_OUT_MAX_BURST   (VIDC_VBIF_BASE_OFFS + 0xDC)
+#define VIDC_VBIF_DDR_ARB_CONF0         (VIDC_VBIF_BASE_OFFS + 0xF4)
+#define VIDC_VBIF_DDR_ARB_CONF1         (VIDC_VBIF_BASE_OFFS + 0xF8)
+#define VIDC_VBIF_ROUND_ROBIN_QOS_ARB   (VIDC_VBIF_BASE_OFFS + 0x124)
+#define VIDC_VBIF_OUT_AXI_AOOO_EN       (VIDC_VBIF_BASE_OFFS + 0x178)
+#define VIDC_VBIF_OUT_AXI_AOOO          (VIDC_VBIF_BASE_OFFS + 0x17C)
+#define VIDC_VBIF_ARB_CTL               (VIDC_VBIF_BASE_OFFS + 0xF0)
+#define VIDC_VBIF_OUT_AXI_AMEMTYPE_CONF0 (VIDC_VBIF_BASE_OFFS + 0x160)
+#define VIDC_VBIF_OUT_AXI_AMEMTYPE_CONF1 (VIDC_VBIF_BASE_OFFS + 0x164)
+#define VIDC_VBIF_ADDR_TRANS_EN         (VIDC_VBIF_BASE_OFFS + 0xC00)
+#define VIDC_VBIF_AT_OLD_BASE           (VIDC_VBIF_BASE_OFFS + 0xC04)
+#define VIDC_VBIF_AT_OLD_HIGH           (VIDC_VBIF_BASE_OFFS + 0xC08)
+#define VIDC_VBIF_AT_NEW_BASE           (VIDC_VBIF_BASE_OFFS + 0xC10)
+#define VIDC_VBIF_AT_NEW_HIGH           (VIDC_VBIF_BASE_OFFS + 0xC18)
+#define VENUS_VBIF_AXI_HALT_CTRL0   (VIDC_VBIF_BASE_OFFS + 0x208)
+#define VENUS_VBIF_AXI_HALT_CTRL1   (VIDC_VBIF_BASE_OFFS + 0x20C)
+
+#define VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ             BIT(0)
+#define VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK             BIT(0)
+#define VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US             500000
+
+#define VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY \
+       (VIDC_WRAPPER_BASE_OFFS + 0x20)
+#define VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL \
+       (VIDC_WRAPPER_BASE_OFFS + 0x24)
+
+#define VIDC_CTRL_INIT 0x000D2048
+#define VIDC_CTRL_INIT_RESERVED_BITS31_1__M 0xFFFFFFFE
+#define VIDC_CTRL_INIT_RESERVED_BITS31_1__S 1
+#define VIDC_CTRL_INIT_CTRL__M 0x00000001
+#define VIDC_CTRL_INIT_CTRL__S 0
+
+#define VIDC_CTRL_STATUS 0x000D204C
+#define VIDC_CTRL_STATUS_RESERVED_BITS31_8__M 0xFFFFFF00
+#define VIDC_CTRL_STATUS_RESERVED_BITS31_8__S 8
+#define VIDC_CTRL_ERROR_STATUS__M             0x000000FE
+#define VIDC_CTRL_ERROR_STATUS__S             1
+#define VIDC_CTRL_INIT_STATUS__M              0x00000001
+#define VIDC_CTRL_INIT_STATUS__S              0
+
+#define VIDC_QTBL_INFO 0x000D2050
+#define VIDC_QTBL_HOSTID__M 0xFF000000
+#define VIDC_QTBL_HOSTID__S 24
+#define VIDC_QTBL_INFO_RESERVED_BITS23_8__M 0x00FFFF00
+#define VIDC_QTBL_INFO_RESERVED_BITS23_8__S 8
+#define VIDC_QTBL_STATUS__M 0x000000FF
+#define VIDC_QTBL_STATUS__S 0
+
+#define VIDC_QTBL_ADDR 0x000D2054
+
+#define VIDC_VERSION_INFO 0x000D2058
+#define VIDC_VERSION_INFO_MAJOR__M  0xF0000000
+#define VIDC_VERSION_INFO_MAJOR__S  28
+#define VIDC_VERSION_INFO_MINOR__M  0x0FFFFFE0
+#define VIDC_VERSION_INFO_MINOR__S  5
+#define VIDC_VERSION_INFO_BRANCH__M 0x0000001F
+#define VIDC_VERSION_INFO_BRANCH__S 0
+
+#define VIDC_SFR_ADDR 0x000D205C
+#define VIDC_MMAP_ADDR 0x000D2060
+#define VIDC_UC_REGION_ADDR 0x000D2064
+#define VIDC_UC_REGION_SIZE 0x000D2068
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/hfi/vidc_hfi.c b/drivers/media/platform/msm/vidc/hfi/vidc_hfi.c
new file mode 100644 (file)
index 0000000..e9806a6
--- /dev/null
@@ -0,0 +1,46 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/slab.h>
+
+#include "msm_vidc_debug.h"
+#include "vidc_hfi_api.h"
+#include "hfi/venus/venus_hfi.h"
+
+void *vidc_hfi_init(enum vidc_hfi_type hfi_type, u32 device_id,
+                   struct vidc_resources *res)
+{
+       struct hfi_device *hdev;
+
+       switch (hfi_type) {
+       case VIDC_HFI_VENUS:
+               hdev = venus_hfi_initialize(device_id, res);
+               break;
+       default:
+               dprintk(VIDC_ERR, "Unsupported host-firmware interface\n");
+               return ERR_PTR(-ENOTSUPP);
+       }
+
+       return hdev;
+}
+
+void vidc_hfi_deinit(enum vidc_hfi_type hfi_type, struct hfi_device *hdev)
+{
+       switch (hfi_type) {
+       case VIDC_HFI_VENUS:
+               venus_hfi_deinitialize(hdev);
+               break;
+       default:
+               dprintk(VIDC_ERR, "Unsupported host-firmware interface\n");
+               return;
+       }
+}
diff --git a/drivers/media/platform/msm/vidc/hfi/vidc_hfi.h b/drivers/media/platform/msm/vidc/hfi/vidc_hfi.h
new file mode 100644 (file)
index 0000000..41e261e
--- /dev/null
@@ -0,0 +1,878 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __H_VIDC_HFI_H__
+#define __H_VIDC_HFI_H__
+
+#include "vidc_hfi_api.h"
+
+#define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES    \
+                                               (HFI_OX_BASE + 0x1)
+#define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUFFER_RESOURCES  \
+                                               (HFI_OX_BASE + 0x2)
+#define HFI_EVENT_SESSION_SEQUENCE_CHANGED     (HFI_OX_BASE + 0x3)
+#define HFI_EVENT_SESSION_PROPERTY_CHANGED     (HFI_OX_BASE + 0x4)
+#define HFI_EVENT_SESSION_LTRUSE_FAILED                (HFI_OX_BASE + 0x5)
+#define HFI_EVENT_RELEASE_BUFFER_REFERENCE     (HFI_OX_BASE + 0x6)
+
+#define HFI_BUFFERFLAG_EOS                             0x00000001
+#define HFI_BUFFERFLAG_STARTTIME                       0x00000002
+#define HFI_BUFFERFLAG_DECODEONLY                      0x00000004
+#define HFI_BUFFERFLAG_DATACORRUPT                     0x00000008
+#define HFI_BUFFERFLAG_ENDOFFRAME                      0x00000010
+#define HFI_BUFFERFLAG_SYNCFRAME                       0x00000020
+#define HFI_BUFFERFLAG_EXTRADATA                       0x00000040
+#define HFI_BUFFERFLAG_CODECCONFIG                     0x00000080
+#define HFI_BUFFERFLAG_TIMESTAMPINVALID                        0x00000100
+#define HFI_BUFFERFLAG_READONLY                                0x00000200
+#define HFI_BUFFERFLAG_ENDOFSUBFRAME                   0x00000400
+#define HFI_BUFFERFLAG_EOSEQ                           0x00200000
+#define HFI_BUFFERFLAG_MBAFF                           0x08000000
+#define HFI_BUFFERFLAG_VPE_YUV_601_709_CSC_CLAMP       0x10000000
+#define HFI_BUFFERFLAG_DROP_FRAME                      0x20000000
+#define HFI_BUFFERFLAG_TEI                             0x40000000
+#define HFI_BUFFERFLAG_DISCONTINUITY                   0x80000000
+
+#define HFI_ERR_SESSION_EMPTY_BUFFER_DONE_OUTPUT_PENDING       \
+                                               (HFI_OX_BASE + 0x1001)
+#define HFI_ERR_SESSION_SAME_STATE_OPERATION   \
+                                               (HFI_OX_BASE + 0x1002)
+#define HFI_ERR_SESSION_SYNC_FRAME_NOT_DETECTED        \
+                                               (HFI_OX_BASE + 0x1003)
+#define  HFI_ERR_SESSION_START_CODE_NOT_FOUND  \
+                                               (HFI_OX_BASE + 0x1004)
+
+#define HFI_BUFFER_INTERNAL_SCRATCH    (HFI_OX_BASE + 0x1)
+#define HFI_BUFFER_EXTRADATA_INPUT     (HFI_OX_BASE + 0x2)
+#define HFI_BUFFER_EXTRADATA_OUTPUT    (HFI_OX_BASE + 0x3)
+#define HFI_BUFFER_EXTRADATA_OUTPUT2   (HFI_OX_BASE + 0x4)
+#define HFI_BUFFER_INTERNAL_SCRATCH_1  (HFI_OX_BASE + 0x5)
+#define HFI_BUFFER_INTERNAL_SCRATCH_2  (HFI_OX_BASE + 0x6)
+
+#define HFI_BUFFER_MODE_STATIC         (HFI_OX_BASE + 0x1)
+#define HFI_BUFFER_MODE_RING           (HFI_OX_BASE + 0x2)
+#define HFI_BUFFER_MODE_DYNAMIC                (HFI_OX_BASE + 0x3)
+
+#define HFI_FLUSH_INPUT                        (HFI_OX_BASE + 0x1)
+#define HFI_FLUSH_OUTPUT               (HFI_OX_BASE + 0x2)
+#define HFI_FLUSH_OUTPUT2              (HFI_OX_BASE + 0x3)
+#define HFI_FLUSH_ALL                  (HFI_OX_BASE + 0x4)
+
+#define HFI_EXTRADATA_NONE                     0x00000000
+#define HFI_EXTRADATA_MB_QUANTIZATION          0x00000001
+#define HFI_EXTRADATA_INTERLACE_VIDEO          0x00000002
+#define HFI_EXTRADATA_VC1_FRAMEDISP            0x00000003
+#define HFI_EXTRADATA_VC1_SEQDISP              0x00000004
+#define HFI_EXTRADATA_TIMESTAMP                        0x00000005
+#define HFI_EXTRADATA_S3D_FRAME_PACKING                0x00000006
+#define HFI_EXTRADATA_FRAME_RATE               0x00000007
+#define HFI_EXTRADATA_PANSCAN_WINDOW           0x00000008
+#define HFI_EXTRADATA_RECOVERY_POINT_SEI       0x00000009
+#define HFI_EXTRADATA_MPEG2_SEQDISP            0x0000000D
+#define HFI_EXTRADATA_STREAM_USERDATA          0x0000000E
+#define HFI_EXTRADATA_FRAME_QP                 0x0000000F
+#define HFI_EXTRADATA_FRAME_BITS_INFO          0x00000010
+#define HFI_EXTRADATA_MULTISLICE_INFO          0x7F100000
+#define HFI_EXTRADATA_NUM_CONCEALED_MB         0x7F100001
+#define HFI_EXTRADATA_INDEX                    0x7F100002
+#define HFI_EXTRADATA_METADATA_LTR             0x7F100004
+#define HFI_EXTRADATA_METADATA_FILLER          0x7FE00002
+
+#define HFI_INDEX_EXTRADATA_INPUT_CROP         0x0700000E
+#define HFI_INDEX_EXTRADATA_DIGITAL_ZOOM       0x07000010
+#define HFI_INDEX_EXTRADATA_ASPECT_RATIO       0x7F100003
+
+struct hfi_buffer_alloc_mode {
+       u32 type;
+       u32 mode;
+};
+
+struct hfi_index_extradata_config {
+       int enable;
+       u32 index_extra_data_id;
+};
+
+struct hfi_extradata_header {
+       u32 size;
+       u32 version;
+       u32 port_index;
+       u32 type;
+       u32 data_size;
+       u8 rg_data[1];
+};
+
+#define HFI_INTERLACE_FRAME_PROGRESSIVE                        0x01
+#define HFI_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST   0x02
+#define HFI_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST        0x04
+#define HFI_INTERLACE_FRAME_TOPFIELDFIRST              0x08
+#define HFI_INTERLACE_FRAME_BOTTOMFIELDFIRST           0x10
+
+#define HFI_PROPERTY_SYS_OX_START      \
+       (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x0000)
+
+#define HFI_PROPERTY_PARAM_OX_START    \
+       (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x1000)
+#define HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL \
+       (HFI_PROPERTY_PARAM_OX_START + 0x001)
+#define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO  \
+       (HFI_PROPERTY_PARAM_OX_START + 0x002)
+#define HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED  \
+       (HFI_PROPERTY_PARAM_OX_START + 0x003)
+#define HFI_PROPERTY_PARAM_CHROMA_SITE \
+       (HFI_PROPERTY_PARAM_OX_START + 0x004)
+#define HFI_PROPERTY_PARAM_EXTRA_DATA_HEADER_CONFIG    \
+       (HFI_PROPERTY_PARAM_OX_START + 0x005)
+#define HFI_PROPERTY_PARAM_INDEX_EXTRADATA     \
+       (HFI_PROPERTY_PARAM_OX_START + 0x006)
+#define HFI_PROPERTY_PARAM_DIVX_FORMAT \
+       (HFI_PROPERTY_PARAM_OX_START + 0x007)
+#define HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE   \
+       (HFI_PROPERTY_PARAM_OX_START + 0x008)
+#define HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA \
+       (HFI_PROPERTY_PARAM_OX_START + 0x009)
+#define HFI_PROPERTY_PARAM_ERR_DETECTION_CODE_EXTRADATA        \
+       (HFI_PROPERTY_PARAM_OX_START + 0x00A)
+#define  HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED        \
+       (HFI_PROPERTY_PARAM_OX_START + 0x00B)
+#define  HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL \
+       (HFI_PROPERTY_PARAM_OX_START + 0x00C)
+#define  HFI_PROPERTY_PARAM_BUFFER_DISPLAY_HOLD_COUNT_ACTUAL   \
+       (HFI_PROPERTY_PARAM_OX_START + 0x00D)
+
+#define HFI_PROPERTY_CONFIG_OX_START                                   \
+       (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x02000)
+#define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS                        \
+       (HFI_PROPERTY_CONFIG_OX_START + 0x001)
+#define HFI_PROPERTY_CONFIG_REALTIME                                   \
+       (HFI_PROPERTY_CONFIG_OX_START + 0x002)
+#define HFI_PROPERTY_CONFIG_PRIORITY                                   \
+       (HFI_PROPERTY_CONFIG_OX_START + 0x003)
+#define HFI_PROPERTY_CONFIG_BATCH_INFO                                 \
+       (HFI_PROPERTY_CONFIG_OX_START + 0x004)
+
+#define HFI_PROPERTY_PARAM_VDEC_OX_START                               \
+       (HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x3000)
+#define HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x001)
+#define HFI_PROPERTY_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT\
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x002)
+#define HFI_PROPERTY_PARAM_VDEC_MULTI_VIEW_SELECT              \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x003)
+#define HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE            \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x004)
+#define HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER                   \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x005)
+#define HFI_PROPERTY_PARAM_VDEC_MB_QUANTIZATION                        \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x006)
+#define HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB               \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x007)
+#define HFI_PROPERTY_PARAM_VDEC_H264_ENTROPY_SWITCHING \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x008)
+#define HFI_PROPERTY_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO\
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x009)
+#define HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA  \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00A)
+#define HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00B)
+#define HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00C)
+#define HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE   \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00D)
+#define HFI_PROPERTY_PARAM_VDEC_FRAME_ASSEMBLY         \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00E)
+#define HFI_PROPERTY_PARAM_VDEC_VC1_FRAMEDISP_EXTRADATA                \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x011)
+#define HFI_PROPERTY_PARAM_VDEC_VC1_SEQDISP_EXTRADATA          \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x012)
+#define HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA                    \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x013)
+#define HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA      \
+       (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_PARAM_VDEC_STREAM_USERDATA_EXTRADATA \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x017)
+#define HFI_PROPERTY_PARAM_VDEC_FRAME_QP_EXTRADATA \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x018)
+#define HFI_PROPERTY_PARAM_VDEC_FRAME_BITS_INFO_EXTRADATA \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x019)
+#define HFI_PROPERTY_PARAM_VDEC_SCS_THRESHOLD \
+       (HFI_PROPERTY_PARAM_VDEC_OX_START + 0x01A)
+
+#define HFI_PROPERTY_CONFIG_VDEC_OX_START                              \
+       (HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x0000)
+#define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER   \
+       (HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x001)
+#define HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP_REPORTING        \
+       (HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x002)
+#define HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP                  \
+       (HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x003)
+
+#define HFI_PROPERTY_PARAM_VENC_OX_START                               \
+       (HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x5000)
+#define  HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_INFO       \
+       (HFI_PROPERTY_PARAM_VENC_OX_START + 0x001)
+#define  HFI_PROPERTY_PARAM_VENC_H264_IDR_S3D_FRAME_PACKING_NAL \
+       (HFI_PROPERTY_PARAM_VENC_OX_START + 0x002)
+#define  HFI_PROPERTY_PARAM_VENC_LTR_INFO                      \
+       (HFI_PROPERTY_PARAM_VENC_OX_START + 0x003)
+#define  HFI_PROPERTY_PARAM_VENC_MBI_DUMPING                           \
+       (HFI_PROPERTY_PARAM_VENC_OX_START + 0x005)
+
+#define HFI_PROPERTY_CONFIG_VENC_OX_START                              \
+       (HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x6000)
+#define  HFI_PROPERTY_CONFIG_VENC_FRAME_QP                             \
+       (HFI_PROPERTY_CONFIG_VENC_OX_START + 0x001)
+
+#define HFI_PROPERTY_PARAM_VPE_OX_START                                        \
+       (HFI_DOMAIN_BASE_VPE + HFI_ARCH_OX_OFFSET + 0x7000)
+#define HFI_PROPERTY_PARAM_VPE_COLOR_SPACE_CONVERSION                  \
+       (HFI_PROPERTY_PARAM_VPE_OX_START + 0x001)
+
+#define HFI_PROPERTY_CONFIG_VPE_OX_START                               \
+       (HFI_DOMAIN_BASE_VPE + HFI_ARCH_OX_OFFSET + 0x8000)
+
+struct hfi_batch_info {
+       u32 input_batch_count;
+       u32 output_batch_count;
+};
+
+struct hfi_buffer_count_actual {
+       u32 type;
+       u32 count_actual;
+};
+
+struct hfi_buffer_size_actual {
+       u32 type;
+       u32 size;
+};
+
+struct hfi_buffer_display_hold_count_actual {
+       u32 type;
+       u32 hold_count;
+};
+
+struct hfi_buffer_requirements {
+       u32 type;
+       u32 size;
+       u32 region_size;
+       u32 hold_count;
+       u32 count_min;
+       u32 count_actual;
+       u32 contiguous;
+       u32 alignment;
+};
+
+#define HFI_CHROMA_SITE_0      (HFI_OX_BASE + 0x1)
+#define HFI_CHROMA_SITE_1      (HFI_OX_BASE + 0x2)
+#define HFI_CHROMA_SITE_2      (HFI_OX_BASE + 0x3)
+#define HFI_CHROMA_SITE_3      (HFI_OX_BASE + 0x4)
+#define HFI_CHROMA_SITE_4      (HFI_OX_BASE + 0x5)
+#define HFI_CHROMA_SITE_5      (HFI_OX_BASE + 0x6)
+
+struct hfi_data_payload {
+       u32 size;
+       u8 rg_data[1];
+};
+
+struct hfi_enable_picture {
+       u32 picture_type;
+};
+
+struct hfi_display_picture_buffer_count {
+       int enable;
+       u32 count;
+};
+
+struct hfi_extra_data_header_config {
+       u32 type;
+       u32 buffer_type;
+       u32 version;
+       u32 port_index;
+       u32 client_extra_data_id;
+};
+
+struct hfi_interlace_format_supported {
+       u32 buffer_type;
+       u32 format;
+};
+
+struct hfi_buffer_alloc_mode_supported {
+       u32 buffer_type;
+       u32 num_entries;
+       u32 rg_data[1];
+};
+
+struct hfi_mb_error_map {
+       u32 error_map_size;
+       u8 rg_error_map[1];
+};
+
+struct hfi_metadata_pass_through {
+       int enable;
+       u32 size;
+};
+
+struct hfi_multi_view_select {
+       u32 view_index;
+};
+
+struct hfi_hybrid_hierp {
+       u32 layers;
+};
+
+#define HFI_PRIORITY_LOW               10
+#define HFI_PRIOIRTY_MEDIUM            20
+#define HFI_PRIORITY_HIGH              30
+
+#define HFI_OUTPUT_ORDER_DISPLAY       (HFI_OX_BASE + 0x1)
+#define HFI_OUTPUT_ORDER_DECODE                (HFI_OX_BASE + 0x2)
+
+#define HFI_RATE_CONTROL_OFF           (HFI_OX_BASE + 0x1)
+#define HFI_RATE_CONTROL_VBR_VFR       (HFI_OX_BASE + 0x2)
+#define HFI_RATE_CONTROL_VBR_CFR       (HFI_OX_BASE + 0x3)
+#define HFI_RATE_CONTROL_CBR_VFR       (HFI_OX_BASE + 0x4)
+#define HFI_RATE_CONTROL_CBR_CFR       (HFI_OX_BASE + 0x5)
+
+struct hfi_uncompressed_plane_actual_constraints_info {
+       u32 buffer_type;
+       u32 num_planes;
+       struct hfi_uncompressed_plane_constraints rg_plane_format[1];
+};
+
+#define HFI_CMD_SYS_OX_START           (HFI_DOMAIN_BASE_COMMON +       \
+                                        HFI_ARCH_OX_OFFSET +           \
+                                        HFI_CMD_START_OFFSET + 0x0000)
+#define HFI_CMD_SYS_SESSION_ABORT      (HFI_CMD_SYS_OX_START + 0x001)
+#define HFI_CMD_SYS_PING               (HFI_CMD_SYS_OX_START + 0x002)
+
+#define HFI_CMD_SESSION_OX_START       (HFI_DOMAIN_BASE_COMMON +       \
+                                        HFI_ARCH_OX_OFFSET +           \
+                                        HFI_CMD_START_OFFSET + 0x1000)
+#define HFI_CMD_SESSION_LOAD_RESOURCES (HFI_CMD_SESSION_OX_START + 0x001)
+#define HFI_CMD_SESSION_START          (HFI_CMD_SESSION_OX_START + 0x002)
+#define HFI_CMD_SESSION_STOP           (HFI_CMD_SESSION_OX_START + 0x003)
+#define HFI_CMD_SESSION_EMPTY_BUFFER   (HFI_CMD_SESSION_OX_START + 0x004)
+#define HFI_CMD_SESSION_FILL_BUFFER    (HFI_CMD_SESSION_OX_START + 0x005)
+#define HFI_CMD_SESSION_SUSPEND                (HFI_CMD_SESSION_OX_START + 0x006)
+#define HFI_CMD_SESSION_RESUME         (HFI_CMD_SESSION_OX_START + 0x007)
+#define HFI_CMD_SESSION_FLUSH          (HFI_CMD_SESSION_OX_START + 0x008)
+#define HFI_CMD_SESSION_GET_PROPERTY   (HFI_CMD_SESSION_OX_START + 0x009)
+#define HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER  \
+                                       (HFI_CMD_SESSION_OX_START + 0x00A)
+#define HFI_CMD_SESSION_RELEASE_BUFFERS                \
+                                       (HFI_CMD_SESSION_OX_START + 0x00B)
+#define HFI_CMD_SESSION_RELEASE_RESOURCES      \
+                                       (HFI_CMD_SESSION_OX_START + 0x00C)
+
+#define HFI_MSG_SYS_OX_START           (HFI_DOMAIN_BASE_COMMON +       \
+                                        HFI_ARCH_OX_OFFSET +           \
+                                        HFI_MSG_START_OFFSET + 0x0000)
+#define HFI_MSG_SYS_PING_ACK           (HFI_MSG_SYS_OX_START + 0x2)
+#define HFI_MSG_SYS_SESSION_ABORT_DONE (HFI_MSG_SYS_OX_START + 0x4)
+
+#define HFI_MSG_SESSION_OX_START               (HFI_DOMAIN_BASE_COMMON + \
+                                                HFI_ARCH_OX_OFFSET + \
+                                                HFI_MSG_START_OFFSET + 0x1000)
+#define HFI_MSG_SESSION_LOAD_RESOURCES_DONE    (HFI_MSG_SESSION_OX_START + 0x1)
+#define HFI_MSG_SESSION_START_DONE             (HFI_MSG_SESSION_OX_START + 0x2)
+#define HFI_MSG_SESSION_STOP_DONE              (HFI_MSG_SESSION_OX_START + 0x3)
+#define HFI_MSG_SESSION_SUSPEND_DONE           (HFI_MSG_SESSION_OX_START + 0x4)
+#define HFI_MSG_SESSION_RESUME_DONE            (HFI_MSG_SESSION_OX_START + 0x5)
+#define HFI_MSG_SESSION_FLUSH_DONE             (HFI_MSG_SESSION_OX_START + 0x6)
+#define HFI_MSG_SESSION_EMPTY_BUFFER_DONE      (HFI_MSG_SESSION_OX_START + 0x7)
+#define HFI_MSG_SESSION_FILL_BUFFER_DONE       (HFI_MSG_SESSION_OX_START + 0x8)
+#define HFI_MSG_SESSION_PROPERTY_INFO          (HFI_MSG_SESSION_OX_START + 0x9)
+#define HFI_MSG_SESSION_RELEASE_RESOURCES_DONE (HFI_MSG_SESSION_OX_START + 0xA)
+#define HFI_MSG_SESSION_PARSE_SEQUENCE_HEADER_DONE             \
+                                               (HFI_MSG_SESSION_OX_START + 0xB)
+#define HFI_MSG_SESSION_RELEASE_BUFFERS_DONE                   \
+                                               (HFI_MSG_SESSION_OX_START + 0xC)
+
+#define VIDC_IFACEQ_MAX_PKT_SIZE       1024
+#define VIDC_IFACEQ_MED_PKT_SIZE       768
+#define VIDC_IFACEQ_MIN_PKT_SIZE       8
+#define VIDC_IFACEQ_VAR_SMALL_PKT_SIZE 100
+#define VIDC_IFACEQ_VAR_LARGE_PKT_SIZE 512
+#define VIDC_IFACEQ_VAR_HUGE_PKT_SIZE  (1024 * 12)
+
+struct hfi_cmd_sys_session_abort_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+};
+
+struct hfi_cmd_sys_ping_packet {
+       u32 size;
+       u32 packet_type;
+       u32 client_data;
+};
+
+struct hfi_cmd_session_load_resources_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+};
+
+struct hfi_cmd_session_start_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+};
+
+struct hfi_cmd_session_stop_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+};
+
+struct hfi_cmd_session_empty_buffer_compressed_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 time_stamp_hi;
+       u32 time_stamp_lo;
+       u32 flags;
+       u32 mark_target;
+       u32 mark_data;
+       u32 offset;
+       u32 alloc_len;
+       u32 filled_len;
+       u32 input_tag;
+       u32 packet_buffer;
+       u32 extra_data_buffer;
+       u32 rgData[1];
+};
+
+struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 view_id;
+       u32 time_stamp_hi;
+       u32 time_stamp_lo;
+       u32 flags;
+       u32 mark_target;
+       u32 mark_data;
+       u32 alloc_len;
+       u32 filled_len;
+       u32 offset;
+       u32 input_tag;
+       u32 packet_buffer;
+       u32 extra_data_buffer;
+       u32 rgData[1];
+};
+
+struct hfi_cmd_session_empty_buffer_uncompressed_plane1_packet {
+       u32 flags;
+       u32 alloc_len;
+       u32 filled_len;
+       u32 offset;
+       u32 packet_buffer2;
+       u32 rgData[1];
+};
+
+struct hfi_cmd_session_empty_buffer_uncompressed_plane2_packet {
+       u32 flags;
+       u32 alloc_len;
+       u32 filled_len;
+       u32 offset;
+       u32 packet_buffer3;
+       u32 rgData[1];
+};
+
+struct hfi_cmd_session_fill_buffer_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 stream_id;
+       u32 offset;
+       u32 alloc_len;
+       u32 filled_len;
+       u32 output_tag;
+       u32 packet_buffer;
+       u32 extra_data_buffer;
+       u32 rgData[1];
+};
+
+struct hfi_cmd_session_flush_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 flush_type;
+};
+
+struct hfi_cmd_session_suspend_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+};
+
+struct hfi_cmd_session_resume_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+};
+
+struct hfi_cmd_session_get_property_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 num_properties;
+       u32 rg_property_data[1];
+};
+
+struct hfi_cmd_session_release_buffer_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 buffer_type;
+       u32 buffer_size;
+       u32 extra_data_size;
+       int response_req;
+       u32 num_buffers;
+       u32 rg_buffer_info[1];
+};
+
+struct hfi_cmd_session_release_resources_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+};
+
+struct hfi_cmd_session_parse_sequence_header_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 header_len;
+       u32 packet_buffer;
+};
+
+struct hfi_msg_sys_session_abort_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+};
+
+struct hfi_msg_sys_idle_packet {
+       u32 size;
+       u32 packet_type;
+};
+
+struct hfi_msg_sys_ping_ack_packet {
+       u32 size;
+       u32 packet_type;
+       u32 client_data;
+};
+
+struct hfi_msg_sys_property_info_packet {
+       u32 size;
+       u32 packet_type;
+       u32 num_properties;
+       u32 rg_property_data[1];
+};
+
+struct hfi_msg_session_load_resources_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+};
+
+struct hfi_msg_session_start_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+};
+
+struct hfi_msg_session_stop_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+};
+
+struct hfi_msg_session_suspend_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+};
+
+struct hfi_msg_session_resume_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+};
+
+struct hfi_msg_session_flush_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+       u32 flush_type;
+};
+
+struct hfi_msg_session_empty_buffer_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+       u32 offset;
+       u32 filled_len;
+       u32 input_tag;
+       u32 packet_buffer;
+       u32 extra_data_buffer;
+       u32 rgData[0];
+};
+
+struct hfi_msg_session_fbd_compressed_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 time_stamp_hi;
+       u32 time_stamp_lo;
+       u32 error_type;
+       u32 flags;
+       u32 mark_target;
+       u32 mark_data;
+       u32 stats;
+       u32 offset;
+       u32 alloc_len;
+       u32 filled_len;
+       u32 input_tag;
+       u32 output_tag;
+       u32 picture_type;
+       u32 packet_buffer;
+       u32 extra_data_buffer;
+       u32 rgData[0];
+};
+
+struct hfi_msg_session_fbd_uncompressed_plane0_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 stream_id;
+       u32 view_id;
+       u32 error_type;
+       u32 time_stamp_hi;
+       u32 time_stamp_lo;
+       u32 flags;
+       u32 mark_target;
+       u32 mark_data;
+       u32 stats;
+       u32 alloc_len;
+       u32 filled_len;
+       u32 offset;
+       u32 frame_width;
+       u32 frame_height;
+       u32 start_x_coord;
+       u32 start_y_coord;
+       u32 input_tag;
+       u32 input_tag2;
+       u32 output_tag;
+       u32 picture_type;
+       u32 packet_buffer;
+       u32 extra_data_buffer;
+       u32 rgData[0];
+};
+
+struct hfi_msg_session_fbd_uncompressed_plane1_packet {
+       u32 flags;
+       u32 alloc_len;
+       u32 filled_len;
+       u32 offset;
+       u32 packet_buffer2;
+       u32 rgData[0];
+};
+
+struct hfi_msg_session_fbd_uncompressed_plane2_packet {
+       u32 flags;
+       u32 alloc_len;
+       u32 filled_len;
+       u32 offset;
+       u32 packet_buffer3;
+       u32 rgData[0];
+};
+
+struct hfi_msg_session_parse_sequence_header_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+       u32 num_properties;
+       u32 rg_property_data[1];
+};
+
+struct hfi_msg_session_property_info_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 num_properties;
+       u32 rg_property_data[1];
+};
+
+struct hfi_msg_session_release_resources_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+};
+
+struct hfi_msg_session_release_buffers_done_packet {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+       u32 num_buffers;
+       u32 rg_buffer_info[1];
+};
+
+struct hfi_extradata_mb_quantization_payload {
+       u8 rg_mb_qp[1];
+};
+
+struct hfi_extradata_vc1_pswnd {
+       u32 ps_wnd_h_offset;
+       u32 ps_wnd_v_offset;
+       u32 ps_wnd_width;
+       u32 ps_wnd_height;
+};
+
+struct hfi_extradata_vc1_framedisp_payload {
+       u32 res_pic;
+       u32 ref;
+       u32 range_map_present;
+       u32 range_map_y;
+       u32 range_map_uv;
+       u32 num_pan_scan_wnds;
+       struct hfi_extradata_vc1_pswnd rg_ps_wnd[1];
+};
+
+struct hfi_extradata_vc1_seqdisp_payload {
+       u32 prog_seg_frm;
+       u32 uv_sampling_fmt;
+       u32 color_fmt_flag;
+       u32 color_primaries;
+       u32 transfer_char;
+       u32 mat_coeff;
+       u32 aspect_ratio;
+       u32 aspect_horiz;
+       u32 aspect_vert;
+};
+
+struct hfi_extradata_timestamp_payload {
+       u32 timestamp_low;
+       u32 timestamp_high;
+};
+
+struct hfi_extradata_s3d_frame_packing_payload {
+       u32 fpa_id;
+       int cancel_flag;
+       u32 fpa_type;
+       int quin_cunx_flag;
+       u32 content_interprtation_type;
+       int spatial_flipping_flag;
+       int frame0_flipped_flag;
+       int field_views_flag;
+       int current_frame_isFrame0_flag;
+       int frame0_self_contained_flag;
+       int frame1_self_contained_flag;
+       u32 frame0_graid_pos_x;
+       u32 frame0_graid_pos_y;
+       u32 frame1_graid_pos_x;
+       u32 frame1_graid_pos_y;
+       u32 fpa_reserved_byte;
+       u32 fpa_repetition_period;
+       int fpa_extension_flag;
+};
+
+struct hfi_extradata_interlace_video_payload {
+       u32 format;
+};
+
+struct hfi_extradata_num_concealed_mb_payload {
+       u32 num_mb_concealed;
+};
+
+struct hfi_extradata_sliceinfo {
+       u32 offset_in_stream;
+       u32 slice_length;
+};
+
+struct hfi_extradata_multislice_info_payload {
+       u32 num_slices;
+       struct hfi_extradata_sliceinfo rg_slice_info[1];
+};
+
+struct hfi_index_extradata_input_crop_payload {
+       u32 size;
+       u32 version;
+       u32 port_index;
+       u32 left;
+       u32 top;
+       u32 width;
+       u32 height;
+};
+
+struct hfi_index_extradata_digital_zoom_payload {
+       u32 size;
+       u32 version;
+       u32 port_index;
+       int width;
+       int height;
+};
+
+struct hfi_index_extradata_aspect_ratio_payload {
+       u32 size;
+       u32 version;
+       u32 port_index;
+       u32 aspect_width;
+       u32 aspect_height;
+};
+
+struct hfi_extradata_panscan_wndw_payload {
+       u32 num_window;
+       struct hfi_extradata_vc1_pswnd wnd[1];
+};
+
+struct hfi_extradata_frame_type_payload {
+       u32 frame_rate;
+};
+
+struct hfi_extradata_recovery_point_sei_payload {
+       u32 flag;
+};
+
+struct hal_session {
+       struct list_head list;
+       void *session_id;
+       bool is_decoder;
+       void *device;
+};
+
+struct hal_device_data {
+       struct list_head dev_head;
+       int dev_count;
+};
+
+void hfi_process_watchdog_timeout(u32 device_id);
+
+u32 hfi_process_msg_packet(u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
+                          struct list_head *sessions,
+                          struct mutex *session_lock);
+#endif
diff --git a/drivers/media/platform/msm/vidc/hfi/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/hfi/vidc_hfi_api.h
new file mode 100644 (file)
index 0000000..6559b1e
--- /dev/null
@@ -0,0 +1,1363 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __VIDC_HFI_API_H__
+#define __VIDC_HFI_API_H__
+
+#include <linux/types.h>
+
+#include "msm_vidc.h"
+#include "msm_vidc_resources.h"
+
+#include "vidc_hfi_helper.h"
+#include "vidc_hfi.h"
+
+#define HAL_BUFFERFLAG_EOS                     0x00000001
+#define HAL_BUFFERFLAG_STARTTIME               0x00000002
+#define HAL_BUFFERFLAG_DECODEONLY              0x00000004
+#define HAL_BUFFERFLAG_DATACORRUPT             0x00000008
+#define HAL_BUFFERFLAG_ENDOFFRAME              0x00000010
+#define HAL_BUFFERFLAG_SYNCFRAME               0x00000020
+#define HAL_BUFFERFLAG_EXTRADATA               0x00000040
+#define HAL_BUFFERFLAG_CODECCONFIG             0x00000080
+#define HAL_BUFFERFLAG_TIMESTAMPINVALID                0x00000100
+#define HAL_BUFFERFLAG_READONLY                        0x00000200
+#define HAL_BUFFERFLAG_ENDOFSUBFRAME           0x00000400
+#define HAL_BUFFERFLAG_EOSEQ                   0x00200000
+#define HAL_BUFFERFLAG_MBAFF                   0x08000000
+#define HAL_BUFFERFLAG_YUV_601_709_CSC_CLAMP   0x10000000
+#define HAL_BUFFERFLAG_DROP_FRAME              0x20000000
+#define HAL_BUFFERFLAG_TS_DISCONTINUITY                0x40000000
+#define HAL_BUFFERFLAG_TS_ERROR                        0x80000000
+
+#define HAL_DEBUG_MSG_LOW                      0x00000001
+#define HAL_DEBUG_MSG_MEDIUM                   0x00000002
+#define HAL_DEBUG_MSG_HIGH                     0x00000004
+#define HAL_DEBUG_MSG_ERROR                    0x00000008
+#define HAL_DEBUG_MSG_FATAL                    0x00000010
+#define MAX_PROFILE_COUNT                      16
+
+#define HAL_MAX_MATRIX_COEFFS                  9
+#define HAL_MAX_BIAS_COEFFS                    3
+#define HAL_MAX_LIMIT_COEFFS                   6
+
+enum vidc_error {
+       VIDC_ERR_NONE = 0x0,
+       VIDC_ERR_FAIL = 0x80000000,
+       VIDC_ERR_ALLOC_FAIL,
+       VIDC_ERR_ILLEGAL_OP,
+       VIDC_ERR_BAD_PARAM,
+       VIDC_ERR_BAD_HANDLE,
+       VIDC_ERR_NOT_SUPPORTED,
+       VIDC_ERR_BAD_STATE,
+       VIDC_ERR_MAX_CLIENTS,
+       VIDC_ERR_IFRAME_EXPECTED,
+       VIDC_ERR_HW_FATAL,
+       VIDC_ERR_BITSTREAM_ERR,
+       VIDC_ERR_INDEX_NOMORE,
+       VIDC_ERR_SEQHDR_PARSE_FAIL,
+       VIDC_ERR_INSUFFICIENT_BUFFER,
+       VIDC_ERR_BAD_POWER_STATE,
+       VIDC_ERR_NO_VALID_SESSION,
+       VIDC_ERR_TIMEOUT,
+       VIDC_ERR_CMDQFULL,
+       VIDC_ERR_START_CODE_NOT_FOUND,
+       VIDC_ERR_CLIENT_PRESENT = 0x90000001,
+       VIDC_ERR_CLIENT_FATAL,
+       VIDC_ERR_CMD_QUEUE_FULL,
+       VIDC_ERR_UNUSED = 0x10000000
+};
+
+#define HAL_BUFFER_MAX         0xb
+
+/* NOTE: if you change this enum you MUST update the
+ * "buffer-type-tz-usage-table" for any affected target
+ * in arch/arm/boot/dts/<arch>.dtsi
+ */
+enum hal_buffer {
+       HAL_BUFFER_NONE                 = 0x0,
+       HAL_BUFFER_INPUT                = 0x1,
+       HAL_BUFFER_OUTPUT               = 0x2,
+       HAL_BUFFER_OUTPUT2              = 0x4,
+       HAL_BUFFER_EXTRADATA_INPUT      = 0x8,
+       HAL_BUFFER_EXTRADATA_OUTPUT     = 0x10,
+       HAL_BUFFER_EXTRADATA_OUTPUT2    = 0x20,
+       HAL_BUFFER_INTERNAL_SCRATCH     = 0x40,
+       HAL_BUFFER_INTERNAL_SCRATCH_1   = 0x80,
+       HAL_BUFFER_INTERNAL_SCRATCH_2   = 0x100,
+       HAL_BUFFER_INTERNAL_PERSIST     = 0x200,
+       HAL_BUFFER_INTERNAL_PERSIST_1   = 0x400,
+       HAL_BUFFER_INTERNAL_CMD_QUEUE   = 0x800,
+};
+
+enum hal_extradata_id {
+       HAL_EXTRADATA_NONE,
+       HAL_EXTRADATA_MB_QUANTIZATION,
+       HAL_EXTRADATA_INTERLACE_VIDEO,
+       HAL_EXTRADATA_VC1_FRAMEDISP,
+       HAL_EXTRADATA_VC1_SEQDISP,
+       HAL_EXTRADATA_TIMESTAMP,
+       HAL_EXTRADATA_S3D_FRAME_PACKING,
+       HAL_EXTRADATA_FRAME_RATE,
+       HAL_EXTRADATA_PANSCAN_WINDOW,
+       HAL_EXTRADATA_RECOVERY_POINT_SEI,
+       HAL_EXTRADATA_MULTISLICE_INFO,
+       HAL_EXTRADATA_INDEX,
+       HAL_EXTRADATA_NUM_CONCEALED_MB,
+       HAL_EXTRADATA_METADATA_FILLER,
+       HAL_EXTRADATA_ASPECT_RATIO,
+       HAL_EXTRADATA_MPEG2_SEQDISP,
+       HAL_EXTRADATA_STREAM_USERDATA,
+       HAL_EXTRADATA_FRAME_QP,
+       HAL_EXTRADATA_FRAME_BITS_INFO,
+       HAL_EXTRADATA_INPUT_CROP,
+       HAL_EXTRADATA_DIGITAL_ZOOM,
+       HAL_EXTRADATA_LTR_INFO,
+       HAL_EXTRADATA_METADATA_MBI,
+};
+
+enum hal_property {
+       HAL_CONFIG_FRAME_RATE = 0x04000001,
+       HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT,                   //2
+       HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO,   //3
+       HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO,               //4
+       HAL_PARAM_EXTRA_DATA_HEADER_CONFIG,                     //5
+       HAL_PARAM_INDEX_EXTRADATA,                              //6
+       HAL_PARAM_FRAME_SIZE,                                   //7
+       HAL_CONFIG_REALTIME,                                    //8
+       HAL_PARAM_BUFFER_COUNT_ACTUAL,                          //9
+       HAL_PARAM_BUFFER_SIZE_ACTUAL,                           //a
+       HAL_PARAM_BUFFER_DISPLAY_HOLD_COUNT_ACTUAL,             //b
+       HAL_PARAM_NAL_STREAM_FORMAT_SELECT,                     //c
+       HAL_PARAM_VDEC_OUTPUT_ORDER,                            //d
+       HAL_PARAM_VDEC_PICTURE_TYPE_DECODE,                     //e
+       HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO,               //f
+       HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER,                    //10
+       HAL_PARAM_VDEC_MULTI_STREAM,                            //11
+       HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT,            //12
+       HAL_PARAM_DIVX_FORMAT,                                  //13
+       HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING,                 //14
+       HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER,                  //15
+       HAL_CONFIG_VDEC_MB_ERROR_MAP,                           //16
+       HAL_CONFIG_VENC_REQUEST_IFRAME,                         //17
+       HAL_PARAM_VENC_MPEG4_SHORT_HEADER,                      //18
+       HAL_PARAM_VENC_MPEG4_AC_PREDICTION,                     //19
+       HAL_CONFIG_VENC_TARGET_BITRATE,                         //1a
+       HAL_PARAM_PROFILE_LEVEL_CURRENT,                        //1b
+       HAL_PARAM_VENC_H264_ENTROPY_CONTROL,                    //1c
+       HAL_PARAM_VENC_RATE_CONTROL,                            //1d
+       HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION,                   //1e
+       HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION,                  //1f
+       HAL_PARAM_VENC_H264_DEBLOCK_CONTROL,                    //20
+       HAL_PARAM_VENC_TEMPORAL_SPATIAL_TRADEOFF,               //21
+       HAL_PARAM_VENC_SESSION_QP,                              //22
+       HAL_PARAM_VENC_SESSION_QP_RANGE,                        //23
+       HAL_CONFIG_VENC_INTRA_PERIOD,                           //24
+       HAL_CONFIG_VENC_IDR_PERIOD,                             //25
+       HAL_CONFIG_VPE_OPERATIONS,                              //26
+       HAL_PARAM_VENC_INTRA_REFRESH,                           //27
+       HAL_PARAM_VENC_MULTI_SLICE_CONTROL,                     //28
+       HAL_CONFIG_VPE_DEINTERLACE,                             //29
+       HAL_SYS_DEBUG_CONFIG,                                   //2a
+       HAL_CONFIG_BUFFER_REQUIREMENTS,                         //2b
+       HAL_CONFIG_PRIORITY,                                    //2c
+       HAL_CONFIG_BATCH_INFO,                                  //2d
+       HAL_PARAM_METADATA_PASS_THROUGH,                        //2e
+       HAL_SYS_IDLE_INDICATOR,                                 //2f
+       HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED,                //30
+       HAL_PARAM_INTERLACE_FORMAT_SUPPORTED,                   //31
+       HAL_PARAM_CHROMA_SITE,                                  //32
+       HAL_PARAM_PROPERTIES_SUPPORTED,                         //33
+       HAL_PARAM_PROFILE_LEVEL_SUPPORTED,                      //34
+       HAL_PARAM_CAPABILITY_SUPPORTED,                         //35
+       HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED,                  //36
+       HAL_PARAM_MULTI_VIEW_FORMAT,                            //37
+       HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE,                     //38
+       HAL_PARAM_CODEC_SUPPORTED,                              //39
+       HAL_PARAM_VDEC_MULTI_VIEW_SELECT,                       //3a
+       HAL_PARAM_VDEC_MB_QUANTIZATION,                         //3b
+       HAL_PARAM_VDEC_NUM_CONCEALED_MB,                        //3c
+       HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING,                  //3d
+       HAL_PARAM_VENC_SLICE_DELIVERY_MODE,                     //3e
+       HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING,                 //3f
+       HAL_CONFIG_BUFFER_COUNT_ACTUAL,                         //40
+       HAL_CONFIG_VDEC_MULTI_STREAM,                           //41
+       HAL_PARAM_VENC_MULTI_SLICE_INFO,                        //42
+       HAL_CONFIG_VENC_TIMESTAMP_SCALE,                        //43
+       HAL_PARAM_VENC_LOW_LATENCY,                             //44
+       HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER,              //45
+       HAL_PARAM_VDEC_SYNC_FRAME_DECODE,                       //46
+       HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL,                //47
+       HAL_CONFIG_VENC_MAX_BITRATE,                            //48
+       HAL_PARAM_VENC_H264_VUI_TIMING_INFO,                    //49
+       HAL_PARAM_VENC_H264_GENERATE_AUDNAL,                    //4a
+       HAL_PARAM_VENC_MAX_NUM_B_FRAMES,                        //4b
+       HAL_PARAM_BUFFER_ALLOC_MODE,                            //4c
+       HAL_PARAM_VDEC_FRAME_ASSEMBLY,                          //4d
+       HAL_PARAM_VENC_H264_VUI_BITSTREAM_RESTRC,               //4e
+       HAL_PARAM_VENC_PRESERVE_TEXT_QUALITY,                   //4f
+       HAL_PARAM_VDEC_CONCEAL_COLOR,                           //50
+       HAL_PARAM_VDEC_SCS_THRESHOLD,                           //51
+       HAL_PARAM_GET_BUFFER_REQUIREMENTS,                      //52
+       HAL_PARAM_MVC_BUFFER_LAYOUT,                            //53
+       HAL_PARAM_VENC_LTRMODE,                                 //54
+       HAL_CONFIG_VENC_MARKLTRFRAME,                           //55
+       HAL_CONFIG_VENC_USELTRFRAME,                            //56
+       HAL_CONFIG_VENC_LTRPERIOD,                              //57
+       HAL_CONFIG_VENC_HIER_P_NUM_FRAMES,                      //58
+       HAL_PARAM_VENC_HIER_P_MAX_ENH_LAYERS,                   //59
+       HAL_PARAM_VENC_DISABLE_RC_TIMESTAMP,                    //5a
+       HAL_PARAM_VENC_ENABLE_INITIAL_QP,                       //5b
+       HAL_PARAM_VENC_SEARCH_RANGE,                            //5c
+       HAL_PARAM_VPE_COLOR_SPACE_CONVERSION,                   //5d
+       HAL_PARAM_VENC_VPX_ERROR_RESILIENCE_MODE,               //5e
+       HAL_PARAM_VENC_H264_NAL_SVC_EXT,                        //5f
+       HAL_CONFIG_VENC_PERF_MODE,                              //60
+       HAL_PARAM_VENC_HIER_B_MAX_ENH_LAYERS,                   //61
+       HAL_PARAM_VDEC_NON_SECURE_OUTPUT2,                      //62
+       HAL_PARAM_VENC_HIER_P_HYBRID_MODE,                      //63
+};
+
+enum hal_domain {
+       HAL_VIDEO_DOMAIN_VPE,
+       HAL_VIDEO_DOMAIN_ENCODER,
+       HAL_VIDEO_DOMAIN_DECODER,
+       HAL_UNUSED_DOMAIN = 0x10000000,
+};
+
+enum multi_stream {
+       HAL_VIDEO_DECODER_NONE          = 0x00000000,
+       HAL_VIDEO_DECODER_PRIMARY       = 0x00000001,
+       HAL_VIDEO_DECODER_SECONDARY     = 0x00000002,
+       HAL_VIDEO_DECODER_BOTH_OUTPUTS  = 0x00000004,
+       HAL_VIDEO_UNUSED_OUTPUTS        = 0x10000000,
+};
+
+enum hal_core_capabilities {
+       HAL_VIDEO_ENCODER_ROTATION_CAPABILITY           = 0x00000001,
+       HAL_VIDEO_ENCODER_SCALING_CAPABILITY            = 0x00000002,
+       HAL_VIDEO_ENCODER_DEINTERLACE_CAPABILITY        = 0x00000004,
+       HAL_VIDEO_DECODER_MULTI_STREAM_CAPABILITY       = 0x00000008,
+       HAL_VIDEO_UNUSED_CAPABILITY                     = 0x10000000,
+};
+
+enum hal_default_properties {
+       HAL_VIDEO_DYNAMIC_BUF_MODE              = 0x00000001,
+       HAL_VIDEO_CONTINUE_DATA_TRANSFER        = 0x00000002,
+};
+
+enum hal_video_codec {
+       HAL_VIDEO_CODEC_UNKNOWN         = 0x00000000,
+       HAL_VIDEO_CODEC_MVC             = 0x00000001,
+       HAL_VIDEO_CODEC_H264            = 0x00000002,
+       HAL_VIDEO_CODEC_H263            = 0x00000004,
+       HAL_VIDEO_CODEC_MPEG1           = 0x00000008,
+       HAL_VIDEO_CODEC_MPEG2           = 0x00000010,
+       HAL_VIDEO_CODEC_MPEG4           = 0x00000020,
+       HAL_VIDEO_CODEC_DIVX_311        = 0x00000040,
+       HAL_VIDEO_CODEC_DIVX            = 0x00000080,
+       HAL_VIDEO_CODEC_VC1             = 0x00000100,
+       HAL_VIDEO_CODEC_SPARK           = 0x00000200,
+       HAL_VIDEO_CODEC_VP6             = 0x00000400,
+       HAL_VIDEO_CODEC_VP7             = 0x00000800,
+       HAL_VIDEO_CODEC_VP8             = 0x00001000,
+       HAL_VIDEO_CODEC_HEVC            = 0x00002000,
+       HAL_VIDEO_CODEC_HEVC_HYBRID     = 0x00004000,
+       HAL_UNUSED_CODEC                = 0x10000000,
+};
+
+enum hal_h263_profile {
+       HAL_H263_PROFILE_BASELINE               = 0x00000001,
+       HAL_H263_PROFILE_H320CODING             = 0x00000002,
+       HAL_H263_PROFILE_BACKWARDCOMPATIBLE     = 0x00000004,
+       HAL_H263_PROFILE_ISWV2                  = 0x00000008,
+       HAL_H263_PROFILE_ISWV3                  = 0x00000010,
+       HAL_H263_PROFILE_HIGHCOMPRESSION        = 0x00000020,
+       HAL_H263_PROFILE_INTERNET               = 0x00000040,
+       HAL_H263_PROFILE_INTERLACE              = 0x00000080,
+       HAL_H263_PROFILE_HIGHLATENCY            = 0x00000100,
+       HAL_UNUSED_H263_PROFILE                 = 0x10000000,
+};
+
+enum hal_h263_level {
+       HAL_H263_LEVEL_10       = 0x00000001,
+       HAL_H263_LEVEL_20       = 0x00000002,
+       HAL_H263_LEVEL_30       = 0x00000004,
+       HAL_H263_LEVEL_40       = 0x00000008,
+       HAL_H263_LEVEL_45       = 0x00000010,
+       HAL_H263_LEVEL_50       = 0x00000020,
+       HAL_H263_LEVEL_60       = 0x00000040,
+       HAL_H263_LEVEL_70       = 0x00000080,
+       HAL_UNUSED_H263_LEVEL   = 0x10000000,
+};
+
+enum hal_mpeg2_profile {
+       HAL_MPEG2_PROFILE_SIMPLE        = 0x00000001,
+       HAL_MPEG2_PROFILE_MAIN          = 0x00000002,
+       HAL_MPEG2_PROFILE_422           = 0x00000004,
+       HAL_MPEG2_PROFILE_SNR           = 0x00000008,
+       HAL_MPEG2_PROFILE_SPATIAL       = 0x00000010,
+       HAL_MPEG2_PROFILE_HIGH          = 0x00000020,
+       HAL_UNUSED_MPEG2_PROFILE        = 0x10000000,
+};
+
+enum hal_mpeg2_level {
+       HAL_MPEG2_LEVEL_LL      = 0x00000001,
+       HAL_MPEG2_LEVEL_ML      = 0x00000002,
+       HAL_MPEG2_LEVEL_H14     = 0x00000004,
+       HAL_MPEG2_LEVEL_HL      = 0x00000008,
+       HAL_UNUSED_MEPG2_LEVEL  = 0x10000000,
+};
+
+enum hal_mpeg4_profile {
+       HAL_MPEG4_PROFILE_SIMPLE                = 0x00000001,
+       HAL_MPEG4_PROFILE_ADVANCEDSIMPLE        = 0x00000002,
+       HAL_MPEG4_PROFILE_CORE                  = 0x00000004,
+       HAL_MPEG4_PROFILE_MAIN                  = 0x00000008,
+       HAL_MPEG4_PROFILE_NBIT                  = 0x00000010,
+       HAL_MPEG4_PROFILE_SCALABLETEXTURE       = 0x00000020,
+       HAL_MPEG4_PROFILE_SIMPLEFACE            = 0x00000040,
+       HAL_MPEG4_PROFILE_SIMPLEFBA             = 0x00000080,
+       HAL_MPEG4_PROFILE_BASICANIMATED         = 0x00000100,
+       HAL_MPEG4_PROFILE_HYBRID                = 0x00000200,
+       HAL_MPEG4_PROFILE_ADVANCEDREALTIME      = 0x00000400,
+       HAL_MPEG4_PROFILE_CORESCALABLE          = 0x00000800,
+       HAL_MPEG4_PROFILE_ADVANCEDCODING        = 0x00001000,
+       HAL_MPEG4_PROFILE_ADVANCEDCORE          = 0x00002000,
+       HAL_MPEG4_PROFILE_ADVANCEDSCALABLE      = 0x00004000,
+       HAL_MPEG4_PROFILE_SIMPLESCALABLE        = 0x00008000,
+       HAL_UNUSED_MPEG4_PROFILE                = 0x10000000,
+};
+
+enum hal_mpeg4_level {
+       HAL_MPEG4_LEVEL_0                       = 0x00000001,
+       HAL_MPEG4_LEVEL_0b                      = 0x00000002,
+       HAL_MPEG4_LEVEL_1                       = 0x00000004,
+       HAL_MPEG4_LEVEL_2                       = 0x00000008,
+       HAL_MPEG4_LEVEL_3                       = 0x00000010,
+       HAL_MPEG4_LEVEL_4                       = 0x00000020,
+       HAL_MPEG4_LEVEL_4a                      = 0x00000040,
+       HAL_MPEG4_LEVEL_5                       = 0x00000080,
+       HAL_MPEG4_LEVEL_VENDOR_START_UNUSED     = 0x7F000000,
+       HAL_MPEG4_LEVEL_6                       = 0x7F000001,
+       HAL_MPEG4_LEVEL_7                       = 0x7F000002,
+       HAL_MPEG4_LEVEL_8                       = 0x7F000003,
+       HAL_MPEG4_LEVEL_9                       = 0x7F000004,
+       HAL_MPEG4_LEVEL_3b                      = 0x7F000005,
+       HAL_UNUSED_MPEG4_LEVEL                  = 0x10000000,
+};
+
+enum hal_h264_profile {
+       HAL_H264_PROFILE_BASELINE               = 0x00000001,
+       HAL_H264_PROFILE_MAIN                   = 0x00000002,
+       HAL_H264_PROFILE_HIGH                   = 0x00000004,
+       HAL_H264_PROFILE_EXTENDED               = 0x00000008,
+       HAL_H264_PROFILE_HIGH10                 = 0x00000010,
+       HAL_H264_PROFILE_HIGH422                = 0x00000020,
+       HAL_H264_PROFILE_HIGH444                = 0x00000040,
+       HAL_H264_PROFILE_CONSTRAINED_BASE       = 0x00000080,
+       HAL_H264_PROFILE_CONSTRAINED_HIGH       = 0x00000100,
+       HAL_UNUSED_H264_PROFILE                 = 0x10000000,
+};
+
+enum hal_h264_level {
+       HAL_H264_LEVEL_1        = 0x00000001,
+       HAL_H264_LEVEL_1b       = 0x00000002,
+       HAL_H264_LEVEL_11       = 0x00000004,
+       HAL_H264_LEVEL_12       = 0x00000008,
+       HAL_H264_LEVEL_13       = 0x00000010,
+       HAL_H264_LEVEL_2        = 0x00000020,
+       HAL_H264_LEVEL_21       = 0x00000040,
+       HAL_H264_LEVEL_22       = 0x00000080,
+       HAL_H264_LEVEL_3        = 0x00000100,
+       HAL_H264_LEVEL_31       = 0x00000200,
+       HAL_H264_LEVEL_32       = 0x00000400,
+       HAL_H264_LEVEL_4        = 0x00000800,
+       HAL_H264_LEVEL_41       = 0x00001000,
+       HAL_H264_LEVEL_42       = 0x00002000,
+       HAL_H264_LEVEL_5        = 0x00004000,
+       HAL_H264_LEVEL_51       = 0x00008000,
+       HAL_H264_LEVEL_52       = 0x00010000,
+       HAL_UNUSED_H264_LEVEL   = 0x10000000,
+};
+
+enum hal_hevc_profile {
+       HAL_HEVC_PROFILE_MAIN           = 0x00000001,
+       HAL_HEVC_PROFILE_MAIN10         = 0x00000002,
+       HAL_HEVC_PROFILE_MAIN_STILL_PIC = 0x00000004,
+       HAL_UNUSED_HEVC_PROFILE         = 0x10000000,
+};
+
+enum hal_hevc_level {
+       HAL_HEVC_MAIN_TIER_LEVEL_1      = 0x10000001,
+       HAL_HEVC_MAIN_TIER_LEVEL_2      = 0x10000002,
+       HAL_HEVC_MAIN_TIER_LEVEL_2_1    = 0x10000004,
+       HAL_HEVC_MAIN_TIER_LEVEL_3      = 0x10000008,
+       HAL_HEVC_MAIN_TIER_LEVEL_3_1    = 0x10000010,
+       HAL_HEVC_MAIN_TIER_LEVEL_4      = 0x10000020,
+       HAL_HEVC_MAIN_TIER_LEVEL_4_1    = 0x10000040,
+       HAL_HEVC_MAIN_TIER_LEVEL_5      = 0x10000080,
+       HAL_HEVC_MAIN_TIER_LEVEL_5_1    = 0x10000100,
+       HAL_HEVC_MAIN_TIER_LEVEL_5_2    = 0x10000200,
+       HAL_HEVC_MAIN_TIER_LEVEL_6      = 0x10000400,
+       HAL_HEVC_MAIN_TIER_LEVEL_6_1    = 0x10000800,
+       HAL_HEVC_MAIN_TIER_LEVEL_6_2    = 0x10001000,
+       HAL_HEVC_HIGH_TIER_LEVEL_1      = 0x20000001,
+       HAL_HEVC_HIGH_TIER_LEVEL_2      = 0x20000002,
+       HAL_HEVC_HIGH_TIER_LEVEL_2_1    = 0x20000004,
+       HAL_HEVC_HIGH_TIER_LEVEL_3      = 0x20000008,
+       HAL_HEVC_HIGH_TIER_LEVEL_3_1    = 0x20000010,
+       HAL_HEVC_HIGH_TIER_LEVEL_4      = 0x20000020,
+       HAL_HEVC_HIGH_TIER_LEVEL_4_1    = 0x20000040,
+       HAL_HEVC_HIGH_TIER_LEVEL_5      = 0x20000080,
+       HAL_HEVC_HIGH_TIER_LEVEL_5_1    = 0x20000100,
+       HAL_HEVC_HIGH_TIER_LEVEL_5_2    = 0x20000200,
+       HAL_HEVC_HIGH_TIER_LEVEL_6      = 0x20000400,
+       HAL_HEVC_HIGH_TIER_LEVEL_6_1    = 0x20000800,
+       HAL_HEVC_HIGH_TIER_LEVEL_6_2    = 0x20001000,
+       HAL_UNUSED_HEVC_TIER_LEVEL      = 0x80000000,
+};
+
+enum hal_hevc_tier {
+       HAL_HEVC_TIER_MAIN      = 0x00000001,
+       HAL_HEVC_TIER_HIGH      = 0x00000002,
+       HAL_UNUSED_HEVC_TIER    = 0x10000000,
+};
+
+enum hal_vpx_profile {
+       HAL_VPX_PROFILE_SIMPLE          = 0x00000001,
+       HAL_VPX_PROFILE_ADVANCED        = 0x00000002,
+       HAL_VPX_PROFILE_VERSION_0       = 0x00000004,
+       HAL_VPX_PROFILE_VERSION_1       = 0x00000008,
+       HAL_VPX_PROFILE_VERSION_2       = 0x00000010,
+       HAL_VPX_PROFILE_VERSION_3       = 0x00000020,
+       HAL_VPX_PROFILE_UNUSED          = 0x10000000,
+};
+
+enum hal_vc1_profile {
+       HAL_VC1_PROFILE_SIMPLE          = 0x00000001,
+       HAL_VC1_PROFILE_MAIN            = 0x00000002,
+       HAL_VC1_PROFILE_ADVANCED        = 0x00000004,
+       HAL_UNUSED_VC1_PROFILE          = 0x10000000,
+};
+
+enum hal_vc1_level {
+       HAL_VC1_LEVEL_LOW       = 0x00000001,
+       HAL_VC1_LEVEL_MEDIUM    = 0x00000002,
+       HAL_VC1_LEVEL_HIGH      = 0x00000004,
+       HAL_VC1_LEVEL_0         = 0x00000008,
+       HAL_VC1_LEVEL_1         = 0x00000010,
+       HAL_VC1_LEVEL_2         = 0x00000020,
+       HAL_VC1_LEVEL_3         = 0x00000040,
+       HAL_VC1_LEVEL_4         = 0x00000080,
+       HAL_UNUSED_VC1_LEVEL    = 0x10000000,
+};
+
+enum hal_divx_format {
+       HAL_DIVX_FORMAT_4,
+       HAL_DIVX_FORMAT_5,
+       HAL_DIVX_FORMAT_6,
+       HAL_UNUSED_DIVX_FORMAT  = 0x10000000,
+};
+
+enum hal_divx_profile {
+       HAL_DIVX_PROFILE_QMOBILE        = 0x00000001,
+       HAL_DIVX_PROFILE_MOBILE         = 0x00000002,
+       HAL_DIVX_PROFILE_MT             = 0x00000004,
+       HAL_DIVX_PROFILE_HT             = 0x00000008,
+       HAL_DIVX_PROFILE_HD             = 0x00000010,
+       HAL_UNUSED_DIVX_PROFILE         = 0x10000000,
+};
+
+enum hal_mvc_profile {
+       HAL_MVC_PROFILE_STEREO_HIGH     = 0x00001000,
+       HAL_UNUSED_MVC_PROFILE          = 0x10000000,
+};
+
+enum hal_mvc_level {
+       HAL_MVC_LEVEL_1         = 0x00000001,
+       HAL_MVC_LEVEL_1b        = 0x00000002,
+       HAL_MVC_LEVEL_11        = 0x00000004,
+       HAL_MVC_LEVEL_12        = 0x00000008,
+       HAL_MVC_LEVEL_13        = 0x00000010,
+       HAL_MVC_LEVEL_2         = 0x00000020,
+       HAL_MVC_LEVEL_21        = 0x00000040,
+       HAL_MVC_LEVEL_22        = 0x00000080,
+       HAL_MVC_LEVEL_3         = 0x00000100,
+       HAL_MVC_LEVEL_31        = 0x00000200,
+       HAL_MVC_LEVEL_32        = 0x00000400,
+       HAL_MVC_LEVEL_4         = 0x00000800,
+       HAL_MVC_LEVEL_41        = 0x00001000,
+       HAL_MVC_LEVEL_42        = 0x00002000,
+       HAL_MVC_LEVEL_5         = 0x00004000,
+       HAL_MVC_LEVEL_51        = 0x00008000,
+       HAL_UNUSED_MVC_LEVEL    = 0x10000000,
+};
+
+struct hal_frame_rate {
+       enum hal_buffer buffer_type;
+       u32 frame_rate;
+};
+
+enum hal_uncompressed_format {
+       HAL_COLOR_FORMAT_MONOCHROME     = 0x00000001,
+       HAL_COLOR_FORMAT_NV12           = 0x00000002,
+       HAL_COLOR_FORMAT_NV21           = 0x00000004,
+       HAL_COLOR_FORMAT_NV12_4x4TILE   = 0x00000008,
+       HAL_COLOR_FORMAT_NV21_4x4TILE   = 0x00000010,
+       HAL_COLOR_FORMAT_YUYV           = 0x00000020,
+       HAL_COLOR_FORMAT_YVYU           = 0x00000040,
+       HAL_COLOR_FORMAT_UYVY           = 0x00000080,
+       HAL_COLOR_FORMAT_VYUY           = 0x00000100,
+       HAL_COLOR_FORMAT_RGB565         = 0x00000200,
+       HAL_COLOR_FORMAT_BGR565         = 0x00000400,
+       HAL_COLOR_FORMAT_RGB888         = 0x00000800,
+       HAL_COLOR_FORMAT_BGR888         = 0x00001000,
+       HAL_COLOR_FORMAT_NV12_UBWC      = 0x00002000,
+       HAL_COLOR_FORMAT_NV12_TP10_UBWC = 0x00004000,
+       HAL_UNUSED_COLOR                = 0x10000000,
+};
+
+enum hal_ssr_trigger_type {
+       SSR_ERR_FATAL           = 1,
+       SSR_SW_DIV_BY_ZERO,
+       SSR_HW_WDOG_IRQ,
+};
+
+enum vidc_extradata_type {
+       VIDC_EXTRADATA_NONE = 0x00000000,
+       VIDC_EXTRADATA_MB_QUANTIZATION = 0x00000001,
+       VIDC_EXTRADATA_INTERLACE_VIDEO = 0x00000002,
+       VIDC_EXTRADATA_VC1_FRAMEDISP = 0x00000003,
+       VIDC_EXTRADATA_VC1_SEQDISP = 0x00000004,
+       VIDC_EXTRADATA_TIMESTAMP = 0x00000005,
+       VIDC_EXTRADATA_S3D_FRAME_PACKING = 0x00000006,
+       VIDC_EXTRADATA_FRAME_RATE = 0x00000007,
+       VIDC_EXTRADATA_PANSCAN_WINDOW = 0x00000008,
+       VIDC_EXTRADATA_RECOVERY_POINT_SEI = 0x00000009,
+       VIDC_EXTRADATA_MPEG2_SEQDISP = 0x0000000D,
+       VIDC_EXTRADATA_STREAM_USERDATA = 0x0000000E,
+       VIDC_EXTRADATA_FRAME_QP = 0x0000000F,
+       VIDC_EXTRADATA_FRAME_BITS_INFO = 0x00000010,
+       VIDC_EXTRADATA_INPUT_CROP = 0x0700000E,
+       VIDC_EXTRADATA_DIGITAL_ZOOM = 0x07000010,
+       VIDC_EXTRADATA_MULTISLICE_INFO = 0x7F100000,
+       VIDC_EXTRADATA_NUM_CONCEALED_MB = 0x7F100001,
+       VIDC_EXTRADATA_INDEX = 0x7F100002,
+       VIDC_EXTRADATA_ASPECT_RATIO = 0x7F100003,
+       VIDC_EXTRADATA_METADATA_LTR = 0x7F100004,
+       VIDC_EXTRADATA_METADATA_FILLER = 0x7FE00002,
+       VIDC_EXTRADATA_METADATA_MBI = 0x7F100005,
+};
+
+struct hal_uncompressed_format_select {
+       enum hal_buffer buffer_type;
+       enum hal_uncompressed_format format;
+};
+
+struct hal_uncompressed_plane_actual {
+       int actual_stride;
+       u32 actual_plane_buffer_height;
+};
+
+struct hal_uncompressed_plane_actual_info {
+       enum hal_buffer buffer_type;
+       u32 num_planes;
+       struct hal_uncompressed_plane_actual rg_plane_format[1];
+};
+
+struct hal_uncompressed_plane_constraints {
+       u32 stride_multiples;
+       u32 max_stride;
+       u32 min_plane_buffer_height_multiple;
+       u32 buffer_alignment;
+};
+
+struct hal_uncompressed_plane_actual_constraints_info {
+       enum hal_buffer buffer_type;
+       u32 num_planes;
+       struct hal_uncompressed_plane_constraints rg_plane_format[1];
+};
+
+struct hal_extra_data_header_config {
+       u32 type;
+       enum hal_buffer buffer_type;
+       u32 version;
+       u32 port_index;
+       u32 client_extradata_id;
+};
+
+struct hal_frame_size {
+       enum hal_buffer buffer_type;
+       u32 width;
+       u32 height;
+};
+
+struct hal_enable {
+       u32 enable;
+};
+
+struct hal_buffer_count_actual {
+       enum hal_buffer type;
+       u32 count_actual;
+};
+
+struct hal_buffer_size_actual {
+       enum hal_buffer type;
+       u32 size;
+};
+
+struct hal_buffer_display_hold_count_actual {
+       enum hal_buffer buffer_type;
+       u32 hold_count;
+};
+
+enum hal_nal_stream_format {
+       HAL_NAL_FORMAT_STARTCODES               = 0x00000001,
+       HAL_NAL_FORMAT_ONE_NAL_PER_BUFFER       = 0x00000002,
+       HAL_NAL_FORMAT_ONE_BYTE_LENGTH          = 0x00000004,
+       HAL_NAL_FORMAT_TWO_BYTE_LENGTH          = 0x00000008,
+       HAL_NAL_FORMAT_FOUR_BYTE_LENGTH         = 0x00000010,
+};
+
+enum hal_output_order {
+       HAL_OUTPUT_ORDER_DISPLAY,
+       HAL_OUTPUT_ORDER_DECODE,
+       HAL_UNUSED_OUTPUT       = 0x10000000,
+};
+
+enum hal_picture {
+       HAL_PICTURE_I           = 0x01,
+       HAL_PICTURE_P           = 0x02,
+       HAL_PICTURE_B           = 0x04,
+       HAL_PICTURE_IDR         = 0x08,
+       HAL_FRAME_NOTCODED      = 0x7F002000,
+       HAL_FRAME_YUV           = 0x7F004000,
+       HAL_UNUSED_PICT         = 0x10000000,
+};
+
+struct hal_extradata_enable {
+       u32 enable;
+       enum hal_extradata_id index;
+};
+
+struct hal_enable_picture {
+       u32 picture_type;
+};
+
+struct hal_multi_stream {
+       enum hal_buffer buffer_type;
+       u32 enable;
+       u32 width;
+       u32 height;
+};
+
+struct hal_display_picture_buffer_count {
+       u32 enable;
+       u32 count;
+};
+
+struct hal_mb_error_map {
+       u32 error_map_size;
+       u8 rg_error_map[1];
+};
+
+struct hal_request_iframe {
+       u32 enable;
+};
+
+struct hal_bitrate {
+       u32 bit_rate;
+       u32 layer_id;
+};
+
+struct hal_profile_level {
+       u32 profile;
+       u32 level;
+};
+
+struct hal_profile_level_supported {
+       u32 profile_count;
+       struct hal_profile_level profile_level[MAX_PROFILE_COUNT];
+};
+
+enum hal_h264_entropy {
+       HAL_H264_ENTROPY_CAVLC  = 1,
+       HAL_H264_ENTROPY_CABAC  = 2,
+       HAL_UNUSED_ENTROPY      = 0x10000000,
+};
+
+enum hal_h264_cabac_model {
+       HAL_H264_CABAC_MODEL_0  = 1,
+       HAL_H264_CABAC_MODEL_1  = 2,
+       HAL_H264_CABAC_MODEL_2  = 4,
+       HAL_UNUSED_CABAC        = 0x10000000,
+};
+
+struct hal_h264_entropy_control {
+       enum hal_h264_entropy entropy_mode;
+       enum hal_h264_cabac_model cabac_model;
+};
+
+enum hal_rate_control {
+       HAL_RATE_CONTROL_OFF,
+       HAL_RATE_CONTROL_VBR_VFR,
+       HAL_RATE_CONTROL_VBR_CFR,
+       HAL_RATE_CONTROL_CBR_VFR,
+       HAL_RATE_CONTROL_CBR_CFR,
+       HAL_UNUSED_RC = 0x10000000,
+};
+
+struct hal_mpeg4_time_resolution {
+       u32 time_increment_resolution;
+};
+
+struct hal_mpeg4_header_extension {
+       u32 header_extension;
+};
+
+enum hal_h264_db_mode {
+       HAL_H264_DB_MODE_DISABLE,
+       HAL_H264_DB_MODE_SKIP_SLICE_BOUNDARY,
+       HAL_H264_DB_MODE_ALL_BOUNDARY,
+       HAL_UNUSED_H264_DB = 0x10000000,
+};
+
+struct hal_h264_db_control {
+       enum hal_h264_db_mode mode;
+       int slice_alpha_offset;
+       int slice_beta_offset;
+};
+
+struct hal_temporal_spatial_tradeoff {
+       u32 ts_factor;
+};
+
+struct hal_quantization {
+       u32 qpi;
+       u32 qpp;
+       u32 qpb;
+       u32 layer_id;
+};
+
+struct hal_initial_quantization {
+       u32 qpi;
+       u32 qpp;
+       u32 qpb;
+       u32 init_qp_enable;
+};
+
+struct hal_quantization_range {
+       u32 min_qp;
+       u32 max_qp;
+       u32 layer_id;
+};
+
+struct hal_intra_period {
+       u32 pframes;
+       u32 bframes;
+};
+
+struct hal_idr_period {
+       u32 idr_period;
+};
+
+enum hal_rotate {
+       HAL_ROTATE_NONE,
+       HAL_ROTATE_90,
+       HAL_ROTATE_180,
+       HAL_ROTATE_270,
+       HAL_UNUSED_ROTATE = 0x10000000,
+};
+
+enum hal_flip {
+       HAL_FLIP_NONE,
+       HAL_FLIP_HORIZONTAL,
+       HAL_FLIP_VERTICAL,
+       HAL_UNUSED_FLIP = 0x10000000,
+};
+
+struct hal_operations {
+       enum hal_rotate rotate;
+       enum hal_flip flip;
+};
+
+enum hal_intra_refresh_mode {
+       HAL_INTRA_REFRESH_NONE,
+       HAL_INTRA_REFRESH_CYCLIC,
+       HAL_INTRA_REFRESH_ADAPTIVE,
+       HAL_INTRA_REFRESH_CYCLIC_ADAPTIVE,
+       HAL_INTRA_REFRESH_RANDOM,
+       HAL_UNUSED_INTRA = 0x10000000,
+};
+
+struct hal_intra_refresh {
+       enum hal_intra_refresh_mode mode;
+       u32 air_mbs;
+       u32 air_ref;
+       u32 cir_mbs;
+};
+
+enum hal_multi_slice {
+       HAL_MULTI_SLICE_OFF,
+       HAL_MULTI_SLICE_BY_MB_COUNT,
+       HAL_MULTI_SLICE_BY_BYTE_COUNT,
+       HAL_MULTI_SLICE_GOB,
+       HAL_UNUSED_SLICE = 0x10000000,
+};
+
+struct hal_multi_slice_control {
+       enum hal_multi_slice multi_slice;
+       u32 slice_size;
+};
+
+struct hal_debug_config {
+       u32 debug_config;
+};
+
+struct hal_buffer_requirements {
+       enum hal_buffer type;
+       u32 size;
+       u32 region_size;
+       u32 hold_count;
+       u32 count_min;
+       u32 count_actual;
+       u32 contiguous;
+       u32 alignment;
+};
+
+enum hal_priority {/* Priority increases with number */
+       HAL_PRIORITY_LOW = 10,
+       HAL_PRIOIRTY_MEDIUM = 20,
+       HAL_PRIORITY_HIGH = 30,
+       HAL_UNUSED_PRIORITY = 0x10000000,
+};
+
+struct hal_batch_info {
+       u32 input_batch_count;
+       u32 output_batch_count;
+};
+
+struct hal_metadata_pass_through {
+       u32 enable;
+       u32 size;
+};
+
+struct hal_uncompressed_format_supported {
+       enum hal_buffer buffer_type;
+       u32 format_entries;
+       u32 rg_format_info[1];
+};
+
+enum hal_interlace_format {
+       HAL_INTERLACE_FRAME_PROGRESSIVE                 = 0x01,
+       HAL_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST    = 0x02,
+       HAL_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST = 0x04,
+       HAL_INTERLACE_FRAME_TOPFIELDFIRST               = 0x08,
+       HAL_INTERLACE_FRAME_BOTTOMFIELDFIRST            = 0x10,
+       HAL_UNUSED_INTERLACE                            = 0x10000000,
+};
+
+struct hal_interlace_format_supported {
+       enum hal_buffer buffer_type;
+       enum hal_interlace_format format;
+};
+
+enum hal_chroma_site {
+       HAL_CHROMA_SITE_0,
+       HAL_CHROMA_SITE_1,
+       HAL_UNUSED_CHROMA = 0x10000000,
+};
+
+struct hal_properties_supported {
+       u32 num_properties;
+       u32 rg_properties[1];
+};
+
+enum hal_capability {
+       HAL_CAPABILITY_FRAME_WIDTH,
+       HAL_CAPABILITY_FRAME_HEIGHT,
+       HAL_CAPABILITY_MBS_PER_FRAME,
+       HAL_CAPABILITY_MBS_PER_SECOND,
+       HAL_CAPABILITY_FRAMERATE,
+       HAL_CAPABILITY_SCALE_X,
+       HAL_CAPABILITY_SCALE_Y,
+       HAL_CAPABILITY_BITRATE,
+       HAL_CAPABILITY_SECURE_OUTPUT2_THRESHOLD,
+       HAL_UNUSED_CAPABILITY = 0x10000000,
+};
+
+struct hal_capability_supported {
+       enum hal_capability capability_type;
+       u32 min;
+       u32 max;
+       u32 step_size;
+};
+
+struct hal_capability_supported_info {
+       u32 num_capabilities;
+       struct hal_capability_supported rg_data[1];
+};
+
+struct hal_nal_stream_format_supported {
+       u32 nal_stream_format_supported;
+};
+
+struct hal_nal_stream_format_select {
+       u32 nal_stream_format_select;
+};
+
+struct hal_multi_view_format {
+       u32 views;
+       u32 rg_view_order[1];
+};
+
+enum hal_buffer_layout_type {
+       HAL_BUFFER_LAYOUT_TOP_BOTTOM,
+       HAL_BUFFER_LAYOUT_SEQ,
+       HAL_UNUSED_BUFFER_LAYOUT = 0x10000000,
+};
+
+struct hal_mvc_buffer_layout {
+       enum hal_buffer_layout_type layout_type;
+       u32 bright_view_first;
+       u32 ngap;
+};
+
+struct hal_seq_header_info {
+       u32 nax_header_len;
+};
+
+struct hal_codec_supported {
+       u32 decoder_codec_supported;
+       u32 encoder_codec_supported;
+};
+
+struct hal_multi_view_select {
+       u32 view_index;
+};
+
+struct hal_timestamp_scale {
+       u32 time_stamp_scale;
+};
+
+
+struct hal_h264_vui_timing_info {
+       u32 enable;
+       u32 fixed_frame_rate;
+       u32 time_scale;
+};
+
+struct hal_h264_vui_bitstream_restrc {
+       u32 enable;
+};
+
+struct hal_preserve_text_quality {
+       u32 enable;
+};
+
+struct hal_vc1e_perf_cfg_type {
+       struct {
+               u32 x_subsampled;
+               u32 y_subsampled;
+       } i_frame, p_frame, b_frame;
+};
+
+struct hal_vpe_color_space_conversion {
+       u32 csc_matrix[HAL_MAX_MATRIX_COEFFS];
+       u32 csc_bias[HAL_MAX_BIAS_COEFFS];
+       u32 csc_limit[HAL_MAX_LIMIT_COEFFS];
+};
+
+enum vidc_resource_id {
+       VIDC_RESOURCE_NONE,
+       VIDC_RESOURCE_OCMEM,
+       VIDC_RESOURCE_VMEM,
+       VIDC_UNUSED_RESOURCE = 0x10000000,
+};
+
+struct vidc_resource_hdr {
+       enum vidc_resource_id resource_id;
+       void *resource_handle;
+       u32 size;
+};
+
+struct vidc_buffer_addr_info {
+       enum hal_buffer buffer_type;
+       u32 buffer_size;
+       u32 num_buffers;
+       u32 device_addr;
+       u32 extradata_addr;
+       u32 extradata_size;
+       u32 response_required;
+};
+
+/* Needs to be exactly the same as hfi_buffer_info */
+struct hal_buffer_info {
+       u32 buffer_addr;
+       u32 extra_data_addr;
+};
+
+struct vidc_frame_plane_config {
+       u32 left;
+       u32 top;
+       u32 width;
+       u32 height;
+       u32 stride;
+       u32 scan_lines;
+};
+
+struct vidc_uncompressed_frame_config {
+       struct vidc_frame_plane_config luma_plane;
+       struct vidc_frame_plane_config chroma_plane;
+};
+
+struct vidc_frame_data {
+       enum hal_buffer buffer_type;
+       u32 device_addr;
+       u32 extradata_addr;
+       int64_t timestamp;
+       u32 flags;
+       u32 offset;
+       u32 alloc_len;
+       u32 filled_len;
+       u32 mark_target;
+       u32 mark_data;
+       u32 clnt_data;
+       u32 extradata_size;
+};
+
+struct vidc_seq_hdr {
+       u32 seq_hdr;
+       u32 seq_hdr_len;
+};
+
+enum hal_flush {
+       HAL_FLUSH_INPUT,
+       HAL_FLUSH_OUTPUT,
+       HAL_FLUSH_OUTPUT2,
+       HAL_FLUSH_ALL,
+       HAL_UNUSED_FLUSH = 0x10000000,
+};
+
+enum hal_event_type {
+       HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES,
+       HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES,
+       HAL_EVENT_RELEASE_BUFFER_REFERENCE,
+       HAL_UNUSED_SEQCHG = 0x10000000,
+};
+
+enum hal_buffer_mode_type {
+       HAL_BUFFER_MODE_STATIC = 0x001,
+       HAL_BUFFER_MODE_RING = 0x010,
+       HAL_BUFFER_MODE_DYNAMIC = 0x100,
+};
+
+struct hal_buffer_alloc_mode {
+       enum hal_buffer type;
+       enum hal_buffer_mode_type mode;
+};
+
+enum ltr_mode {
+       HAL_LTR_MODE_DISABLE,
+       HAL_LTR_MODE_MANUAL,
+       HAL_LTR_MODE_PERIODIC,
+};
+
+struct hal_ltr_mode {
+       enum ltr_mode mode;
+       u32 count;
+       u32 trust_mode;
+};
+
+struct hal_ltr_use {
+       u32 ref_ltr;
+       u32 use_constraint;
+       u32 frames;
+};
+
+struct hal_ltr_mark {
+       u32 mark_frame;
+};
+
+struct hal_venc_perf_mode {
+       u32 mode;
+};
+
+struct hal_hybrid_hierp {
+       u32 layers;
+};
+
+struct hfi_scs_threshold {
+       u32 threshold_value;
+};
+
+struct buffer_requirements {
+       struct hal_buffer_requirements buffer[HAL_BUFFER_MAX];
+};
+
+union hal_get_property {
+       struct hal_frame_rate frame_rate;
+       struct hal_uncompressed_format_select format_select;
+       struct hal_uncompressed_plane_actual plane_actual;
+       struct hal_uncompressed_plane_actual_info plane_actual_info;
+       struct hal_uncompressed_plane_constraints plane_constraints;
+       struct hal_uncompressed_plane_actual_constraints_info
+                                               plane_constraints_info;
+       struct hal_extra_data_header_config extra_data_header_config;
+       struct hal_frame_size frame_size;
+       struct hal_enable enable;
+       struct hal_buffer_count_actual buffer_count_actual;
+       struct hal_extradata_enable extradata_enable;
+       struct hal_enable_picture enable_picture;
+       struct hal_multi_stream multi_stream;
+       struct hal_display_picture_buffer_count display_picture_buffer_count;
+       struct hal_mb_error_map mb_error_map;
+       struct hal_request_iframe request_iframe;
+       struct hal_bitrate bitrate;
+       struct hal_profile_level profile_level;
+       struct hal_profile_level_supported profile_level_supported;
+       struct hal_h264_entropy_control h264_entropy_control;
+       struct hal_mpeg4_time_resolution mpeg4_time_resolution;
+       struct hal_mpeg4_header_extension mpeg4_header_extension;
+       struct hal_h264_db_control h264_db_control;
+       struct hal_temporal_spatial_tradeoff temporal_spatial_tradeoff;
+       struct hal_quantization quantization;
+       struct hal_quantization_range quantization_range;
+       struct hal_intra_period intra_period;
+       struct hal_idr_period idr_period;
+       struct hal_operations operations;
+       struct hal_intra_refresh intra_refresh;
+       struct hal_multi_slice_control multi_slice_control;
+       struct hal_debug_config debug_config;
+       struct hal_batch_info batch_info;
+       struct hal_metadata_pass_through metadata_pass_through;
+       struct hal_uncompressed_format_supported uncompressed_format_supported;
+       struct hal_interlace_format_supported interlace_format_supported;
+       struct hal_properties_supported properties_supported;
+       struct hal_capability_supported capability_supported;
+       struct hal_capability_supported_info capability_supported_info;
+       struct hal_nal_stream_format_supported nal_stream_format_supported;
+       struct hal_nal_stream_format_select nal_stream_format_select;
+       struct hal_multi_view_format multi_view_format;
+       struct hal_seq_header_info seq_header_info;
+       struct hal_codec_supported codec_supported;
+       struct hal_multi_view_select multi_view_select;
+       struct hal_timestamp_scale timestamp_scale;
+       struct hal_h264_vui_timing_info h264_vui_timing_info;
+       struct hal_h264_vui_bitstream_restrc h264_vui_bitstream_restrc;
+       struct hal_preserve_text_quality preserve_text_quality;
+       struct hal_buffer_info buffer_info;
+       struct hal_buffer_alloc_mode buffer_alloc_mode;
+       struct buffer_requirements buf_req;
+};
+
+/* HAL Response */
+
+enum command_response {
+       /* SYSTEM COMMANDS_DONE*/
+       SYS_EVENT_CHANGE,
+       SYS_INIT_DONE,
+       SYS_SET_RESOURCE_DONE,
+       SYS_RELEASE_RESOURCE_DONE,
+       SYS_PING_ACK_DONE,
+       SYS_PC_PREP_DONE,
+       SYS_IDLE,
+       SYS_DEBUG,
+       SYS_WATCHDOG_TIMEOUT,
+       SYS_ERROR,
+       /* SESSION COMMANDS_DONE */
+       SESSION_LOAD_RESOURCE_DONE,
+       SESSION_INIT_DONE,
+       SESSION_END_DONE,
+       SESSION_ABORT_DONE,
+       SESSION_START_DONE,
+       SESSION_STOP_DONE,
+       SESSION_ETB_DONE,
+       SESSION_FTB_DONE,
+       SESSION_FLUSH_DONE,
+       SESSION_SUSPEND_DONE,
+       SESSION_RESUME_DONE,
+       SESSION_SET_PROP_DONE,
+       SESSION_GET_PROP_DONE,
+       SESSION_PARSE_SEQ_HDR_DONE,
+       SESSION_GET_SEQ_HDR_DONE,
+       SESSION_RELEASE_BUFFER_DONE,
+       SESSION_RELEASE_RESOURCE_DONE,
+       SESSION_PROPERTY_INFO,
+       SESSION_ERROR,
+       RESPONSE_UNUSED = 0x10000000,
+};
+
+/* Event Callback structure */
+
+struct vidc_cb_event {
+       u32 device_id;
+       u32 session_id;
+       enum vidc_error error;
+       u32 height;
+       u32 width;
+       u32 hal_event_type;
+       u32 packet_buffer;
+       u32 extra_data_buffer;
+       u32 profile;
+       u32 level;
+};
+
+/* Data callback structure */
+
+struct vidc_hal_ebd {
+       u32 timestamp_hi;
+       u32 timestamp_lo;
+       u32 flags;
+       enum vidc_error error;
+       u32 mark_target;
+       u32 mark_data;
+       u32 stats;
+       u32 offset;
+       u32 alloc_len;
+       u32 filled_len;
+       enum hal_picture picture_type;
+       u32 packet_buffer;
+       u32 extra_data_buffer;
+};
+
+struct vidc_hal_fbd {
+       u32 stream_id;
+       u32 view_id;
+       u32 timestamp_hi;
+       u32 timestamp_lo;
+       u32 flags1;
+       u32 mark_target;
+       u32 mark_data;
+       u32 stats;
+       u32 alloc_len1;
+       u32 filled_len1;
+       u32 offset1;
+       u32 frame_width;
+       u32 frame_height;
+       u32 start_x_coord;
+       u32 start_y_coord;
+       u32 input_tag;
+       u32 input_tag1;
+       enum hal_picture picture_type;
+       u32 packet_buffer1;
+       u32 extra_data_buffer;
+       u32 flags2;
+       u32 alloc_len2;
+       u32 filled_len2;
+       u32 offset2;
+       u32 packet_buffer2;
+       u32 flags3;
+       u32 alloc_len3;
+       u32 filled_len3;
+       u32 offset3;
+       u32 packet_buffer3;
+       enum hal_buffer buffer_type;
+};
+
+struct vidc_cb_data_done {
+       u32 device_id;
+       void *session_id;
+       enum vidc_error error;
+       u32 size;
+       u32 clnt_data;
+       union {
+               struct vidc_hal_ebd input_done;
+               struct vidc_hal_fbd output_done;
+       };
+};
+
+struct vidc_hal_sys_init_done {
+       u32 enc_codec_supported;
+       u32 dec_codec_supported;
+};
+
+struct vidc_hal_session_init_done {
+       struct hal_capability_supported width;
+       struct hal_capability_supported height;
+       struct hal_capability_supported mbs_per_frame;
+       struct hal_capability_supported mbs_per_sec;
+       struct hal_capability_supported frame_rate;
+       struct hal_capability_supported scale_x;
+       struct hal_capability_supported scale_y;
+       struct hal_capability_supported bitrate;
+       struct hal_capability_supported hier_p;
+       struct hal_capability_supported ltr_count;
+       struct hal_capability_supported secure_output2_threshold;
+       struct hal_uncompressed_format_supported uncomp_format;
+       struct hal_interlace_format_supported HAL_format;
+       struct hal_nal_stream_format_supported nal_stream_format;
+       struct hal_profile_level_supported profile_level;
+       /* allocate and released memory for above */
+       struct hal_intra_refresh intra_refresh;
+       struct hal_seq_header_info seq_hdr_info;
+       enum hal_buffer_mode_type alloc_mode_out;
+};
+
+enum vidc_hfi_type {
+       VIDC_HFI_VENUS,
+       VIDC_HFI_Q6,
+};
+
+#define call_hfi_op(hdev, op, args...) \
+       (((hdev) && (hdev)->ops && (hdev)->ops->op) ?   \
+       ((hdev)->ops->op(args)) : 0)
+
+struct hfi_ops {
+       int (*core_init)(void *device);
+       int (*core_release)(void *device);
+       int (*core_ping)(void *device);
+       int (*core_trigger_ssr)(void *device, enum hal_ssr_trigger_type);
+
+       void *(*session_init)(void *device, void *session_id,
+                             enum hal_domain session_type,
+                             enum hal_video_codec codec_type);
+       int (*session_end)(void *session);
+       int (*session_abort)(void *session);
+       int (*session_clean)(void *sess);
+       int (*session_flush)(void *sess, enum hal_flush flush_mode);
+       int (*session_start)(void *sess);
+       int (*session_stop)(void *sess);
+       int (*session_etb)(void *sess, struct vidc_frame_data *input_frame);
+       int (*session_ftb)(void *sess, struct vidc_frame_data *output_frame);
+       int (*session_set_buffers)(void *sess,
+                                  struct vidc_buffer_addr_info *bai);
+       int (*session_release_buffers)(void *sess,
+                                      struct vidc_buffer_addr_info *bai);
+       int (*session_load_res)(void *sess);
+       int (*session_release_res)(void *sess);
+       int (*session_parse_seq_hdr)(void *sess, struct vidc_seq_hdr *seq_hdr);
+       int (*session_get_seq_hdr)(void *sess, struct vidc_seq_hdr *seq_hdr);
+       int (*session_set_property)(void *sess, enum hal_property ptype,
+                                   void *pdata);
+       int (*session_get_property)(void *sess, enum hal_property ptype);
+
+       int (*get_stride_scanline)(int color_fmt, int width, int height,
+                                  int *stride, int *scanlines);
+       int (*get_core_capabilities)(void);
+       int (*resume)(void *dev);
+       int (*suspend)(void *dev);
+       enum hal_default_properties (*get_default_properties)(void *dev);
+};
+
+struct hfi_device {
+       void *hfi_device_data;
+       const struct hfi_ops *ops;
+};
+
+void *vidc_hfi_init(enum vidc_hfi_type hfi_type, u32 device_id,
+                   struct vidc_resources *res);
+void vidc_hfi_deinit(enum vidc_hfi_type hfi_type, struct hfi_device *hdev);
+
+#endif /*__VIDC_HFI_API_H__ */
diff --git a/drivers/media/platform/msm/vidc/hfi/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/hfi/vidc_hfi_helper.h
new file mode 100644 (file)
index 0000000..1015a82
--- /dev/null
@@ -0,0 +1,1059 @@
+/* Copyright (c) 2012-2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __H_VIDC_HFI_HELPER_H__
+#define __H_VIDC_HFI_HELPER_H__
+
+#define HFI_COMMON_BASE                                0
+#define HFI_OX_BASE                            0x01000000
+
+#define HFI_VIDEO_DOMAIN_ENCODER               (HFI_COMMON_BASE + 0x1)
+#define HFI_VIDEO_DOMAIN_DECODER               (HFI_COMMON_BASE + 0x2)
+#define HFI_VIDEO_DOMAIN_VPE                   (HFI_COMMON_BASE + 0x4)
+#define HFI_VIDEO_DOMAIN_MBI                   (HFI_COMMON_BASE + 0x8)
+
+#define HFI_DOMAIN_BASE_COMMON                 (HFI_COMMON_BASE + 0)
+#define HFI_DOMAIN_BASE_VDEC                   (HFI_COMMON_BASE + 0x01000000)
+#define HFI_DOMAIN_BASE_VENC                   (HFI_COMMON_BASE + 0x02000000)
+#define HFI_DOMAIN_BASE_VPE                    (HFI_COMMON_BASE + 0x03000000)
+
+#define HFI_VIDEO_ARCH_OX                      (HFI_COMMON_BASE + 0x1)
+
+#define HFI_ARCH_COMMON_OFFSET                 0
+#define HFI_ARCH_OX_OFFSET                     0x00200000
+
+#define HFI_CMD_START_OFFSET                   0x00010000
+#define HFI_MSG_START_OFFSET                   0x00020000
+
+#define HFI_ERR_NONE                           HFI_COMMON_BASE
+#define HFI_ERR_SYS_FATAL                      (HFI_COMMON_BASE + 0x1)
+#define HFI_ERR_SYS_INVALID_PARAMETER          (HFI_COMMON_BASE + 0x2)
+#define HFI_ERR_SYS_VERSION_MISMATCH           (HFI_COMMON_BASE + 0x3)
+#define HFI_ERR_SYS_INSUFFICIENT_RESOURCES     (HFI_COMMON_BASE + 0x4)
+#define HFI_ERR_SYS_MAX_SESSIONS_REACHED       (HFI_COMMON_BASE + 0x5)
+#define HFI_ERR_SYS_UNSUPPORTED_CODEC          (HFI_COMMON_BASE + 0x6)
+#define HFI_ERR_SYS_SESSION_IN_USE             (HFI_COMMON_BASE + 0x7)
+#define HFI_ERR_SYS_SESSION_ID_OUT_OF_RANGE    (HFI_COMMON_BASE + 0x8)
+#define HFI_ERR_SYS_UNSUPPORTED_DOMAIN         (HFI_COMMON_BASE + 0x9)
+
+#define HFI_ERR_SESSION_FATAL                  (HFI_COMMON_BASE + 0x1001)
+#define HFI_ERR_SESSION_INVALID_PARAMETER      (HFI_COMMON_BASE + 0x1002)
+#define HFI_ERR_SESSION_BAD_POINTER            (HFI_COMMON_BASE + 0x1003)
+#define HFI_ERR_SESSION_INVALID_SESSION_ID     (HFI_COMMON_BASE + 0x1004)
+#define HFI_ERR_SESSION_INVALID_STREAM_ID      (HFI_COMMON_BASE + 0x1005)
+#define HFI_ERR_SESSION_INCORRECT_STATE_OPERATION              \
+                                               (HFI_COMMON_BASE + 0x1006)
+#define HFI_ERR_SESSION_UNSUPPORTED_PROPERTY   (HFI_COMMON_BASE + 0x1007)
+
+#define HFI_ERR_SESSION_UNSUPPORTED_SETTING    (HFI_COMMON_BASE + 0x1008)
+
+#define HFI_ERR_SESSION_INSUFFICIENT_RESOURCES (HFI_COMMON_BASE + 0x1009)
+
+#define HFI_ERR_SESSION_STREAM_CORRUPT_OUTPUT_STALLED  \
+                                               (HFI_COMMON_BASE + 0x100a)
+
+#define HFI_ERR_SESSION_STREAM_CORRUPT         (HFI_COMMON_BASE + 0x100b)
+#define HFI_ERR_SESSION_ENC_OVERFLOW           (HFI_COMMON_BASE + 0x100c)
+#define HFI_ERR_SESSION_UNSUPPORTED_STREAM     (HFI_COMMON_BASE + 0x100d)
+#define HFI_ERR_SESSION_CMDSIZE                        (HFI_COMMON_BASE + 0x100e)
+#define HFI_ERR_SESSION_UNSUPPORT_CMD          (HFI_COMMON_BASE + 0x100f)
+#define HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE   (HFI_COMMON_BASE + 0x1010)
+#define HFI_ERR_SESSION_BUFFERCOUNT_TOOSMALL   (HFI_COMMON_BASE + 0x1011)
+#define HFI_ERR_SESSION_INVALID_SCALE_FACTOR   (HFI_COMMON_BASE + 0x1012)
+#define HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED  (HFI_COMMON_BASE + 0x1013)
+
+#define HFI_EVENT_SYS_ERROR                    (HFI_COMMON_BASE + 0x1)
+#define HFI_EVENT_SESSION_ERROR                        (HFI_COMMON_BASE + 0x2)
+
+#define HFI_VIDEO_CODEC_H264                   0x00000002
+#define HFI_VIDEO_CODEC_H263                   0x00000004
+#define HFI_VIDEO_CODEC_MPEG1                  0x00000008
+#define HFI_VIDEO_CODEC_MPEG2                  0x00000010
+#define HFI_VIDEO_CODEC_MPEG4                  0x00000020
+#define HFI_VIDEO_CODEC_DIVX_311               0x00000040
+#define HFI_VIDEO_CODEC_DIVX                   0x00000080
+#define HFI_VIDEO_CODEC_VC1                    0x00000100
+#define HFI_VIDEO_CODEC_SPARK                  0x00000200
+#define HFI_VIDEO_CODEC_VP8                    0x00001000
+#define HFI_VIDEO_CODEC_HEVC                   0x00002000
+#define HFI_VIDEO_CODEC_HEVC_HYBRID            0x00004000
+
+#define HFI_H264_PROFILE_BASELINE              0x00000001
+#define HFI_H264_PROFILE_MAIN                  0x00000002
+#define HFI_H264_PROFILE_HIGH                  0x00000004
+#define HFI_H264_PROFILE_STEREO_HIGH           0x00000008
+#define HFI_H264_PROFILE_MULTIVIEW_HIGH                0x00000010
+#define HFI_H264_PROFILE_CONSTRAINED_BASE      0x00000020
+#define HFI_H264_PROFILE_CONSTRAINED_HIGH      0x00000040
+
+#define HFI_H264_LEVEL_1                       0x00000001
+#define HFI_H264_LEVEL_1b                      0x00000002
+#define HFI_H264_LEVEL_11                      0x00000004
+#define HFI_H264_LEVEL_12                      0x00000008
+#define HFI_H264_LEVEL_13                      0x00000010
+#define HFI_H264_LEVEL_2                       0x00000020
+#define HFI_H264_LEVEL_21                      0x00000040
+#define HFI_H264_LEVEL_22                      0x00000080
+#define HFI_H264_LEVEL_3                       0x00000100
+#define HFI_H264_LEVEL_31                      0x00000200
+#define HFI_H264_LEVEL_32                      0x00000400
+#define HFI_H264_LEVEL_4                       0x00000800
+#define HFI_H264_LEVEL_41                      0x00001000
+#define HFI_H264_LEVEL_42                      0x00002000
+#define HFI_H264_LEVEL_5                       0x00004000
+#define HFI_H264_LEVEL_51                      0x00008000
+#define HFI_H264_LEVEL_52                      0x00010000
+
+#define HFI_H263_PROFILE_BASELINE              0x00000001
+
+#define HFI_H263_LEVEL_10                      0x00000001
+#define HFI_H263_LEVEL_20                      0x00000002
+#define HFI_H263_LEVEL_30                      0x00000004
+#define HFI_H263_LEVEL_40                      0x00000008
+#define HFI_H263_LEVEL_45                      0x00000010
+#define HFI_H263_LEVEL_50                      0x00000020
+#define HFI_H263_LEVEL_60                      0x00000040
+#define HFI_H263_LEVEL_70                      0x00000080
+
+#define HFI_MPEG2_PROFILE_SIMPLE               0x00000001
+#define HFI_MPEG2_PROFILE_MAIN                 0x00000002
+#define HFI_MPEG2_PROFILE_422                  0x00000004
+#define HFI_MPEG2_PROFILE_SNR                  0x00000008
+#define HFI_MPEG2_PROFILE_SPATIAL              0x00000010
+#define HFI_MPEG2_PROFILE_HIGH                 0x00000020
+
+#define HFI_MPEG2_LEVEL_LL                     0x00000001
+#define HFI_MPEG2_LEVEL_ML                     0x00000002
+#define HFI_MPEG2_LEVEL_H14                    0x00000004
+#define HFI_MPEG2_LEVEL_HL                     0x00000008
+
+#define HFI_MPEG4_PROFILE_SIMPLE               0x00000001
+#define HFI_MPEG4_PROFILE_ADVANCEDSIMPLE       0x00000002
+
+#define HFI_MPEG4_LEVEL_0                      0x00000001
+#define HFI_MPEG4_LEVEL_0b                     0x00000002
+#define HFI_MPEG4_LEVEL_1                      0x00000004
+#define HFI_MPEG4_LEVEL_2                      0x00000008
+#define HFI_MPEG4_LEVEL_3                      0x00000010
+#define HFI_MPEG4_LEVEL_4                      0x00000020
+#define HFI_MPEG4_LEVEL_4a                     0x00000040
+#define HFI_MPEG4_LEVEL_5                      0x00000080
+#define HFI_MPEG4_LEVEL_6                      0x00000100
+#define HFI_MPEG4_LEVEL_7                      0x00000200
+#define HFI_MPEG4_LEVEL_8                      0x00000400
+#define HFI_MPEG4_LEVEL_9                      0x00000800
+#define HFI_MPEG4_LEVEL_3b                     0x00001000
+
+#define HFI_VC1_PROFILE_SIMPLE                 0x00000001
+#define HFI_VC1_PROFILE_MAIN                   0x00000002
+#define HFI_VC1_PROFILE_ADVANCED               0x00000004
+
+#define HFI_VC1_LEVEL_LOW                      0x00000001
+#define HFI_VC1_LEVEL_MEDIUM                   0x00000002
+#define HFI_VC1_LEVEL_HIGH                     0x00000004
+#define HFI_VC1_LEVEL_0                                0x00000008
+#define HFI_VC1_LEVEL_1                                0x00000010
+#define HFI_VC1_LEVEL_2                                0x00000020
+#define HFI_VC1_LEVEL_3                                0x00000040
+#define HFI_VC1_LEVEL_4                                0x00000080
+
+#define HFI_VPX_PROFILE_SIMPLE                 0x00000001
+#define HFI_VPX_PROFILE_ADVANCED               0x00000002
+#define HFI_VPX_PROFILE_VERSION_0              0x00000004
+#define HFI_VPX_PROFILE_VERSION_1              0x00000008
+#define HFI_VPX_PROFILE_VERSION_2              0x00000010
+#define HFI_VPX_PROFILE_VERSION_3              0x00000020
+
+#define HFI_DIVX_FORMAT_4                      (HFI_COMMON_BASE + 0x1)
+#define HFI_DIVX_FORMAT_5                      (HFI_COMMON_BASE + 0x2)
+#define HFI_DIVX_FORMAT_6                      (HFI_COMMON_BASE + 0x3)
+
+#define HFI_DIVX_PROFILE_QMOBILE               0x00000001
+#define HFI_DIVX_PROFILE_MOBILE                        0x00000002
+#define HFI_DIVX_PROFILE_MT                    0x00000004
+#define HFI_DIVX_PROFILE_HT                    0x00000008
+#define HFI_DIVX_PROFILE_HD                    0x00000010
+
+#define HFI_HEVC_PROFILE_MAIN                  0x00000001
+#define HFI_HEVC_PROFILE_MAIN10                        0x00000002
+#define HFI_HEVC_PROFILE_MAIN_STILL_PIC                0x00000004
+
+#define HFI_HEVC_LEVEL_1                       0x00000001
+#define HFI_HEVC_LEVEL_2                       0x00000002
+#define HFI_HEVC_LEVEL_21                      0x00000004
+#define HFI_HEVC_LEVEL_3                       0x00000008
+#define HFI_HEVC_LEVEL_31                      0x00000010
+#define HFI_HEVC_LEVEL_4                       0x00000020
+#define HFI_HEVC_LEVEL_41                      0x00000040
+#define HFI_HEVC_LEVEL_5                       0x00000080
+#define HFI_HEVC_LEVEL_51                      0x00000100
+#define HFI_HEVC_LEVEL_52                      0x00000200
+#define HFI_HEVC_LEVEL_6                       0x00000400
+#define HFI_HEVC_LEVEL_61                      0x00000800
+#define HFI_HEVC_LEVEL_62                      0x00001000
+
+#define HFI_HEVC_TIER_MAIN                     0x1
+#define HFI_HEVC_TIER_HIGH0                    0x2
+
+#define HFI_BUFFER_INPUT                       (HFI_COMMON_BASE + 0x1)
+#define HFI_BUFFER_OUTPUT                      (HFI_COMMON_BASE + 0x2)
+#define HFI_BUFFER_OUTPUT2                     (HFI_COMMON_BASE + 0x3)
+#define HFI_BUFFER_INTERNAL_PERSIST            (HFI_COMMON_BASE + 0x4)
+#define HFI_BUFFER_INTERNAL_PERSIST_1          (HFI_COMMON_BASE + 0x5)
+
+#define HFI_VENC_PERFMODE_MAX_QUALITY          0x1
+#define HFI_VENC_PERFMODE_POWER_SAVE           0x2
+
+struct hfi_buffer_info {
+       u32 buffer_addr;
+       u32 extra_data_addr;
+};
+
+#define HFI_PROPERTY_SYS_COMMON_START          \
+       (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x0000)
+#define HFI_PROPERTY_SYS_DEBUG_CONFIG          \
+       (HFI_PROPERTY_SYS_COMMON_START + 0x001)
+#define HFI_PROPERTY_SYS_RESOURCE_OCMEM_REQUIREMENT_INFO       \
+       (HFI_PROPERTY_SYS_COMMON_START + 0x002)
+#define HFI_PROPERTY_SYS_CONFIG_VCODEC_CLKFREQ \
+       (HFI_PROPERTY_SYS_COMMON_START + 0x003)
+#define HFI_PROPERTY_SYS_IDLE_INDICATOR                \
+       (HFI_PROPERTY_SYS_COMMON_START + 0x004)
+#define  HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL       \
+       (HFI_PROPERTY_SYS_COMMON_START + 0x005)
+#define  HFI_PROPERTY_SYS_IMAGE_VERSION                \
+       (HFI_PROPERTY_SYS_COMMON_START + 0x006)
+#define  HFI_PROPERTY_SYS_CONFIG_COVERAGE      \
+       (HFI_PROPERTY_SYS_COMMON_START + 0x007)
+
+#define HFI_PROPERTY_PARAM_COMMON_START                \
+       (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x1000)
+#define HFI_PROPERTY_PARAM_FRAME_SIZE          \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x001)
+#define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO      \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x002)
+#define HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT          \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x003)
+#define HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED       \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x004)
+#define HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT               \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x005)
+#define HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED             \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x006)
+#define HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED                        \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x007)
+#define HFI_PROPERTY_PARAM_PROPERTIES_SUPPORTED                        \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x008)
+#define HFI_PROPERTY_PARAM_CODEC_SUPPORTED                     \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x009)
+#define HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED         \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x00a)
+#define HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT            \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x00b)
+#define HFI_PROPERTY_PARAM_MULTI_VIEW_FORMAT                   \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x00c)
+#define  HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE           \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x00d)
+#define  HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED               \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x00e)
+#define HFI_PROPERTY_PARAM_MVC_BUFFER_LAYOUT                   \
+       (HFI_PROPERTY_PARAM_COMMON_START + 0x00f)
+
+#define HFI_PROPERTY_CONFIG_COMMON_START                               \
+       (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x2000)
+#define HFI_PROPERTY_CONFIG_FRAME_RATE                                 \
+       (HFI_PROPERTY_CONFIG_COMMON_START + 0x001)
+
+#define HFI_PROPERTY_PARAM_VDEC_COMMON_START                           \
+       (HFI_DOMAIN_BASE_VDEC + HFI_ARCH_COMMON_OFFSET + 0x3000)
+#define HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM                           \
+       (HFI_PROPERTY_PARAM_VDEC_COMMON_START + 0x001)
+#define HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR                          \
+       (HFI_PROPERTY_PARAM_VDEC_COMMON_START + 0x002)
+#define HFI_PROPERTY_PARAM_VDEC_NONCP_OUTPUT2                          \
+       (HFI_PROPERTY_PARAM_VDEC_COMMON_START + 0x003)
+
+#define HFI_PROPERTY_CONFIG_VDEC_COMMON_START                          \
+       (HFI_DOMAIN_BASE_VDEC + HFI_ARCH_COMMON_OFFSET + 0x4000)
+
+#define HFI_PROPERTY_PARAM_VENC_COMMON_START                           \
+       (HFI_DOMAIN_BASE_VENC + HFI_ARCH_COMMON_OFFSET + 0x5000)
+#define HFI_PROPERTY_PARAM_VENC_SLICE_DELIVERY_MODE                    \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x001)
+#define HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL                   \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x002)
+#define HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL                   \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x003)
+#define HFI_PROPERTY_PARAM_VENC_RATE_CONTROL                           \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x004)
+#define  HFI_PROPERTY_PARAM_VENC_H264_PICORDER_CNT_TYPE                        \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x005)
+#define HFI_PROPERTY_PARAM_VENC_SESSION_QP                             \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x006)
+#define HFI_PROPERTY_PARAM_VENC_MPEG4_AC_PREDICTION                    \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x007)
+#define  HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE                      \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x008)
+#define HFI_PROPERTY_PARAM_VENC_MPEG4_TIME_RESOLUTION                  \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x009)
+#define HFI_PROPERTY_PARAM_VENC_MPEG4_SHORT_HEADER                     \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x00a)
+#define HFI_PROPERTY_PARAM_VENC_MPEG4_HEADER_EXTENSION                 \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x00b)
+#define  HFI_PROPERTY_PARAM_VENC_OPEN_GOP                              \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x00c)
+#define HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH                          \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x00d)
+#define HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_CONTROL                    \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x00e)
+#define  HFI_PROPERTY_PARAM_VENC_VBV_HRD_BUF_SIZE                      \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x00f)
+#define  HFI_PROPERTY_PARAM_VENC_QUALITY_VS_SPEED                      \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x010)
+#define HFI_PROPERTY_PARAM_VENC_ADVANCED                               \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x012)
+#define  HFI_PROPERTY_PARAM_VENC_H264_SPS_ID                           \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x014)
+#define  HFI_PROPERTY_PARAM_VENC_H264_PPS_ID                           \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x015)
+#define HFI_PROPERTY_PARAM_VENC_H264_GENERATE_AUDNAL                   \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x016)
+#define HFI_PROPERTY_PARAM_VENC_ASPECT_RATIO                           \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x017)
+#define HFI_PROPERTY_PARAM_VENC_NUMREF                                 \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x018)
+#define HFI_PROPERTY_PARAM_VENC_MULTIREF_P                             \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x019)
+#define HFI_PROPERTY_PARAM_VENC_H264_NAL_SVC_EXT                       \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01b)
+#define HFI_PROPERTY_PARAM_VENC_LTRMODE                                        \
+        (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01c)
+#define HFI_PROPERTY_PARAM_VENC_VIDEO_FULL_RANGE                       \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01d)
+#define HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO                   \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01e)
+#define HFI_PROPERTY_PARAM_VENC_VC1_PERF_CFG                           \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01f)
+#define  HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES                      \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x020)
+#define HFI_PROPERTY_PARAM_VENC_H264_VUI_BITSTREAM_RESTRC              \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x021)
+#define HFI_PROPERTY_PARAM_VENC_PRESERVE_TEXT_QUALITY                  \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x023)
+#define HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER               \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x026)
+#define HFI_PROPERTY_PARAM_VENC_DISABLE_RC_TIMESTAMP                   \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x027)
+#define HFI_PROPERTY_PARAM_VENC_INITIAL_QP                             \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x028)
+#define HFI_PROPERTY_PARAM_VENC_VPX_ERROR_RESILIENCE_MODE              \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x029)
+#define HFI_PROPERTY_PARAM_VENC_HIER_B_MAX_NUM_ENH_LAYER               \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x02c)
+#define  HFI_PROPERTY_PARAM_VENC_HIER_P_HYBRID_MODE                    \
+       (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x02f)
+
+#define HFI_PROPERTY_CONFIG_VENC_COMMON_START                          \
+       (HFI_DOMAIN_BASE_VENC + HFI_ARCH_COMMON_OFFSET + 0x6000)
+#define HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE                                \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x001)
+#define HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD                            \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x002)
+#define HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD                          \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x003)
+#define HFI_PROPERTY_CONFIG_VENC_REQUEST_SYNC_FRAME                    \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x004)
+#define  HFI_PROPERTY_CONFIG_VENC_SLICE_SIZE                           \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x005)
+#define HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE                           \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x007)
+
+#define HFI_PROPERTY_PARAM_VPE_COMMON_START                            \
+       (HFI_DOMAIN_BASE_VPE + HFI_ARCH_COMMON_OFFSET + 0x7000)
+#define  HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER           \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x008)
+#define  HFI_PROPERTY_CONFIG_VENC_MARKLTRFRAME                         \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x009)
+#define  HFI_PROPERTY_CONFIG_VENC_USELTRFRAME                          \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x00a)
+#define  HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER                     \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x00b)
+#define  HFI_PROPERTY_CONFIG_VENC_LTRPERIOD                            \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x00c)
+#define  HFI_PROPERTY_CONFIG_VENC_PERF_MODE                            \
+       (HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x00e)
+
+#define HFI_PROPERTY_CONFIG_VPE_COMMON_START                           \
+       (HFI_DOMAIN_BASE_VPE + HFI_ARCH_COMMON_OFFSET + 0x8000)
+#define HFI_PROPERTY_CONFIG_VPE_DEINTERLACE                            \
+       (HFI_PROPERTY_CONFIG_VPE_COMMON_START + 0x001)
+#define HFI_PROPERTY_CONFIG_VPE_OPERATIONS                             \
+       (HFI_PROPERTY_CONFIG_VPE_COMMON_START + 0x002)
+
+struct hfi_bitrate {
+       u32 bit_rate;
+       u32 layer_id;
+};
+
+#define HFI_CAPABILITY_FRAME_WIDTH                     (HFI_COMMON_BASE + 0x1)
+#define HFI_CAPABILITY_FRAME_HEIGHT                    (HFI_COMMON_BASE + 0x2)
+#define HFI_CAPABILITY_MBS_PER_FRAME                   (HFI_COMMON_BASE + 0x3)
+#define HFI_CAPABILITY_MBS_PER_SECOND                  (HFI_COMMON_BASE + 0x4)
+#define HFI_CAPABILITY_FRAMERATE                       (HFI_COMMON_BASE + 0x5)
+#define HFI_CAPABILITY_SCALE_X                         (HFI_COMMON_BASE + 0x6)
+#define HFI_CAPABILITY_SCALE_Y                         (HFI_COMMON_BASE + 0x7)
+#define HFI_CAPABILITY_BITRATE                         (HFI_COMMON_BASE + 0x8)
+#define HFI_CAPABILITY_BFRAME                          (HFI_COMMON_BASE + 0x9)
+#define HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS           (HFI_COMMON_BASE + 0x10)
+#define HFI_CAPABILITY_ENC_LTR_COUNT                   (HFI_COMMON_BASE + 0x11)
+#define HFI_CAPABILITY_CP_OUTPUT2_THRESH               (HFI_COMMON_BASE + 0x12)
+#define HFI_CAPABILITY_HIER_P_HYBRID_NUM_ENH_LAYERS    (HFI_COMMON_BASE + 0x15)
+
+struct hfi_capability_supported {
+       u32 capability_type;
+       u32 min;
+       u32 max;
+       u32 step_size;
+};
+
+struct hfi_capability_supported_info {
+       u32 num_capabilities;
+       struct hfi_capability_supported rg_data[1];
+};
+
+#define HFI_DEBUG_MSG_LOW      0x00000001
+#define HFI_DEBUG_MSG_MEDIUM   0x00000002
+#define HFI_DEBUG_MSG_HIGH     0x00000004
+#define HFI_DEBUG_MSG_ERROR    0x00000008
+#define HFI_DEBUG_MSG_FATAL    0x00000010
+#define HFI_DEBUG_MSG_PERF     0x00000020
+
+#define HFI_DEBUG_MODE_QUEUE   0x00000001
+#define HFI_DEBUG_MODE_QDSS    0x00000002
+
+struct hfi_debug_config {
+       u32 debug_config;
+       u32 debug_mode;
+};
+
+struct hfi_enable {
+       int enable;
+};
+
+#define HFI_H264_DB_MODE_DISABLE               (HFI_COMMON_BASE + 0x1)
+#define HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY   (HFI_COMMON_BASE + 0x2)
+#define HFI_H264_DB_MODE_ALL_BOUNDARY          (HFI_COMMON_BASE + 0x3)
+
+struct hfi_h264_db_control {
+       u32 mode;
+       int slice_alpha_offset;
+       int slice_beta_offset;
+};
+
+#define HFI_H264_ENTROPY_CAVLC                 (HFI_COMMON_BASE + 0x1)
+#define HFI_H264_ENTROPY_CABAC                 (HFI_COMMON_BASE + 0x2)
+
+#define HFI_H264_CABAC_MODEL_0                 (HFI_COMMON_BASE + 0x1)
+#define HFI_H264_CABAC_MODEL_1                 (HFI_COMMON_BASE + 0x2)
+#define HFI_H264_CABAC_MODEL_2                 (HFI_COMMON_BASE + 0x3)
+
+struct hfi_h264_entropy_control {
+       u32 entropy_mode;
+       u32 cabac_model;
+};
+
+struct hfi_frame_rate {
+       u32 buffer_type;
+       u32 frame_rate;
+};
+
+#define HFI_INTRA_REFRESH_NONE                 (HFI_COMMON_BASE + 0x1)
+#define HFI_INTRA_REFRESH_CYCLIC               (HFI_COMMON_BASE + 0x2)
+#define HFI_INTRA_REFRESH_ADAPTIVE             (HFI_COMMON_BASE + 0x3)
+#define HFI_INTRA_REFRESH_CYCLIC_ADAPTIVE      (HFI_COMMON_BASE + 0x4)
+#define HFI_INTRA_REFRESH_RANDOM               (HFI_COMMON_BASE + 0x5)
+
+struct hfi_intra_refresh {
+       u32 mode;
+       u32 air_mbs;
+       u32 air_ref;
+       u32 cir_mbs;
+};
+
+struct hfi_idr_period {
+       u32 idr_period;
+};
+
+struct hfi_operations_type {
+       u32 rotation;
+       u32 flip;
+};
+
+struct hfi_max_num_b_frames {
+       u32 max_num_b_frames;
+};
+
+struct hfi_vc1e_perf_cfg_type {
+       u32 search_range_x_subsampled[3];
+       u32 search_range_y_subsampled[3];
+};
+
+struct hfi_conceal_color {
+       u32 conceal_color;
+};
+
+struct hfi_intra_period {
+       u32 pframes;
+       u32 bframes;
+};
+
+struct hfi_mpeg4_header_extension {
+       u32 header_extension;
+};
+
+struct hfi_mpeg4_time_resolution {
+       u32 time_increment_resolution;
+};
+
+struct hfi_multi_stream {
+       u32 buffer_type;
+       u32 enable;
+       u32 width;
+       u32 height;
+};
+
+struct hfi_multi_view_format {
+       u32 views;
+       u32 rg_view_order[1];
+};
+
+#define HFI_MULTI_SLICE_OFF                    (HFI_COMMON_BASE + 0x1)
+#define HFI_MULTI_SLICE_BY_MB_COUNT            (HFI_COMMON_BASE + 0x2)
+#define HFI_MULTI_SLICE_BY_BYTE_COUNT          (HFI_COMMON_BASE + 0x3)
+#define HFI_MULTI_SLICE_GOB                    (HFI_COMMON_BASE + 0x4)
+
+struct hfi_multi_slice_control {
+       u32 multi_slice;
+       u32 slice_size;
+};
+
+#define HFI_NAL_FORMAT_STARTCODES              0x00000001
+#define HFI_NAL_FORMAT_ONE_NAL_PER_BUFFER      0x00000002
+#define HFI_NAL_FORMAT_ONE_BYTE_LENGTH         0x00000004
+#define HFI_NAL_FORMAT_TWO_BYTE_LENGTH         0x00000008
+#define HFI_NAL_FORMAT_FOUR_BYTE_LENGTH                0x00000010
+
+struct hfi_nal_stream_format_supported {
+       u32 nal_stream_format_supported;
+};
+
+struct hfi_nal_stream_format_select {
+       u32 nal_stream_format_select;
+};
+#define HFI_PICTURE_TYPE_I                     0x01
+#define HFI_PICTURE_TYPE_P                     0x02
+#define HFI_PICTURE_TYPE_B                     0x04
+#define HFI_PICTURE_TYPE_IDR                   0x08
+
+struct hfi_profile_level {
+       u32 profile;
+       u32 level;
+};
+
+struct hfi_profile_level_supported {
+       u32 profile_count;
+       struct hfi_profile_level rg_profile_level[1];
+};
+
+struct hfi_quality_vs_speed {
+       u32 quality_vs_speed;
+};
+
+struct hfi_quantization {
+       u32 qp_i;
+       u32 qp_p;
+       u32 qp_b;
+       u32 layer_id;
+};
+
+struct hfi_initial_quantization {
+       u32 qp_i;
+       u32 qp_p;
+       u32 qp_b;
+       u32 init_qp_enable;
+};
+
+struct hfi_quantization_range {
+       u32 min_qp;
+       u32 max_qp;
+       u32 layer_id;
+};
+
+#define HFI_LTR_MODE_DISABLE   0x0
+#define HFI_LTR_MODE_MANUAL    0x1
+#define HFI_LTR_MODE_PERIODIC  0x2
+
+struct hfi_ltr_mode {
+       u32 ltr_mode;
+       u32 ltr_count;
+       u32 trust_mode;
+};
+
+struct hfi_ltr_use {
+       u32 ref_ltr;
+       u32 use_constrnt;
+       u32 frames;
+};
+
+struct hfi_ltr_mark {
+       u32 mark_frame;
+};
+
+struct hfi_frame_size {
+       u32 buffer_type;
+       u32 width;
+       u32 height;
+};
+
+struct hfi_h264_vui_timing_info {
+       u32 enable;
+       u32 fixed_frame_rate;
+       u32 time_scale;
+};
+
+/* Base Offset for UBWC color formats  */
+#define HFI_COLOR_FORMAT_UBWC_BASE             0x8000
+/* Base Offset for 10-bit color formats */
+#define HFI_COLOR_FORMAT_10_BIT_BASE           0x4000
+
+#define HFI_COLOR_FORMAT_MONOCHROME            (HFI_COMMON_BASE + 0x1)
+#define HFI_COLOR_FORMAT_NV12                  (HFI_COMMON_BASE + 0x2)
+#define HFI_COLOR_FORMAT_NV21                  (HFI_COMMON_BASE + 0x3)
+#define HFI_COLOR_FORMAT_NV12_4x4TILE          (HFI_COMMON_BASE + 0x4)
+#define HFI_COLOR_FORMAT_NV21_4x4TILE          (HFI_COMMON_BASE + 0x5)
+#define HFI_COLOR_FORMAT_YUYV                  (HFI_COMMON_BASE + 0x6)
+#define HFI_COLOR_FORMAT_YVYU                  (HFI_COMMON_BASE + 0x7)
+#define HFI_COLOR_FORMAT_UYVY                  (HFI_COMMON_BASE + 0x8)
+#define HFI_COLOR_FORMAT_VYUY                  (HFI_COMMON_BASE + 0x9)
+#define HFI_COLOR_FORMAT_RGB565                        (HFI_COMMON_BASE + 0xA)
+#define HFI_COLOR_FORMAT_BGR565                        (HFI_COMMON_BASE + 0xB)
+#define HFI_COLOR_FORMAT_RGB888                        (HFI_COMMON_BASE + 0xC)
+#define HFI_COLOR_FORMAT_BGR888                        (HFI_COMMON_BASE + 0xD)
+#define HFI_COLOR_FORMAT_YUV444                        (HFI_COMMON_BASE + 0xE)
+#define HFI_COLOR_FORMAT_RGBA8888              (HFI_COMMON_BASE + 0x10)
+
+#define HFI_COLOR_FORMAT_YUV420_TP10   \
+       (HFI_COLOR_FORMAT_10_BIT_BASE + HFI_COLOR_FORMAT_NV12)
+
+#define HFI_COLOR_FORMAT_NV12_UBWC     \
+       (HFI_COLOR_FORMAT_UBWC_BASE + HFI_COLOR_FORMAT_NV12)
+
+#define HFI_COLOR_FORMAT_YUV420_TP10_UBWC      \
+       (HFI_COLOR_FORMAT_UBWC_BASE + HFI_COLOR_FORMAT_YUV420_TP10)
+
+#define HFI_COLOR_FORMAT_RGBA8888_UBWC \
+       (HFI_COLOR_FORMAT_UBWC_BASE + HFI_COLOR_FORMAT_RGBA8888)
+
+#define HFI_MAX_MATRIX_COEFFS  9
+#define HFI_MAX_BIAS_COEFFS    3
+#define HFI_MAX_LIMIT_COEFFS   6
+
+struct hfi_uncompressed_format_select {
+       u32 buffer_type;
+       u32 format;
+};
+
+struct hfi_uncompressed_format_supported {
+       u32 buffer_type;
+       u32 format_entries;
+       u32 rg_format_info[1];
+};
+
+struct hfi_uncompressed_plane_actual {
+       int actual_stride;
+       u32 actual_plane_buffer_height;
+};
+
+struct hfi_uncompressed_plane_actual_info {
+       u32 buffer_type;
+       u32 num_planes;
+       struct hfi_uncompressed_plane_actual rg_plane_format[1];
+};
+
+struct hfi_uncompressed_plane_constraints {
+       u32 stride_multiples;
+       u32 max_stride;
+       u32 min_plane_buffer_height_multiple;
+       u32 buffer_alignment;
+};
+
+struct hfi_uncompressed_plane_info {
+       u32 format;
+       u32 num_planes;
+       struct hfi_uncompressed_plane_constraints rg_plane_format[1];
+};
+
+struct hfi_codec_supported {
+       u32 decoder_codec_supported;
+       u32 encoder_codec_supported;
+};
+
+struct hfi_properties_supported {
+       u32 num_properties;
+       u32 rg_properties[1];
+};
+
+struct hfi_vpe_color_space_conversion {
+       u32 csc_matrix[HFI_MAX_MATRIX_COEFFS];
+       u32 csc_bias[HFI_MAX_BIAS_COEFFS];
+       u32 csc_limit[HFI_MAX_LIMIT_COEFFS];
+};
+
+#define HFI_ROTATE_NONE                        (HFI_COMMON_BASE + 0x1)
+#define HFI_ROTATE_90                  (HFI_COMMON_BASE + 0x2)
+#define HFI_ROTATE_180                 (HFI_COMMON_BASE + 0x3)
+#define HFI_ROTATE_270                 (HFI_COMMON_BASE + 0x4)
+
+#define HFI_FLIP_NONE                  (HFI_COMMON_BASE + 0x1)
+#define HFI_FLIP_HORIZONTAL            (HFI_COMMON_BASE + 0x2)
+#define HFI_FLIP_VERTICAL              (HFI_COMMON_BASE + 0x3)
+
+struct hfi_operations {
+       u32 rotate;
+       u32 flip;
+};
+
+#define HFI_RESOURCE_OCMEM     0x00000001
+
+struct hfi_resource_ocmem {
+       u32 size;
+       u32 mem;
+};
+
+struct hfi_resource_ocmem_requirement {
+       u32 session_domain;
+       u32 width;
+       u32 height;
+       u32 size;
+};
+
+struct hfi_resource_ocmem_requirement_info {
+       u32 num_entries;
+       struct hfi_resource_ocmem_requirement rg_requirements[1];
+};
+
+struct hfi_property_sys_image_version_info_type {
+       u32 string_size;
+       u8  str_image_version[1];
+};
+
+struct hfi_venc_config_advanced {
+       u8 pipe2d;
+       u8 hw_mode;
+       u8 low_delay_enforce;
+       u8 worker_vppsg_delay;
+       int close_gop;
+       int h264_constrain_intra_pred;
+       int h264_transform_8x8_flag;
+       int mpeg4_qpel_enable;
+       int multi_refp_en;
+       int qmatrix_en;
+       u8 vpp_info_packet_mode;
+       u8 ref_tile_mode;
+       u8 bitstream_flush_mode;
+       u32 vppsg_vspap_fb_sync_delay;
+       u32 rc_initial_delay;
+       u32 peak_bitrate_constraint;
+       u32 ds_display_frame_width;
+       u32 ds_display_frame_height;
+       u32 perf_tune_param_ptr;
+       u32 input_x_offset;
+       u32 input_y_offset;
+       u32 input_roi_width;
+       u32 input_roi_height;
+       u32 vsp_fifo_dma_sel;
+       u32 h264_num_ref_frames;
+};
+
+struct hfi_vbv_hrd_bufsize {
+       u32 buffer_size;
+};
+
+struct hfi_codec_mask_supported {
+       u32 codecs;
+       u32 video_domains;
+};
+
+struct hfi_seq_header_info {
+       u32 max_hader_len;
+};
+struct hfi_aspect_ratio {
+       u32 aspect_width;
+       u32 aspect_height;
+};
+#define HFI_MVC_BUFFER_LAYOUT_TOP_BOTTOM       0
+#define HFI_MVC_BUFFER_LAYOUT_SIDEBYSIDE       1
+#define HFI_MVC_BUFFER_LAYOUT_SEQ              2
+
+struct hfi_mvc_buffer_layout_descp_type {
+       u32 layout_type;
+       u32 bright_view_first;
+       u32 ngap;
+};
+
+#define HFI_CMD_SYS_COMMON_START       (HFI_DOMAIN_BASE_COMMON + \
+                                        HFI_ARCH_COMMON_OFFSET + \
+                                        HFI_CMD_START_OFFSET + 0x0000)
+#define HFI_CMD_SYS_INIT               (HFI_CMD_SYS_COMMON_START + 0x001)
+#define HFI_CMD_SYS_PC_PREP            (HFI_CMD_SYS_COMMON_START + 0x002)
+#define HFI_CMD_SYS_SET_RESOURCE       (HFI_CMD_SYS_COMMON_START + 0x003)
+#define HFI_CMD_SYS_RELEASE_RESOURCE   (HFI_CMD_SYS_COMMON_START + 0x004)
+#define HFI_CMD_SYS_SET_PROPERTY       (HFI_CMD_SYS_COMMON_START + 0x005)
+#define HFI_CMD_SYS_GET_PROPERTY       (HFI_CMD_SYS_COMMON_START + 0x006)
+#define HFI_CMD_SYS_SESSION_INIT       (HFI_CMD_SYS_COMMON_START + 0x007)
+#define HFI_CMD_SYS_SESSION_END                (HFI_CMD_SYS_COMMON_START + 0x008)
+#define HFI_CMD_SYS_SET_BUFFERS                (HFI_CMD_SYS_COMMON_START + 0x009)
+#define HFI_CMD_SYS_TEST_START         (HFI_CMD_SYS_COMMON_START + 0x100)
+
+#define HFI_CMD_SESSION_COMMON_START   (HFI_DOMAIN_BASE_COMMON + \
+                                        HFI_ARCH_COMMON_OFFSET + \
+                                        HFI_CMD_START_OFFSET + 0x1000)
+#define HFI_CMD_SESSION_SET_PROPERTY   (HFI_CMD_SESSION_COMMON_START + 0x001)
+#define HFI_CMD_SESSION_SET_BUFFERS    (HFI_CMD_SESSION_COMMON_START + 0x002)
+#define HFI_CMD_SESSION_GET_SEQUENCE_HEADER \
+                                       (HFI_CMD_SESSION_COMMON_START + 0x003)
+
+#define HFI_MSG_SYS_COMMON_START       (HFI_DOMAIN_BASE_COMMON + \
+                                        HFI_ARCH_COMMON_OFFSET + \
+                                        HFI_MSG_START_OFFSET + 0x0000)
+#define HFI_MSG_SYS_INIT_DONE          (HFI_MSG_SYS_COMMON_START + 0x1)
+#define HFI_MSG_SYS_PC_PREP_DONE       (HFI_MSG_SYS_COMMON_START + 0x2)
+#define HFI_MSG_SYS_RELEASE_RESOURCE   (HFI_MSG_SYS_COMMON_START + 0x3)
+#define HFI_MSG_SYS_DEBUG              (HFI_MSG_SYS_COMMON_START + 0x4)
+#define HFI_MSG_SYS_SESSION_INIT_DONE  (HFI_MSG_SYS_COMMON_START + 0x6)
+#define HFI_MSG_SYS_SESSION_END_DONE   (HFI_MSG_SYS_COMMON_START + 0x7)
+#define HFI_MSG_SYS_IDLE               (HFI_MSG_SYS_COMMON_START + 0x8)
+#define HFI_MSG_SYS_COV                 (HFI_MSG_SYS_COMMON_START + 0x9)
+#define HFI_MSG_SYS_PROPERTY_INFO      (HFI_MSG_SYS_COMMON_START + 0xA)
+
+#define HFI_MSG_SESSION_COMMON_START   (HFI_DOMAIN_BASE_COMMON + \
+                                        HFI_ARCH_COMMON_OFFSET + \
+                                        HFI_MSG_START_OFFSET + 0x1000)
+#define HFI_MSG_EVENT_NOTIFY           (HFI_MSG_SESSION_COMMON_START + 0x1)
+#define HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE               \
+                                       (HFI_MSG_SESSION_COMMON_START + 0x2)
+
+#define HFI_CMD_SYS_TEST_SSR           (HFI_CMD_SYS_TEST_START + 0x1)
+#define HFI_TEST_SSR_SW_ERR_FATAL      0x1
+#define HFI_TEST_SSR_SW_DIV_BY_ZERO    0x2
+#define HFI_TEST_SSR_HW_WDOG_IRQ       0x3
+
+struct vidc_hal_cmd_pkt_hdr {
+       u32 size;
+       u32 packet_type;
+};
+
+struct vidc_hal_msg_pkt_hdr {
+       u32 size;
+       u32 packet;
+};
+
+struct vidc_hal_session_cmd_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+};
+
+struct hfi_sys_init_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 arch_type;
+};
+
+struct hfi_sys_pc_prep_pkt {
+       u32 size;
+       u32 packet_type;
+};
+
+struct hfi_sys_set_resource_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 resource_handle;
+       u32 resource_type;
+       u32 rg_resource_data[1];
+};
+
+struct hfi_sys_release_resource_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 resource_type;
+       u32 resource_handle;
+};
+
+struct hfi_sys_set_property_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 num_properties;
+       u32 rg_property_data[1];
+};
+
+struct hfi_sys_get_property_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 num_properties;
+       u32 rg_property_data[1];
+};
+
+struct hfi_session_init_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 session_domain;
+       u32 session_codec;
+};
+
+struct hfi_session_end_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+};
+
+struct hfi_sys_set_buffers_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 buffer_type;
+       u32 buffer_size;
+       u32 num_buffers;
+       u32 rg_buffer_addr[1];
+};
+
+struct hfi_session_set_property_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 num_properties;
+       u32 rg_property_data[0];
+};
+
+struct hfi_session_set_buffers_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 buffer_type;
+       u32 buffer_size;
+       u32 extra_data_size;
+       u32 min_buffer_size;
+       u32 num_buffers;
+       u32 rg_buffer_info[1];
+};
+
+struct hfi_session_get_sequence_header_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 buffer_len;
+       u32 packet_buffer;
+};
+
+struct hfi_msg_event_notify_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 event_id;
+       u32 event_data1;
+       u32 event_data2;
+       u32 rg_ext_event_data[1];
+};
+
+struct hfi_msg_event_release_buffer_ref_pkt {
+       u32 packet_buffer;
+       u32 extra_data_buffer;
+       u32 output_tag;
+};
+
+struct hfi_msg_sys_init_done_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 error_type;
+       u32 num_properties;
+       u32 rg_property_data[1];
+};
+
+struct hfi_msg_sys_pc_prep_done_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 error_type;
+};
+
+struct hfi_msg_sys_release_resource_done_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 resource_handle;
+       u32 error_type;
+};
+
+struct hfi_msg_session_init_done_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+       u32 num_properties;
+       u32 rg_property_data[1];
+};
+
+struct hfi_msg_session_end_done_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+};
+
+struct hfi_msg_session_get_sequence_hdr_done_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 session_id;
+       u32 error_type;
+       u32 header_len;
+       u32 sequence_header;
+};
+
+struct hfi_msg_sys_debug_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 msg_type;
+       u32 msg_size;
+       u32 time_stamp_hi;
+       u32 time_stamp_lo;
+       u8 rg_msg_data[1];
+};
+
+struct hfi_msg_sys_coverage_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 msg_size;
+       u32 time_stamp_hi;
+       u32 time_stamp_lo;
+       u8 rg_msg_data[1];
+};
+
+struct hfi_sfr {
+       u32 buf_size;
+       u8 rg_data[1];
+};
+
+struct hfi_sys_test_ssr_pkt {
+       u32 size;
+       u32 packet_type;
+       u32 trigger_type;
+};
+#endif
diff --git a/drivers/media/platform/msm/vidc/msm_hfi_interface.h b/drivers/media/platform/msm/vidc/msm_hfi_interface.h
new file mode 100644 (file)
index 0000000..6b3106e
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MSM_HFI_INTERFACE_H_
+#define _MSM_HFI_INTERFACE_H_
+
+struct vidc_inst;
+struct vidc_buffer_addr_info;
+
+int hfi_core_init(struct vidc_core *core);
+int hfi_core_deinit(struct vidc_core *core);
+
+int hfi_session_init(struct vidc_inst *inst, u32 pixfmt);
+int hfi_session_deinit(struct vidc_inst *inst);
+int hfi_session_start(struct vidc_inst *inst);
+int hfi_session_stop(struct vidc_inst *inst);
+int hfi_session_abort(struct vidc_inst *inst);
+int hfi_session_load_res(struct vidc_inst *inst);
+int hfi_session_release_res(struct vidc_inst *inst);
+int hfi_session_flush(struct vidc_inst *inst);
+int hfi_session_release_buffers(struct vidc_inst *inst,
+                               struct vidc_buffer_addr_info *bai);
+int hfi_session_set_property(struct vidc_inst *inst, enum hal_property ptype,
+                            void *pdata);
+int hfi_session_get_property(struct vidc_inst *inst, enum hal_property ptype,
+                            union hal_get_property *hprop);
+void hfi_session_clean(struct vidc_inst *inst);
+
+#endif /* _MSM_HFI_INTERFACE_H_ */
\ No newline at end of file
diff --git a/drivers/media/platform/msm/vidc/msm_internal-buffers.c b/drivers/media/platform/msm/vidc/msm_internal-buffers.c
new file mode 100644 (file)
index 0000000..4c8c806
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_smem.h"
+#include "msm_internal-buffers.h"
+#include "msm_vidc_debug.h"
+#include "msm_hfi_interface.h"
+
+static enum hal_buffer
+scratch_buf_sufficient(struct vidc_inst *inst, enum hal_buffer buffer_type)
+{
+       struct hal_buffer_requirements *bufreq;
+       struct vidc_internal_buf *buf;
+       int count = 0;
+
+       bufreq = get_buff_req_buffer(inst, buffer_type);
+       if (!bufreq)
+               goto not_sufficient;
+
+       /* Check if current scratch buffers are sufficient */
+       mutex_lock(&inst->scratchbufs.lock);
+       list_for_each_entry(buf, &inst->scratchbufs.list, list) {
+               if (!buf->smem) {
+                       dprintk(VIDC_ERR, "%s: invalid buf handle\n", __func__);
+                       mutex_unlock(&inst->scratchbufs.lock);
+                       goto not_sufficient;
+               }
+
+               if (buf->type == buffer_type &&
+                   buf->smem->size >= bufreq->size)
+                       count++;
+       }
+       mutex_unlock(&inst->scratchbufs.lock);
+
+       if (count != bufreq->count_actual)
+               goto not_sufficient;
+
+       dprintk(VIDC_DBG,
+               "Existing scratch buffer is sufficient for buffer type %#x\n",
+               buffer_type);
+
+       return buffer_type;
+
+not_sufficient:
+       return HAL_BUFFER_NONE;
+}
+
+static int set_internal_buf_on_fw(struct vidc_inst *inst,
+                                 enum hal_buffer buffer_type,
+                                 struct smem *mem, bool reuse)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       struct vidc_buffer_addr_info bai = {0};
+       int ret;
+
+       ret = smem_cache_operations(inst->mem_client, mem, SMEM_CACHE_CLEAN);
+       if (ret)
+               dprintk(VIDC_WARN,
+                       "Failed to clean cache. May cause undefined behavior\n");
+
+       bai.buffer_size = mem->size;
+       bai.buffer_type = buffer_type;
+       bai.num_buffers = 1;
+       bai.device_addr = mem->da;
+
+       ret = call_hfi_op(hdev, session_set_buffers, inst->session, &bai);
+       if (ret) {
+               dprintk(VIDC_ERR, "session_set_buffers failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int alloc_and_set(struct vidc_inst *inst,
+                        struct hal_buffer_requirements *bufreq,
+                        struct vidc_list *buf_list)
+{
+       struct smem *smem;
+       struct vidc_internal_buf *buf;
+       u32 smem_flags = 0;
+       unsigned int i;
+       int ret = 0;
+
+       if (!bufreq->size)
+               return 0;
+
+       if (inst->flags & VIDC_SECURE)
+               smem_flags |= SMEM_SECURE;
+
+       for (i = 0; i < bufreq->count_actual; i++) {
+
+               smem = smem_alloc(inst->mem_client, bufreq->size, 1, smem_flags,
+                                 bufreq->type, 0);
+               if (IS_ERR(smem)) {
+                       ret = PTR_ERR(smem);
+                       goto err_no_mem;
+               }
+
+               buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+               if (!buf) {
+                       ret = -ENOMEM;
+                       goto fail_kzalloc;
+               }
+
+               buf->smem = smem;
+               buf->type = bufreq->type;
+
+               ret = set_internal_buf_on_fw(inst, bufreq->type, smem, false);
+               if (ret)
+                       goto fail_set_buffers;
+
+               mutex_lock(&buf_list->lock);
+               list_add_tail(&buf->list, &buf_list->list);
+               mutex_unlock(&buf_list->lock);
+       }
+
+       return ret;
+
+fail_set_buffers:
+       kfree(buf);
+fail_kzalloc:
+       smem_free(inst->mem_client, smem);
+err_no_mem:
+       return ret;
+}
+
+static bool
+reuse_scratch_buffer(struct vidc_inst *inst, enum hal_buffer buffer_type)
+{
+       struct vidc_internal_buf *buf;
+       bool reused = false;
+       int ret = 0;
+
+       mutex_lock(&inst->scratchbufs.lock);
+       list_for_each_entry(buf, &inst->scratchbufs.list, list) {
+               if (!buf->smem) {
+                       reused = false;
+                       break;
+               }
+
+               if (buf->type != buffer_type)
+                       continue;
+
+               ret = set_internal_buf_on_fw(inst, buffer_type, buf->smem,
+                                            true);
+               if (ret) {
+                       dprintk(VIDC_ERR,
+                               "%s: session_set_buffers failed\n", __func__);
+                       reused = false;
+                       break;
+               }
+
+               reused = true;
+       }
+       mutex_unlock(&inst->scratchbufs.lock);
+
+       return reused;
+}
+
+static int set_scratch_buffer(struct vidc_inst *inst, enum hal_buffer type)
+{
+       struct hal_buffer_requirements *bufreq;
+
+       bufreq = get_buff_req_buffer(inst, type);
+       if (!bufreq)
+               return 0;
+
+       dprintk(VIDC_DBG, "%s: num:%d, size:%d\n", __func__,
+               bufreq->count_actual, bufreq->size);
+
+       /*
+        * Try reusing existing scratch buffers first.
+        * If it's not possible to reuse, allocate new buffers.
+        */
+       if (reuse_scratch_buffer(inst, type))
+               return 0;
+
+       return alloc_and_set(inst, bufreq, &inst->scratchbufs);
+}
+
+static int set_persist_buffer(struct vidc_inst *inst, enum hal_buffer type)
+{
+       struct hal_buffer_requirements *bufreq;
+
+       bufreq = get_buff_req_buffer(inst, type);
+       if (!bufreq)
+               return 0;
+
+       dprintk(VIDC_DBG, "persist: num = %d, size = %d\n",
+               bufreq->count_actual, bufreq->size);
+
+       mutex_lock(&inst->persistbufs.lock);
+       if (!list_empty(&inst->persistbufs.list)) {
+               mutex_unlock(&inst->persistbufs.lock);
+               return 0;
+       }
+       mutex_unlock(&inst->persistbufs.lock);
+
+       return alloc_and_set(inst, bufreq, &inst->persistbufs);
+}
+
+int release_scratch_buffers(struct vidc_inst *inst, bool reuse)
+{
+       struct smem *smem;
+       struct vidc_internal_buf *buf, *dummy;
+       struct vidc_buffer_addr_info bai = {0};
+       enum hal_buffer sufficiency = HAL_BUFFER_NONE;
+       int ret = 0;
+
+       if (reuse) {
+               sufficiency |= scratch_buf_sufficient(inst,
+                                       HAL_BUFFER_INTERNAL_SCRATCH);
+
+               sufficiency |= scratch_buf_sufficient(inst,
+                                       HAL_BUFFER_INTERNAL_SCRATCH_1);
+
+               sufficiency |= scratch_buf_sufficient(inst,
+                                       HAL_BUFFER_INTERNAL_SCRATCH_2);
+       }
+
+       mutex_lock(&inst->scratchbufs.lock);
+       list_for_each_entry_safe(buf, dummy, &inst->scratchbufs.list, list) {
+               if (!buf->smem) {
+                       ret = -EINVAL;
+                       goto exit;
+               }
+
+               smem = buf->smem;
+               bai.buffer_size = smem->size;
+               bai.buffer_type = buf->type;
+               bai.num_buffers = 1;
+               bai.device_addr = smem->da;
+               bai.response_required = true;
+
+               mutex_unlock(&inst->scratchbufs.lock);
+               ret = hfi_session_release_buffers(inst, &bai);
+               mutex_lock(&inst->scratchbufs.lock);
+
+               /* If scratch buffers can be reused, do not free the buffers */
+               if (sufficiency & buf->type)
+                       continue;
+
+               list_del(&buf->list);
+               mutex_unlock(&inst->scratchbufs.lock);
+               smem_free(inst->mem_client, buf->smem);
+               mutex_lock(&inst->scratchbufs.lock);
+               kfree(buf);
+       }
+
+exit:
+       mutex_unlock(&inst->scratchbufs.lock);
+       return ret;
+}
+
+int release_persist_buffers(struct vidc_inst *inst)
+{
+       struct smem *smem;
+       struct list_head *ptr, *next;
+       struct vidc_internal_buf *buf;
+       struct vidc_buffer_addr_info bai = {0};
+       int ret = 0;
+
+       mutex_lock(&inst->persistbufs.lock);
+       list_for_each_safe(ptr, next, &inst->persistbufs.list) {
+               buf = list_entry(ptr, struct vidc_internal_buf, list);
+
+               smem = buf->smem;
+               bai.buffer_size = smem->size;
+               bai.buffer_type = buf->type;
+               bai.num_buffers = 1;
+               bai.device_addr = smem->da;
+               bai.response_required = true;
+
+               mutex_unlock(&inst->persistbufs.lock);
+               ret = hfi_session_release_buffers(inst, &bai);
+               mutex_lock(&inst->persistbufs.lock);
+
+               list_del(&buf->list);
+               mutex_unlock(&inst->persistbufs.lock);
+               smem_free(inst->mem_client, buf->smem);
+               mutex_lock(&inst->persistbufs.lock);
+               kfree(buf);
+       }
+       mutex_unlock(&inst->persistbufs.lock);
+
+       return ret;
+}
+
+int set_scratch_buffers(struct vidc_inst *inst)
+{
+       int ret;
+
+       ret = release_scratch_buffers(inst, true);
+       if (ret)
+               dprintk(VIDC_WARN, "Failed to release scratch buffers\n");
+
+       ret = set_scratch_buffer(inst, HAL_BUFFER_INTERNAL_SCRATCH);
+       if (ret)
+               goto error;
+
+       ret = set_scratch_buffer(inst, HAL_BUFFER_INTERNAL_SCRATCH_1);
+       if (ret)
+               goto error;
+
+       ret = set_scratch_buffer(inst, HAL_BUFFER_INTERNAL_SCRATCH_2);
+       if (ret)
+               goto error;
+
+       return 0;
+error:
+       release_scratch_buffers(inst, false);
+       return ret;
+}
+
+int set_persist_buffers(struct vidc_inst *inst)
+{
+       int ret;
+
+       ret = set_persist_buffer(inst, HAL_BUFFER_INTERNAL_PERSIST);
+       if (ret)
+               goto error;
+
+       ret = set_persist_buffer(inst, HAL_BUFFER_INTERNAL_PERSIST_1);
+       if (ret)
+               goto error;
+
+       return 0;
+
+error:
+       release_persist_buffers(inst);
+       return ret;
+}
diff --git a/drivers/media/platform/msm/vidc/msm_internal-buffers.h b/drivers/media/platform/msm/vidc/msm_internal-buffers.h
new file mode 100644 (file)
index 0000000..e19cc91
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MSM_VIDC_INTERNAL_BUFFERS_H_
+#define _MSM_VIDC_INTERNAL_BUFFERS_H_
+
+#include "msm_vidc_common.h"
+
+int set_scratch_buffers(struct vidc_inst *);
+int set_persist_buffers(struct vidc_inst *);
+int release_persist_buffers(struct vidc_inst *);
+int release_scratch_buffers(struct vidc_inst *, bool);
+
+#endif /* _MSM_VIDC_INTERNAL_BUFFERS_H_ */
diff --git a/drivers/media/platform/msm/vidc/msm_media_info.h b/drivers/media/platform/msm/vidc/msm_media_info.h
new file mode 100644 (file)
index 0000000..5b26be3
--- /dev/null
@@ -0,0 +1,613 @@
+#ifndef __MEDIA_INFO_H__
+#define __MEDIA_INFO_H__
+
+#ifndef MSM_MEDIA_ALIGN
+#define MSM_MEDIA_ALIGN(__sz, __align) (((__sz) + (__align-1)) & (~(__align-1)))
+#endif
+
+#ifndef MSM_MEDIA_ROUNDUP
+#define MSM_MEDIA_ROUNDUP(__sz, __r) (((__sz) + ((__r) - 1)) / (__r))
+#endif
+
+enum color_fmts {
+       /* Venus NV12:
+        * YUV 4:2:0 image with a plane of 8 bit Y samples followed
+        * by an interleaved U/V plane containing 8 bit 2x2 subsampled
+        * colour difference samples.
+        *
+        * <-------- Y/UV_Stride -------->
+        * <------- Width ------->
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  ^           ^
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  Height      |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |          Y_Scanlines
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  V           |
+        * . . . . . . . . . . . . . . . .              |
+        * . . . . . . . . . . . . . . . .              |
+        * . . . . . . . . . . . . . . . .              |
+        * . . . . . . . . . . . . . . . .              V
+        * U V U V U V U V U V U V . . . .  ^
+        * U V U V U V U V U V U V . . . .  |
+        * U V U V U V U V U V U V . . . .  |
+        * U V U V U V U V U V U V . . . .  UV_Scanlines
+        * . . . . . . . . . . . . . . . .  |
+        * . . . . . . . . . . . . . . . .  V
+        * . . . . . . . . . . . . . . . .  --> Buffer size alignment
+        *
+        * Y_Stride : Width aligned to 128
+        * UV_Stride : Width aligned to 128
+        * Y_Scanlines: Height aligned to 32
+        * UV_Scanlines: Height/2 aligned to 16
+        * Extradata: Arbitrary (software-imposed) padding
+        * Total size = align((Y_Stride * Y_Scanlines
+        *          + UV_Stride * UV_Scanlines + Extradata), 4096)
+        */
+       COLOR_FMT_NV12,
+
+       /* Venus NV21:
+        * YUV 4:2:0 image with a plane of 8 bit Y samples followed
+        * by an interleaved V/U plane containing 8 bit 2x2 subsampled
+        * colour difference samples.
+        *
+        * <-------- Y/UV_Stride -------->
+        * <------- Width ------->
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  ^           ^
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  Height      |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |          Y_Scanlines
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  V           |
+        * . . . . . . . . . . . . . . . .              |
+        * . . . . . . . . . . . . . . . .              |
+        * . . . . . . . . . . . . . . . .              |
+        * . . . . . . . . . . . . . . . .              V
+        * V U V U V U V U V U V U . . . .  ^
+        * V U V U V U V U V U V U . . . .  |
+        * V U V U V U V U V U V U . . . .  |
+        * V U V U V U V U V U V U . . . .  UV_Scanlines
+        * . . . . . . . . . . . . . . . .  |
+        * . . . . . . . . . . . . . . . .  V
+        * . . . . . . . . . . . . . . . .  --> Padding & Buffer size alignment
+        *
+        * Y_Stride : Width aligned to 128
+        * UV_Stride : Width aligned to 128
+        * Y_Scanlines: Height aligned to 32
+        * UV_Scanlines: Height/2 aligned to 16
+        * Extradata: Arbitrary (software-imposed) padding
+        * Total size = align((Y_Stride * Y_Scanlines
+        *          + UV_Stride * UV_Scanlines + Extradata), 4096)
+        */
+       COLOR_FMT_NV21,
+       /* Venus NV12_MVTB:
+        * Two YUV 4:2:0 images/views one after the other
+        * in a top-bottom layout, same as NV12
+        * with a plane of 8 bit Y samples followed
+        * by an interleaved U/V plane containing 8 bit 2x2 subsampled
+        * colour difference samples.
+        *
+        *
+        * <-------- Y/UV_Stride -------->
+        * <------- Width ------->
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  ^           ^               ^
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |               |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  Height      |               |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |          Y_Scanlines      |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |               |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |               |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |               |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  V           |               |
+        * . . . . . . . . . . . . . . . .              |             View_1
+        * . . . . . . . . . . . . . . . .              |               |
+        * . . . . . . . . . . . . . . . .              |               |
+        * . . . . . . . . . . . . . . . .              V               |
+        * U V U V U V U V U V U V . . . .  ^                           |
+        * U V U V U V U V U V U V . . . .  |                           |
+        * U V U V U V U V U V U V . . . .  |                           |
+        * U V U V U V U V U V U V . . . .  UV_Scanlines                |
+        * . . . . . . . . . . . . . . . .  |                           |
+        * . . . . . . . . . . . . . . . .  V                           V
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  ^           ^               ^
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |               |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  Height      |               |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |          Y_Scanlines      |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |               |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |               |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  |           |               |
+        * Y Y Y Y Y Y Y Y Y Y Y Y . . . .  V           |               |
+        * . . . . . . . . . . . . . . . .              |             View_2
+        * . . . . . . . . . . . . . . . .              |               |
+        * . . . . . . . . . . . . . . . .              |               |
+        * . . . . . . . . . . . . . . . .              V               |
+        * U V U V U V U V U V U V . . . .  ^                           |
+        * U V U V U V U V U V U V . . . .  |                           |
+        * U V U V U V U V U V U V . . . .  |                           |
+        * U V U V U V U V U V U V . . . .  UV_Scanlines                |
+        * . . . . . . . . . . . . . . . .  |                           |
+        * . . . . . . . . . . . . . . . .  V                           V
+        * . . . . . . . . . . . . . . . .  --> Buffer size alignment
+        *
+        * Y_Stride : Width aligned to 128
+        * UV_Stride : Width aligned to 128
+        * Y_Scanlines: Height aligned to 32
+        * UV_Scanlines: Height/2 aligned to 16
+        * View_1 begin at: 0 (zero)
+        * View_2 begin at: Y_Stride * Y_Scanlines + UV_Stride * UV_Scanlines
+        * Extradata: Arbitrary (software-imposed) padding
+        * Total size = align((2*(Y_Stride * Y_Scanlines)
+        *          + 2*(UV_Stride * UV_Scanlines) + Extradata), 4096)
+        */
+       COLOR_FMT_NV12_MVTB,
+       /* Venus NV12 UBWC:
+        * Compressed Macro-tile format for NV12.
+        * Contains 4 planes in the following order -
+        * (A) Y_Meta_Plane
+        * (B) Y_UBWC_Plane
+        * (C) UV_Meta_Plane
+        * (D) UV_UBWC_Plane
+        *
+        * Y_Meta_Plane consists of meta information to decode compressed
+        * tile data in Y_UBWC_Plane.
+        * Y_UBWC_Plane consists of Y data in compressed macro-tile format.
+        * UBWC decoder block will use the Y_Meta_Plane data together with
+        * Y_UBWC_Plane data to produce loss-less uncompressed 8 bit Y samples.
+        *
+        * UV_Meta_Plane consists of meta information to decode compressed
+        * tile data in UV_UBWC_Plane.
+        * UV_UBWC_Plane consists of UV data in compressed macro-tile format.
+        * UBWC decoder block will use UV_Meta_Plane data together with
+        * UV_UBWC_Plane data to produce loss-less uncompressed 8 bit 2x2
+        * subsampled color difference samples.
+        *
+        * Each tile in Y_UBWC_Plane/UV_UBWC_Plane is independently decodable
+        * and randomly accessible. There is no dependency between tiles.
+        *
+        * <----- Y_Meta_Stride ---->
+        * <-------- Width ------>
+        * M M M M M M M M M M M M . .      ^           ^
+        * M M M M M M M M M M M M . .      |           |
+        * M M M M M M M M M M M M . .      Height      |
+        * M M M M M M M M M M M M . .      |         Meta_Y_Scanlines
+        * M M M M M M M M M M M M . .      |           |
+        * M M M M M M M M M M M M . .      |           |
+        * M M M M M M M M M M M M . .      |           |
+        * M M M M M M M M M M M M . .      V           |
+        * . . . . . . . . . . . . . .                  |
+        * . . . . . . . . . . . . . .                  |
+        * . . . . . . . . . . . . . .      -------> Buffer size aligned to 4k
+        * . . . . . . . . . . . . . .                  V
+        * <--Compressed tile Y Stride--->
+        * <------- Width ------->
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  ^           ^
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  Height      |
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |        Macro_tile_Y_Scanlines
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  V           |
+        * . . . . . . . . . . . . . . . .              |
+        * . . . . . . . . . . . . . . . .              |
+        * . . . . . . . . . . . . . . . .  -------> Buffer size aligned to 4k
+        * . . . . . . . . . . . . . . . .              V
+        * <----- UV_Meta_Stride ---->
+        * M M M M M M M M M M M M . .      ^
+        * M M M M M M M M M M M M . .      |
+        * M M M M M M M M M M M M . .      |
+        * M M M M M M M M M M M M . .      M_UV_Scanlines
+        * . . . . . . . . . . . . . .      |
+        * . . . . . . . . . . . . . .      V
+        * . . . . . . . . . . . . . .      -------> Buffer size aligned to 4k
+        * <--Compressed tile UV Stride--->
+        * U* V* U* V* U* V* U* V* . . . .  ^
+        * U* V* U* V* U* V* U* V* . . . .  |
+        * U* V* U* V* U* V* U* V* . . . .  |
+        * U* V* U* V* U* V* U* V* . . . .  UV_Scanlines
+        * . . . . . . . . . . . . . . . .  |
+        * . . . . . . . . . . . . . . . .  V
+        * . . . . . . . . . . . . . . . .  -------> Buffer size aligned to 4k
+        *
+        * Y_Stride = align(Width, 128)
+        * UV_Stride = align(Width, 128)
+        * Y_Scanlines = align(Height, 32)
+        * UV_Scanlines = align(Height/2, 16)
+        * Y_UBWC_Plane_size = align(Y_Stride * Y_Scanlines, 4096)
+        * UV_UBWC_Plane_size = align(UV_Stride * UV_Scanlines, 4096)
+        * Y_Meta_Stride = align(roundup(Width, Y_TileWidth), 64)
+        * Y_Meta_Scanlines = align(roundup(Height, Y_TileHeight), 16)
+        * Y_Meta_Plane_size = align(Y_Meta_Stride * Y_Meta_Scanlines, 4096)
+        * UV_Meta_Stride = align(roundup(Width, UV_TileWidth), 64)
+        * UV_Meta_Scanlines = align(roundup(Height, UV_TileHeight), 16)
+        * UV_Meta_Plane_size = align(UV_Meta_Stride * UV_Meta_Scanlines, 4096)
+        * Extradata = 8k
+        *
+        * Total size = align( Y_UBWC_Plane_size + UV_UBWC_Plane_size +
+        *           Y_Meta_Plane_size + UV_Meta_Plane_size + Extradata, 4096)
+        */
+       COLOR_FMT_NV12_UBWC,
+       /* Venus NV12 10-bit UBWC:
+        * Compressed Macro-tile format for NV12.
+        * Contains 4 planes in the following order -
+        * (A) Y_Meta_Plane
+        * (B) Y_UBWC_Plane
+        * (C) UV_Meta_Plane
+        * (D) UV_UBWC_Plane
+        *
+        * Y_Meta_Plane consists of meta information to decode compressed
+        * tile data in Y_UBWC_Plane.
+        * Y_UBWC_Plane consists of Y data in compressed macro-tile format.
+        * UBWC decoder block will use the Y_Meta_Plane data together with
+        * Y_UBWC_Plane data to produce loss-less uncompressed 10 bit Y samples.
+        *
+        * UV_Meta_Plane consists of meta information to decode compressed
+        * tile data in UV_UBWC_Plane.
+        * UV_UBWC_Plane consists of UV data in compressed macro-tile format.
+        * UBWC decoder block will use UV_Meta_Plane data together with
+        * UV_UBWC_Plane data to produce loss-less uncompressed 10 bit 2x2
+        * subsampled color difference samples.
+        *
+        * Each tile in Y_UBWC_Plane/UV_UBWC_Plane is independently decodable
+        * and randomly accessible. There is no dependency between tiles.
+        *
+        * <----- Y_Meta_Stride ----->
+        * <-------- Width ------>
+        * M M M M M M M M M M M M . .      ^           ^
+        * M M M M M M M M M M M M . .      |           |
+        * M M M M M M M M M M M M . .      Height      |
+        * M M M M M M M M M M M M . .      |         Meta_Y_Scanlines
+        * M M M M M M M M M M M M . .      |           |
+        * M M M M M M M M M M M M . .      |           |
+        * M M M M M M M M M M M M . .      |           |
+        * M M M M M M M M M M M M . .      V           |
+        * . . . . . . . . . . . . . .                  |
+        * . . . . . . . . . . . . . .                  |
+        * . . . . . . . . . . . . . .      -------> Buffer size aligned to 4k
+        * . . . . . . . . . . . . . .                  V
+        * <--Compressed tile Y Stride--->
+        * <------- Width ------->
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  ^           ^
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  Height      |
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |        Macro_tile_Y_Scanlines
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  |           |
+        * Y* Y* Y* Y* Y* Y* Y* Y* . . . .  V           |
+        * . . . . . . . . . . . . . . . .              |
+        * . . . . . . . . . . . . . . . .              |
+        * . . . . . . . . . . . . . . . .  -------> Buffer size aligned to 4k
+        * . . . . . . . . . . . . . . . .              V
+        * <----- UV_Meta_Stride ---->
+        * M M M M M M M M M M M M . .      ^
+        * M M M M M M M M M M M M . .      |
+        * M M M M M M M M M M M M . .      |
+        * M M M M M M M M M M M M . .      M_UV_Scanlines
+        * . . . . . . . . . . . . . .      |
+        * . . . . . . . . . . . . . .      V
+        * . . . . . . . . . . . . . .      -------> Buffer size aligned to 4k
+        * <--Compressed tile UV Stride--->
+        * U* V* U* V* U* V* U* V* . . . .  ^
+        * U* V* U* V* U* V* U* V* . . . .  |
+        * U* V* U* V* U* V* U* V* . . . .  |
+        * U* V* U* V* U* V* U* V* . . . .  UV_Scanlines
+        * . . . . . . . . . . . . . . . .  |
+        * . . . . . . . . . . . . . . . .  V
+        * . . . . . . . . . . . . . . . .  -------> Buffer size aligned to 4k
+        *
+        *
+        * Y_Stride = align(Width * 4/3, 128)
+        * UV_Stride = align(Width * 4/3, 128)
+        * Y_Scanlines = align(Height, 32)
+        * UV_Scanlines = align(Height/2, 16)
+        * Y_UBWC_Plane_Size = align(Y_Stride * Y_Scanlines, 4096)
+        * UV_UBWC_Plane_Size = align(UV_Stride * UV_Scanlines, 4096)
+        * Y_Meta_Stride = align(roundup(Width, Y_TileWidth), 64)
+        * Y_Meta_Scanlines = align(roundup(Height, Y_TileHeight), 16)
+        * Y_Meta_Plane_size = align(Y_Meta_Stride * Y_Meta_Scanlines, 4096)
+        * UV_Meta_Stride = align(roundup(Width, UV_TileWidth), 64)
+        * UV_Meta_Scanlines = align(roundup(Height, UV_TileHeight), 16)
+        * UV_Meta_Plane_size = align(UV_Meta_Stride * UV_Meta_Scanlines, 4096)
+        * Extradata = 8k
+        */
+       COLOR_FMT_NV12_BPP10_UBWC,
+};
+
+static inline unsigned int VENUS_EXTRADATA_SIZE(int width, int height)
+{
+       (void)height;
+       (void)width;
+
+       /*
+        * In the future, calculate the size based on the w/h but just
+        * hardcode it for now since 8K satisfies all current usecases.
+        */
+       return 8 * 1024;
+}
+
+static inline unsigned int VENUS_Y_STRIDE(int color_fmt, int width)
+{
+       unsigned int alignment, stride = 0;
+       if (!width)
+               goto invalid_input;
+
+       switch (color_fmt) {
+       case COLOR_FMT_NV21:
+       case COLOR_FMT_NV12:
+       case COLOR_FMT_NV12_MVTB:
+       case COLOR_FMT_NV12_UBWC:
+               alignment = 128;
+               stride = MSM_MEDIA_ALIGN(width, alignment);
+               break;
+       case COLOR_FMT_NV12_BPP10_UBWC:
+               alignment = 128;
+               stride = MSM_MEDIA_ALIGN(width * 4/3, alignment);
+               break;
+       default:
+               break;
+       }
+invalid_input:
+       return stride;
+}
+
+static inline unsigned int VENUS_UV_STRIDE(int color_fmt, int width)
+{
+       unsigned int alignment, stride = 0;
+       if (!width)
+               goto invalid_input;
+
+       switch (color_fmt) {
+       case COLOR_FMT_NV21:
+       case COLOR_FMT_NV12:
+       case COLOR_FMT_NV12_MVTB:
+       case COLOR_FMT_NV12_UBWC:
+               alignment = 128;
+               stride = MSM_MEDIA_ALIGN(width, alignment);
+               break;
+       case COLOR_FMT_NV12_BPP10_UBWC:
+               alignment = 128;
+               stride = MSM_MEDIA_ALIGN(width * 4/3, alignment);
+               break;
+       default:
+               break;
+       }
+invalid_input:
+       return stride;
+}
+
+static inline unsigned int VENUS_Y_SCANLINES(int color_fmt, int height)
+{
+       unsigned int alignment, sclines = 0;
+       if (!height)
+               goto invalid_input;
+
+       switch (color_fmt) {
+       case COLOR_FMT_NV21:
+       case COLOR_FMT_NV12:
+       case COLOR_FMT_NV12_MVTB:
+       case COLOR_FMT_NV12_UBWC:
+       case COLOR_FMT_NV12_BPP10_UBWC:
+               alignment = 32;
+               sclines = MSM_MEDIA_ALIGN(height, alignment);
+               break;
+       default:
+               break;
+       }
+invalid_input:
+       return sclines;
+}
+
+static inline unsigned int VENUS_UV_SCANLINES(int color_fmt, int height)
+{
+       unsigned int alignment, sclines = 0;
+       if (!height)
+               goto invalid_input;
+
+       switch (color_fmt) {
+       case COLOR_FMT_NV21:
+       case COLOR_FMT_NV12:
+       case COLOR_FMT_NV12_MVTB:
+       case COLOR_FMT_NV12_UBWC:
+       case COLOR_FMT_NV12_BPP10_UBWC:
+               alignment = 16;
+               sclines = MSM_MEDIA_ALIGN(((height + 1) >> 1), alignment);
+               break;
+       default:
+               break;
+       }
+invalid_input:
+       return sclines;
+}
+
+static inline unsigned int VENUS_Y_META_STRIDE(int color_fmt, int width)
+{
+       int y_tile_width = 0, y_meta_stride = 0;
+
+       if (!width)
+               goto invalid_input;
+
+       switch (color_fmt) {
+       case COLOR_FMT_NV12_UBWC:
+               y_tile_width = 32;
+               break;
+       case COLOR_FMT_NV12_BPP10_UBWC:
+               y_tile_width = 48;
+               break;
+       default:
+               goto invalid_input;
+       }
+
+       y_meta_stride = MSM_MEDIA_ROUNDUP(width, y_tile_width);
+       y_meta_stride = MSM_MEDIA_ALIGN(y_meta_stride, 64);
+
+invalid_input:
+       return y_meta_stride;
+}
+
+static inline unsigned int VENUS_Y_META_SCANLINES(int color_fmt, int height)
+{
+       int y_tile_height = 0, y_meta_scanlines = 0;
+
+       if (!height)
+               goto invalid_input;
+
+       switch (color_fmt) {
+       case COLOR_FMT_NV12_UBWC:
+               y_tile_height = 8;
+               break;
+       case COLOR_FMT_NV12_BPP10_UBWC:
+               y_tile_height = 4;
+               break;
+       default:
+               goto invalid_input;
+       }
+
+       y_meta_scanlines = MSM_MEDIA_ROUNDUP(height, y_tile_height);
+       y_meta_scanlines = MSM_MEDIA_ALIGN(y_meta_scanlines, 16);
+
+invalid_input:
+       return y_meta_scanlines;
+}
+
+static inline unsigned int VENUS_UV_META_STRIDE(int color_fmt, int width)
+{
+       int uv_tile_width = 0, uv_meta_stride = 0;
+
+       if (!width)
+               goto invalid_input;
+
+       switch (color_fmt) {
+       case COLOR_FMT_NV12_UBWC:
+               uv_tile_width = 16;
+               break;
+       case COLOR_FMT_NV12_BPP10_UBWC:
+               uv_tile_width = 24;
+               break;
+       default:
+               goto invalid_input;
+       }
+
+       uv_meta_stride = MSM_MEDIA_ROUNDUP(width, uv_tile_width);
+       uv_meta_stride = MSM_MEDIA_ALIGN(uv_meta_stride, 64);
+
+invalid_input:
+       return uv_meta_stride;
+}
+
+static inline unsigned int VENUS_UV_META_SCANLINES(int color_fmt, int height)
+{
+       int uv_tile_height = 0, uv_meta_scanlines = 0;
+
+       if (!height)
+               goto invalid_input;
+
+       switch (color_fmt) {
+       case COLOR_FMT_NV12_UBWC:
+               uv_tile_height = 8;
+               break;
+       case COLOR_FMT_NV12_BPP10_UBWC:
+               uv_tile_height = 4;
+               break;
+       default:
+               goto invalid_input;
+       }
+
+       uv_meta_scanlines = MSM_MEDIA_ROUNDUP(height, uv_tile_height);
+       uv_meta_scanlines = MSM_MEDIA_ALIGN(uv_meta_scanlines, 16);
+
+invalid_input:
+       return uv_meta_scanlines;
+}
+
+static inline unsigned int VENUS_BUFFER_SIZE(int color_fmt, int width,
+                                            int height)
+{
+       const unsigned int extra_size = VENUS_EXTRADATA_SIZE(width, height);
+       unsigned int uv_alignment = 0, size = 0;
+       unsigned int y_plane, uv_plane, y_stride,
+               uv_stride, y_sclines, uv_sclines;
+       unsigned int y_ubwc_plane = 0, uv_ubwc_plane = 0;
+       unsigned int y_meta_stride = 0, y_meta_scanlines = 0;
+       unsigned int uv_meta_stride = 0, uv_meta_scanlines = 0;
+       unsigned int y_meta_plane = 0, uv_meta_plane = 0;
+
+       if (!width || !height)
+               goto invalid_input;
+
+       y_stride = VENUS_Y_STRIDE(color_fmt, width);
+       uv_stride = VENUS_UV_STRIDE(color_fmt, width);
+       y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
+       uv_sclines = VENUS_UV_SCANLINES(color_fmt, height);
+
+       switch (color_fmt) {
+       case COLOR_FMT_NV21:
+       case COLOR_FMT_NV12:
+               uv_alignment = 4096;
+               y_plane = y_stride * y_sclines;
+               uv_plane = uv_stride * uv_sclines + uv_alignment;
+               size = y_plane + uv_plane + extra_size;
+               size = MSM_MEDIA_ALIGN(size, 4096);
+               break;
+       case COLOR_FMT_NV12_MVTB:
+               uv_alignment = 4096;
+               y_plane = y_stride * y_sclines;
+               uv_plane = uv_stride * uv_sclines + uv_alignment;
+               size = y_plane + uv_plane;
+               size = 2 * size + extra_size;
+               size = MSM_MEDIA_ALIGN(size, 4096);
+               break;
+       case COLOR_FMT_NV12_UBWC:
+       case COLOR_FMT_NV12_BPP10_UBWC:
+               y_ubwc_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
+               uv_ubwc_plane = MSM_MEDIA_ALIGN(uv_stride * uv_sclines, 4096);
+               y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
+               y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
+               y_meta_plane = MSM_MEDIA_ALIGN(
+                               y_meta_stride * y_meta_scanlines, 4096);
+               uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
+               uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
+               uv_meta_plane = MSM_MEDIA_ALIGN(uv_meta_stride *
+                                       uv_meta_scanlines, 4096);
+
+               size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane +
+                               uv_meta_plane + extra_size;
+               size = MSM_MEDIA_ALIGN(size, 4096);
+               break;
+       default:
+               break;
+       }
+
+invalid_input:
+       return size;
+}
+
+static inline unsigned int VENUS_VIEW2_OFFSET(
+       int color_fmt, int width, int height)
+{
+       unsigned int offset = 0;
+       unsigned int y_plane, uv_plane, y_stride,
+               uv_stride, y_sclines, uv_sclines;
+       if (!width || !height)
+               goto invalid_input;
+
+       y_stride = VENUS_Y_STRIDE(color_fmt, width);
+       uv_stride = VENUS_UV_STRIDE(color_fmt, width);
+       y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
+       uv_sclines = VENUS_UV_SCANLINES(color_fmt, height);
+       switch (color_fmt) {
+       case COLOR_FMT_NV12_MVTB:
+               y_plane = y_stride * y_sclines;
+               uv_plane = uv_stride * uv_sclines;
+               offset = y_plane + uv_plane;
+               break;
+       default:
+               break;
+       }
+invalid_input:
+       return offset;
+}
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
new file mode 100644 (file)
index 0000000..320087b
--- /dev/null
@@ -0,0 +1,191 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/dma-iommu.h>
+#include <linux/dma-attrs.h>
+#include <linux/dma-direction.h>
+#include <linux/iommu.h>
+#include <linux/qcom_iommu.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "msm_smem.h"
+#include "msm_vidc_debug.h"
+#include "msm_vidc_resources.h"
+
+static int alloc_dma_mem(struct smem_client *client, size_t size, u32 align,
+                        u32 flags, enum hal_buffer buffer_type,
+                        struct smem *mem, int map_kernel)
+{
+       int ret;
+
+       if (align > 1) {
+               align = ALIGN(align, SZ_4K);
+               size = ALIGN(size, align);
+       }
+
+       size = ALIGN(size, SZ_4K);
+
+       dprintk(VIDC_DBG, "%s: type: %x, size %zu\n", __func__, buffer_type,
+               size);
+
+       mem->flags = flags;
+       mem->buffer_type = buffer_type;
+       mem->size = size;
+       mem->kvaddr = NULL;
+       mem->smem_priv = NULL;
+
+       mem->iommu_dev = msm_iommu_get_ctx("venus_ns");
+       if (IS_ERR(mem->iommu_dev))
+               return PTR_ERR(mem->iommu_dev);
+
+       init_dma_attrs(&mem->attrs);
+
+       if (!map_kernel)
+               dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &mem->attrs);
+
+       mem->kvaddr = dma_alloc_attrs(mem->iommu_dev, size, &mem->da,
+                                     GFP_KERNEL, &mem->attrs);
+       if (!mem->kvaddr)
+               return -ENOMEM;
+
+       mem->sgt = kmalloc(sizeof(*mem->sgt), GFP_KERNEL);
+       if (!mem->sgt) {
+               ret = -ENOMEM;
+               goto error_sgt;
+       }
+
+       ret = dma_get_sgtable_attrs(mem->iommu_dev, mem->sgt, mem->kvaddr,
+                                   mem->da, mem->size, &mem->attrs);
+       if (ret)
+               goto error;
+
+       return 0;
+error:
+       kfree(mem->sgt);
+error_sgt:
+       dma_free_attrs(mem->iommu_dev, mem->size, mem->kvaddr,
+                      mem->da, &mem->attrs);
+       return ret;
+}
+
+static void free_dma_mem(struct smem_client *client, struct smem *mem)
+{
+       dma_free_attrs(mem->iommu_dev, mem->size, mem->kvaddr,
+                      mem->da, &mem->attrs);
+       kfree(mem->sgt);
+}
+
+static int sync_dma_cache(struct smem *mem, enum smem_cache_ops cache_op)
+{
+       if (cache_op == SMEM_CACHE_CLEAN) {
+               dma_sync_sg_for_device(mem->iommu_dev, mem->sgt->sgl,
+                                      mem->sgt->nents, DMA_TO_DEVICE);
+       } else if (cache_op == SMEM_CACHE_INVALIDATE) {
+               dma_sync_sg_for_cpu(mem->iommu_dev, mem->sgt->sgl,
+                                   mem->sgt->nents, DMA_FROM_DEVICE);
+       } else {
+               dma_sync_sg_for_device(mem->iommu_dev, mem->sgt->sgl,
+                                      mem->sgt->nents, DMA_TO_DEVICE);
+               dma_sync_sg_for_cpu(mem->iommu_dev, mem->sgt->sgl,
+                                   mem->sgt->nents, DMA_FROM_DEVICE);
+       }
+
+       return 0;
+}
+
+int smem_cache_operations(struct smem_client *client, struct smem *mem,
+                         enum smem_cache_ops cache_op)
+{
+       if (!client)
+               return -EINVAL;
+
+       return sync_dma_cache(mem, cache_op);
+}
+
+struct smem_client *smem_new_client(void *platform_resources)
+{
+       struct vidc_resources *res = platform_resources;
+       struct smem_client *client;
+
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (!client)
+               return ERR_PTR(-ENOMEM);
+
+       client->clnt = NULL;
+       client->res = res;
+
+       return client;
+}
+
+void smem_delete_client(struct smem_client *client)
+{
+       if (!client)
+               return;
+
+       kfree(client);
+}
+
+struct smem *smem_alloc(struct smem_client *client, size_t size, u32 align,
+                       u32 flags, enum hal_buffer buffer_type, int map_kernel)
+{
+       struct smem *mem;
+       int ret;
+
+       if (!client || !size)
+               return ERR_PTR(-EINVAL);
+
+       mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+       if (!mem)
+               return ERR_PTR(-ENOMEM);
+
+       ret = alloc_dma_mem(client, size, align, flags, buffer_type,
+                           mem, map_kernel);
+       if (ret) {
+               kfree(mem);
+               return ERR_PTR(ret);
+       }
+
+       return mem;
+}
+
+void smem_free(struct smem_client *client, struct smem *mem)
+{
+       if (!client || !mem)
+               return;
+
+       free_dma_mem(client, mem);
+       kfree(mem);
+};
+
+struct context_bank_info *
+smem_get_context_bank(struct smem_client *client, bool is_secure,
+                     enum hal_buffer buffer_type)
+{
+       struct context_bank_info *cb = NULL, *match = NULL;
+
+       if (!client) {
+               dprintk(VIDC_ERR, "%s - invalid params\n", __func__);
+               return NULL;
+       }
+
+       list_for_each_entry(cb, &client->res->context_banks, list) {
+               if (cb->is_secure == is_secure &&
+                   cb->buffer_type & buffer_type) {
+                       match = cb;
+                       break;
+               }
+       }
+
+       return match;
+}
diff --git a/drivers/media/platform/msm/vidc/msm_smem.h b/drivers/media/platform/msm/vidc/msm_smem.h
new file mode 100644 (file)
index 0000000..62e7cfa
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __VIDC_MSM_SMEM_H__
+#define __VIDC_MSM_SMEM_H__
+
+#include <linux/dma-attrs.h>
+#include <linux/scatterlist.h>
+
+#include "msm_vidc_resources.h"
+#include "msm_vidc.h"
+#include "hfi/vidc_hfi_api.h"
+
+enum smem_prop {
+       SMEM_CACHED = BIT(0),
+       SMEM_SECURE = BIT(1),
+};
+
+enum smem_cache_ops {
+       SMEM_CACHE_CLEAN,
+       SMEM_CACHE_INVALIDATE,
+       SMEM_CACHE_CLEAN_INVALIDATE,
+};
+
+struct smem {
+       size_t size;
+       void *kvaddr;
+       dma_addr_t da;
+       unsigned long flags;
+       void *smem_priv;
+       enum hal_buffer buffer_type;
+       struct dma_attrs attrs;
+       struct device *iommu_dev;
+       struct sg_table *sgt;
+};
+
+struct smem_client {
+       void *clnt;
+       struct vidc_resources *res;
+};
+
+struct smem_client *smem_new_client(void *platform_resources);
+void smem_delete_client(struct smem_client *clt);
+
+struct smem *smem_alloc(struct smem_client *clt, size_t size, u32 align,
+                       u32 flags, enum hal_buffer buffer_type, int map_kernel);
+void smem_free(struct smem_client *clt, struct smem *mem);
+
+int smem_cache_operations(struct smem_client *clt, struct smem *mem,
+                         enum smem_cache_ops);
+struct context_bank_info *
+smem_get_context_bank(struct smem_client *clt, bool is_secure,
+                     enum hal_buffer buffer_type);
+
+#endif /* __VIDC_MSM_SMEM_H__ */
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
new file mode 100644 (file)
index 0000000..52c842b
--- /dev/null
@@ -0,0 +1,571 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/remoteproc.h>
+
+#include "msm_vidc_common.h"
+#include "msm_smem.h"
+#include "msm_vdec.h"
+#include "msm_venc.h"
+#include "msm_vidc_debug.h"
+#include "msm_vidc_internal.h"
+#include "msm_vidc_resources.h"
+#include "msm_hfi_interface.h"
+
+/* Offset base for buffers on the destination queue - used to distinguish
+ * between source and destination buffers when mmapping - they receive the same
+ * offsets but for different queues */
+#define DST_QUEUE_OFF_BASE     (1 << 30)
+
+struct vidc_drv *vidc_driver;
+unsigned int vidc_pwr_collapse_delay = 2000;
+
+static inline struct vidc_inst *vidc_to_inst(struct file *file)
+{
+       return container_of(file->private_data, struct vidc_inst, fh);
+}
+
+static void vidc_add_inst(struct vidc_core *core, struct vidc_inst *inst)
+{
+       mutex_lock(&core->lock);
+       list_add_tail(&inst->list, &core->instances);
+       mutex_unlock(&core->lock);
+}
+
+static void vidc_del_inst(struct vidc_core *core, struct vidc_inst *inst)
+{
+       struct vidc_inst *pos, *n;
+
+       mutex_lock(&core->lock);
+       list_for_each_entry_safe(pos, n, &core->instances, list) {
+               if (pos == inst)
+                       list_del(&inst->list);
+       }
+       mutex_unlock(&core->lock);
+}
+
+static int vidc_firmware_load(struct vidc_core *core)
+{
+       int ret;
+
+       if (core->rproc_booted)
+               return 0;
+
+       ret = rproc_boot(core->rproc);
+       if (ret)
+               return ret;
+
+       core->rproc_booted = true;
+
+       return 0;
+}
+
+static void vidc_firmware_unload(struct vidc_core *core)
+{
+       if (!core->rproc_booted)
+               return;
+
+       rproc_shutdown(core->rproc);
+       core->rproc_booted = false;
+}
+
+struct vidc_sys_error {
+       struct vidc_core *core;
+       struct delayed_work work;
+};
+
+static void vidc_sys_error_handler(struct work_struct *work)
+{
+       struct vidc_sys_error *handler;
+       struct vidc_core *core;
+       struct hfi_device *hdev;
+       int ret;
+
+       handler = container_of(work, struct vidc_sys_error, work.work);
+       core = handler->core;
+       hdev = core->hfidev;
+
+       mutex_lock(&core->lock);
+       if (core->state != CORE_INVALID) {
+               mutex_unlock(&core->lock);
+               goto exit;
+       }
+
+       ret = call_hfi_op(hdev, core_release, hdev->hfi_device_data);
+       if (ret) {
+               dprintk(VIDC_ERR, "%s: core_release failed: %d\n",
+                       __func__, ret);
+       }
+
+       rproc_report_crash(core->rproc, RPROC_FATAL_ERROR);
+
+       vidc_firmware_unload(core);
+
+       ret = vidc_firmware_load(core);
+       if (ret)
+               goto exit;
+
+       core->state = CORE_INIT;
+
+       mutex_unlock(&core->lock);
+
+exit:
+       kfree(handler);
+}
+
+static int vidc_event_notify(struct vidc_core *core, u32 device_id, u32 event)
+{
+       struct vidc_sys_error *handler;
+       struct vidc_inst *inst = NULL;
+
+       switch (event) {
+       case SYS_WATCHDOG_TIMEOUT:
+       case SYS_ERROR:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       mutex_lock(&core->lock);
+
+       core->state = CORE_INVALID;
+
+       list_for_each_entry(inst, &core->instances, list)
+               vidc_inst_set_state(inst, INST_INVALID);
+
+       mutex_unlock(&core->lock);
+
+       handler = kzalloc(sizeof(*handler), GFP_KERNEL);
+       if (!handler)
+               return -ENOMEM;
+
+       handler->core = core;
+       INIT_DELAYED_WORK(&handler->work, vidc_sys_error_handler);
+
+       /*
+        * Sleep for 5 sec to ensure venus has completed any
+        * pending cache operations. Without this sleep, we see
+        * device reset when firmware is unloaded after a sys
+        * error.
+        */
+       schedule_delayed_work(&handler->work, msecs_to_jiffies(5000));
+
+       return 0;
+}
+
+static int vidc_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct vidc_core *core = video_drvdata(file);
+       struct device *dev = &core->res.pdev->dev;
+       struct vidc_inst *inst;
+       int ret = 0;
+
+       inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+       if (!inst)
+               return -ENOMEM;
+
+       mutex_init(&inst->sync_lock);
+       mutex_init(&inst->lock);
+
+       INIT_VIDC_LIST(&inst->scratchbufs);
+       INIT_VIDC_LIST(&inst->persistbufs);
+       INIT_VIDC_LIST(&inst->pending_getpropq);
+       INIT_VIDC_LIST(&inst->registeredbufs);
+
+       INIT_LIST_HEAD(&inst->bufqueue);
+       mutex_init(&inst->bufqueue_lock);
+
+       if (vdev == &core->vdev_dec)
+               inst->session_type = VIDC_DECODER;
+       else
+               inst->session_type = VIDC_ENCODER;
+
+       inst->state = INST_UNINIT;
+       inst->core = core;
+
+       inst->mem_client = smem_new_client(&core->res);
+       if (IS_ERR(inst->mem_client)) {
+               ret = PTR_ERR(inst->mem_client);
+               goto err_free_inst;
+       }
+
+       ret = enable_clocks(&core->res);
+       if (ret) {
+               dev_err(dev, "enable clocks\n");
+               goto err_del_mem_clnt;
+       }
+
+       ret = vidc_firmware_load(core);
+       if (ret)
+               goto err_dis_clks;
+
+       ret = hfi_core_init(core);
+       if (ret)
+               goto err_fw_unload;
+
+       inst->debugfs_root = vidc_debugfs_init_inst(inst, core->debugfs_root);
+
+       if (inst->session_type == VIDC_DECODER)
+               ret = vdec_open(inst);
+       else
+               ret = venc_open(inst);
+
+       if (ret)
+               goto err_core_deinit;
+
+       if (inst->session_type == VIDC_DECODER)
+               v4l2_fh_init(&inst->fh, &core->vdev_dec);
+       else
+               v4l2_fh_init(&inst->fh, &core->vdev_enc);
+
+       inst->fh.ctrl_handler = &inst->ctrl_handler;
+
+       v4l2_fh_add(&inst->fh);
+
+       file->private_data = &inst->fh;
+
+       vidc_add_inst(core, inst);
+
+       return 0;
+
+err_core_deinit:
+       hfi_core_deinit(core);
+err_fw_unload:
+       vidc_firmware_unload(core);
+err_dis_clks:
+       disable_clocks(&core->res);
+err_del_mem_clnt:
+       smem_delete_client(inst->mem_client);
+err_free_inst:
+       kfree(inst);
+       return ret;
+}
+
+static int vidc_close(struct file *file)
+{
+       struct vidc_inst *inst = vidc_to_inst(file);
+       struct vidc_core *core = inst->core;
+       struct device *dev = &core->res.pdev->dev;
+       int ret;
+
+       if (inst->session_type == VIDC_DECODER)
+               vdec_close(inst);
+       else
+               venc_close(inst);
+
+       vidc_del_inst(core, inst);
+
+       debugfs_remove_recursive(inst->debugfs_root);
+
+       mutex_lock(&inst->pending_getpropq.lock);
+       WARN_ON(!list_empty(&inst->pending_getpropq.list));
+       mutex_unlock(&inst->pending_getpropq.lock);
+
+       hfi_session_clean(inst);
+
+       ret = hfi_core_deinit(core);
+       if (ret)
+               dev_err(dev, "core: deinit failed (%d)\n", ret);
+
+       disable_clocks(&core->res);
+
+       smem_delete_client(inst->mem_client);
+
+       mutex_destroy(&inst->bufqueue_lock);
+       mutex_destroy(&inst->scratchbufs.lock);
+       mutex_destroy(&inst->persistbufs.lock);
+       mutex_destroy(&inst->pending_getpropq.lock);
+       mutex_destroy(&inst->registeredbufs.lock);
+
+       v4l2_fh_del(&inst->fh);
+       v4l2_fh_exit(&inst->fh);
+
+       kfree(inst);
+
+       return 0;
+}
+
+static int vidc_get_poll_flags(struct vidc_inst *inst)
+{
+       struct vb2_queue *outq = &inst->bufq_out;
+       struct vb2_queue *capq = &inst->bufq_cap;
+       struct vb2_buffer *out_vb = NULL;
+       struct vb2_buffer *cap_vb = NULL;
+       unsigned long flags;
+       int ret = 0;
+
+       if (v4l2_event_pending(&inst->fh))
+               ret |= POLLPRI;
+
+       spin_lock_irqsave(&capq->done_lock, flags);
+       if (!list_empty(&capq->done_list))
+               cap_vb = list_first_entry(&capq->done_list, struct vb2_buffer,
+                                         done_entry);
+       if (cap_vb && (cap_vb->state == VB2_BUF_STATE_DONE ||
+                      cap_vb->state == VB2_BUF_STATE_ERROR))
+               ret |= POLLIN | POLLRDNORM;
+       spin_unlock_irqrestore(&capq->done_lock, flags);
+
+       spin_lock_irqsave(&outq->done_lock, flags);
+       if (!list_empty(&outq->done_list))
+               out_vb = list_first_entry(&outq->done_list, struct vb2_buffer,
+                                         done_entry);
+       if (out_vb && (out_vb->state == VB2_BUF_STATE_DONE ||
+                      out_vb->state == VB2_BUF_STATE_ERROR))
+               ret |= POLLOUT | POLLWRNORM;
+       spin_unlock_irqrestore(&outq->done_lock, flags);
+
+       return ret;
+}
+
+static unsigned int vidc_poll(struct file *file, struct poll_table_struct *pt)
+{
+       struct vidc_inst *inst = vidc_to_inst(file);
+       struct vb2_queue *outq = &inst->bufq_out;
+       struct vb2_queue *capq = &inst->bufq_cap;
+
+       poll_wait(file, &inst->fh.wait, pt);
+       poll_wait(file, &capq->done_wq, pt);
+       poll_wait(file, &outq->done_wq, pt);
+
+       return vidc_get_poll_flags(inst);
+}
+
+static int vidc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct vidc_inst *inst = vidc_to_inst(file);
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       int ret;
+
+       if (offset < DST_QUEUE_OFF_BASE) {
+               ret = vb2_mmap(&inst->bufq_out, vma);
+       } else {
+               vma->vm_pgoff -= DST_QUEUE_OFF_BASE >> PAGE_SHIFT;
+               ret = vb2_mmap(&inst->bufq_cap, vma);
+       }
+
+       return ret;
+}
+
+const struct v4l2_file_operations vidc_fops = {
+       .owner = THIS_MODULE,
+       .open = vidc_open,
+       .release = vidc_close,
+       .unlocked_ioctl = video_ioctl2,
+       .poll = vidc_poll,
+       .mmap = vidc_mmap,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl32 = v4l2_compat_ioctl32,
+#endif
+};
+
+static const struct of_device_id vidc_dt_match[] = {
+       { .compatible = "qcom,msm-vidc" },
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, vidc_dt_match);
+
+static int vidc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct vidc_core *core;
+       struct vidc_resources *res;
+       struct device_node *rproc;
+       struct resource *r;
+       int ret;
+
+       if (!vidc_driver) {
+               vidc_driver = kzalloc(sizeof(*vidc_driver), GFP_KERNEL);
+               if (!vidc_driver)
+                       return -ENOMEM;
+
+               INIT_LIST_HEAD(&vidc_driver->cores);
+               mutex_init(&vidc_driver->lock);
+
+               vidc_driver->debugfs_root = vidc_debugfs_init_drv();
+               if (!vidc_driver->debugfs_root)
+                       dev_err(dev, "create debugfs for vidc\n");
+       }
+
+       mutex_lock(&vidc_driver->lock);
+       if (vidc_driver->num_cores + 1 > VIDC_CORES_MAX) {
+               mutex_unlock(&vidc_driver->lock);
+               dev_warn(dev, "maximum cores reached\n");
+               return -EBUSY;
+       }
+       vidc_driver->num_cores++;
+       mutex_unlock(&vidc_driver->lock);
+
+       core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL);
+       if (!core)
+               return -ENOMEM;
+
+       core->res.pdev = pdev;
+       platform_set_drvdata(pdev, core);
+
+       rproc = of_parse_phandle(dev->of_node, "rproc", 0);
+       if (IS_ERR(rproc)) {
+               dev_err(dev, "cannot parse phandle rproc\n");
+               return PTR_ERR(rproc);
+       }
+
+       core->rproc = rproc_get_by_phandle(rproc->phandle);
+       if (IS_ERR(core->rproc))
+               return PTR_ERR(core->rproc);
+       else if (!core->rproc)
+               return -EPROBE_DEFER;
+
+       res = &core->res;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       res->base = devm_ioremap_resource(dev, r);
+       if (IS_ERR(res->base))
+               return PTR_ERR(res->base);
+
+       res->irq = platform_get_irq(pdev, 0);
+       if (IS_ERR_VALUE(res->irq))
+               return res->irq;
+
+       ret = get_platform_resources(core);
+       if (ret)
+               return ret;
+
+       INIT_LIST_HEAD(&core->instances);
+       mutex_init(&core->lock);
+       core->state = CORE_UNINIT;
+
+       if (core->hfi_type == VIDC_HFI_Q6)
+               core->id = VIDC_CORE_Q6;
+       else
+               core->id = VIDC_CORE_VENUS;
+
+       ret = v4l2_device_register(dev, &core->v4l2_dev);
+       if (ret)
+               return ret;
+
+       ret = vdec_init(core, &core->vdev_dec);
+       if (ret)
+               goto err_dev_unregister;
+
+       ret = venc_init(core, &core->vdev_enc);
+       if (ret)
+               goto err_vdec_deinit;
+
+       core->hfidev = vidc_hfi_init(core->hfi_type, core->id, &core->res);
+       if (IS_ERR(core->hfidev)) {
+               mutex_lock(&vidc_driver->lock);
+               vidc_driver->num_cores--;
+               mutex_unlock(&vidc_driver->lock);
+
+               ret = PTR_ERR(core->hfidev);
+               goto err_venc_deinit;
+       }
+
+       core->event_notify = vidc_event_notify;
+
+       mutex_lock(&vidc_driver->lock);
+       list_add_tail(&core->list, &vidc_driver->cores);
+       mutex_unlock(&vidc_driver->lock);
+
+       core->debugfs_root =
+               vidc_debugfs_init_core(core, vidc_driver->debugfs_root);
+
+       return 0;
+
+err_venc_deinit:
+       venc_deinit(core, &core->vdev_enc);
+err_vdec_deinit:
+       vdec_deinit(core, &core->vdev_dec);
+err_dev_unregister:
+       v4l2_device_unregister(&core->v4l2_dev);
+       return ret;
+}
+
+static int vidc_remove(struct platform_device *pdev)
+{
+       struct vidc_core *core;
+       int empty;
+
+       core = platform_get_drvdata(pdev);
+       if (!core)
+               return -EINVAL;
+
+       vidc_hfi_deinit(core->hfi_type, core->hfidev);
+       vdec_deinit(core, &core->vdev_dec);
+       venc_deinit(core, &core->vdev_enc);
+       v4l2_device_unregister(&core->v4l2_dev);
+
+       put_platform_resources(core);
+
+       mutex_lock(&vidc_driver->lock);
+       list_del(&core->list);
+       empty = list_empty(&vidc_driver->cores);
+       mutex_unlock(&vidc_driver->lock);
+
+       vidc_firmware_unload(core);
+
+       if (!empty)
+               return 0;
+
+       debugfs_remove_recursive(vidc_driver->debugfs_root);
+       kfree(vidc_driver);
+       vidc_driver = NULL;
+
+       return 0;
+}
+
+static int vidc_pm_suspend(struct device *dev)
+{
+       struct vidc_core *core = dev_get_drvdata(dev);
+
+       if (!core)
+               return -EINVAL;
+
+       return hfi_core_suspend(core);
+}
+
+static int vidc_pm_resume(struct device *dev)
+{
+       return 0;
+}
+
+static const struct dev_pm_ops vidc_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(vidc_pm_suspend, vidc_pm_resume)
+};
+
+static struct platform_driver qcom_vidc_driver = {
+       .probe = vidc_probe,
+       .remove = vidc_remove,
+       .driver = {
+               .name = "qcom-vidc",
+               .of_match_table = vidc_dt_match,
+               .pm = &vidc_pm_ops,
+       },
+};
+
+module_platform_driver(qcom_vidc_driver);
+
+MODULE_ALIAS("platform:qcom-vidc");
+MODULE_DESCRIPTION("Qualcomm video decoder driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/vidc/msm_vdec-ctrls.c b/drivers/media/platform/msm/vidc/msm_vdec-ctrls.c
new file mode 100644 (file)
index 0000000..bd43642
--- /dev/null
@@ -0,0 +1,1195 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/cpumask.h>
+#include <linux/types.h>
+#include <linux/v4l2-controls.h>
+#include <linux/qcom_scm.h>
+#include <media/msm-v4l2-controls.h>
+#include <linux/kernel.h>
+
+#include "msm_vidc_debug.h"
+#include "msm_vidc_common.h"
+#include "msm_vidc_load.h"
+#include "msm_hfi_interface.h"
+
+#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK      0x8010
+#define TZ_DYNAMIC_BUFFER_FEATURE_ID           12
+#define TZ_FEATURE_VERSION(major, minor, patch) \
+       (((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF))
+
+static const char *const mpeg_video_vidc_divx_format[] = {
+       "DIVX Format 4",
+       "DIVX Format 5",
+       "DIVX Format 6",
+       NULL
+};
+static const char *mpeg_video_stream_format[] = {
+       "NAL Format Start Codes",
+       "NAL Format One NAL Per Buffer",
+       "NAL Format One Byte Length",
+       "NAL Format Two Byte Length",
+       "NAL Format Four Byte Length",
+       NULL
+};
+static const char *const mpeg_video_output_order[] = {
+       "Display Order",
+       "Decode Order",
+       NULL
+};
+static const char *const mpeg_video_vidc_extradata[] = {
+       "Extradata none",
+       "Extradata MB Quantization",
+       "Extradata Interlace Video",
+       "Extradata VC1 Framedisp",
+       "Extradata VC1 Seqdisp",
+       "Extradata timestamp",
+       "Extradata S3D Frame Packing",
+       "Extradata Frame Rate",
+       "Extradata Panscan Window",
+       "Extradata Recovery point SEI",
+       "Extradata Closed Caption UD",
+       "Extradata AFD UD",
+       "Extradata Multislice info",
+       "Extradata number of concealed MB",
+       "Extradata metadata filler",
+       "Extradata input crop",
+       "Extradata digital zoom",
+       "Extradata aspect ratio",
+       "Extradata mpeg2 seqdisp",
+};
+static const char *const mpeg_vidc_video_alloc_mode_type[] = {
+       "Buffer Allocation Static",
+       "Buffer Allocation Ring Buffer",
+       "Buffer Allocation Dynamic Buffer"
+};
+
+static const char *const perf_level[] = {
+       "Nominal",
+       "Performance",
+       "Turbo"
+};
+
+static const char *const h263_level[] = {
+       "1.0",
+       "2.0",
+       "3.0",
+       "4.0",
+       "4.5",
+       "5.0",
+       "6.0",
+       "7.0",
+};
+
+static const char *const h263_profile[] = {
+       "Baseline",
+       "H320 Coding",
+       "Backward Compatible",
+       "ISWV2",
+       "ISWV3",
+       "High Compression",
+       "Internet",
+       "Interlace",
+       "High Latency",
+};
+
+static const char *const vp8_profile_level[] = {
+       "Unused",
+       "0.0",
+       "1.0",
+       "2.0",
+       "3.0",
+};
+
+static const char *const mpeg2_profile[] = {
+       "Simple",
+       "Main",
+       "422",
+       "SNR scalable",
+       "Spatial scalable",
+       "High",
+};
+
+static const char *const mpeg2_level[] = {
+       "Level 0",
+       "Level 1",
+       "Level 2",
+       "Level 3",
+};
+
+static const char *const mpeg_vidc_video_h264_mvc_layout[] = {
+       "Frame packing arrangement sequential",
+       "Frame packing arrangement top-bottom",
+};
+
+static struct vidc_ctrl vdec_ctrls[] = {
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT,
+               .name = "NAL Format",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES,
+               .menu_skip_mask = ~(
+               (1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_ONE_NAL_PER_BUFFER) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_ONE_BYTE_LENGTH) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH)
+               ),
+               .qmenu = mpeg_video_stream_format,
+               .step = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER,
+               .name = "Output Order",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE)
+                       ),
+               .qmenu = mpeg_video_output_order,
+               .step = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_PICTURE_TYPE,
+               .name = "Picture Type Decoding",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 15,
+               .default_value = 15,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO,
+               .name = "Keep Aspect Ratio",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_POST_LOOP_DEBLOCKER_MODE,
+               .name = "Deblocker Mode",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT,
+               .name = "Divx Format",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6)
+                       ),
+               .qmenu = mpeg_video_vidc_divx_format,
+               .step = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_MB_ERROR_MAP_REPORTING,
+               .name = "MB Error Map Reporting",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER,
+               .name = "Smooth streamng",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE,
+               .name = "Sync Frame Decode",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_DISABLE,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_DISABLE,
+               .step = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE,
+               .name = "Secure mode",
+               .type = V4L2_CTRL_TYPE_BUTTON,
+               .minimum = 0,
+               .maximum = 0,
+               .default_value = 0,
+               .step = 0,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA,
+               .name = "Extradata Type",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
+               .maximum = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO,
+               .default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_MB_QUANTIZATION) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_VC1_FRAMEDISP) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO)
+                       ),
+               .qmenu = mpeg_video_vidc_extradata,
+               .step = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_INPUT,
+               .name = "Buffer allocation mode for input",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_STATIC,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_DYNAMIC,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_STATIC,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDC_VIDEO_STATIC) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_RING) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_DYNAMIC)
+                       ),
+               .qmenu = mpeg_vidc_video_alloc_mode_type,
+               .step = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT,
+               .name = "Buffer allocation mode for output",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_STATIC,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_DYNAMIC,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_STATIC,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDC_VIDEO_STATIC) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_RING) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_DYNAMIC)
+                       ),
+               .qmenu = mpeg_vidc_video_alloc_mode_type,
+               .step = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY,
+               .name = "Video frame assembly",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE,
+               .maximum = V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE,
+               .default_value =  V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE,
+               .name = "Video decoder multi stream",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY,
+               .maximum = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY,
+               .default_value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY,
+               .menu_skip_mask = 0,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
+               .name = "MPEG4 Profile",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
+               .maximum =
+               V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY,
+               .default_value = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
+               .menu_skip_mask = 0,
+               .flags = V4L2_CTRL_FLAG_VOLATILE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
+               .name = "MPEG4 Level",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
+               .maximum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
+               .default_value = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
+               .menu_skip_mask = 0,
+               .flags = V4L2_CTRL_FLAG_VOLATILE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+               .name = "H264 Profile",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
+               .default_value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+               .menu_skip_mask = 0,
+               .flags = V4L2_CTRL_FLAG_VOLATILE,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+               .name = "H264 Level",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .maximum = V4L2_MPEG_VIDEO_H264_LEVEL_5_2,
+               .default_value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+               .menu_skip_mask = 0,
+               .flags = V4L2_CTRL_FLAG_VOLATILE,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE,
+               .name = "H263 Profile",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE,
+               .menu_skip_mask = ~(
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_H320CODING) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BACKWARDCOMPATIBLE) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV2) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV3) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHCOMPRESSION) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERNET) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERLACE) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY)
+               ),
+               .qmenu = h263_profile,
+               .flags = V4L2_CTRL_FLAG_VOLATILE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL,
+               .name = "H263 Level",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0,
+               .menu_skip_mask = ~(
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_2_0) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_3_0) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_0) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_5_0) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_6_0) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0)
+               ),
+               .qmenu = h263_level,
+               .flags = V4L2_CTRL_FLAG_VOLATILE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL,
+               .name = "VP8 Profile Level",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1)
+               ),
+               .qmenu = vp8_profile_level,
+               .flags = V4L2_CTRL_FLAG_VOLATILE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE,
+               .name = "MPEG2 Profile",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_SIMPLE,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_HIGH,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_SIMPLE,
+               .menu_skip_mask = 0,
+               .qmenu = mpeg2_profile,
+               .flags = V4L2_CTRL_FLAG_VOLATILE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL,
+               .name = "MPEG2 Level",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_0,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_3,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_0,
+               .menu_skip_mask = 0,
+               .qmenu = mpeg2_level,
+               .flags = V4L2_CTRL_FLAG_VOLATILE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_SCS_THRESHOLD,
+               .name = "Video start code search threshold",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = INT_MAX,
+               .default_value = INT_MAX,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT,
+               .name = "MVC buffer layout",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_MVC_SEQUENTIAL,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDC_VIDEO_MVC_SEQUENTIAL) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM)
+                       ),
+               .qmenu = mpeg_vidc_video_h264_mvc_layout,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR,
+               .name = "Picture concealed color",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0x0,
+               .maximum = 0xffffff,
+               .default_value = DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
+               .step = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD,
+               .name = "Secure scaling output2 threshold",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+               .flags = V4L2_CTRL_FLAG_VOLATILE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2,
+               .name = "Non-Secure output2",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+};
+
+#define NUM_CTRLS      ARRAY_SIZE(vdec_ctrls)
+
+#define IS_PRIV_CTRL(idx)      ( \
+               (V4L2_CTRL_ID2CLASS(idx) == V4L2_CTRL_CLASS_MPEG) && \
+               V4L2_CTRL_DRIVER_PRIV(idx))
+
+static int check_tz_dynamic_buffer_support(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       int version = qcom_scm_get_feat_version(TZ_DYNAMIC_BUFFER_FEATURE_ID);
+
+       /*
+        * if the version is < 1.1.0 then dynamic buffer allocation is
+        * not supported
+        */
+       if (version < TZ_FEATURE_VERSION(1, 1, 0)) {
+               dev_dbg(dev, "dynamic buffer mode not supported, "
+                       "tz version is %u vs required %u\n",
+                       version, TZ_FEATURE_VERSION(1, 1, 0));
+               return -ENOTSUPP;
+       }
+
+       return 0;
+}
+
+static enum hal_buffer_mode_type get_buf_type(int val)
+{
+       switch (val) {
+       case V4L2_MPEG_VIDC_VIDEO_STATIC:
+               return HAL_BUFFER_MODE_STATIC;
+       case V4L2_MPEG_VIDC_VIDEO_RING:
+               return HAL_BUFFER_MODE_RING;
+       case V4L2_MPEG_VIDC_VIDEO_DYNAMIC:
+               return HAL_BUFFER_MODE_DYNAMIC;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int is_ctrl_valid_for_codec(struct vidc_inst *inst,
+                                  struct v4l2_ctrl *ctrl)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT:
+               if (inst->fmt_out->pixfmt != V4L2_PIX_FMT_H264_MVC) {
+                       dev_err(dev, "control %x only valid for MVC\n",
+                               ctrl->id);
+                       ret = -ENOTSUPP;
+                       break;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               if (inst->fmt_out->pixfmt == V4L2_PIX_FMT_H264_MVC &&
+                       ctrl->val != V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) {
+                       dev_err(dev, "Profile %x not supported for MVC\n",
+                               ctrl->val);
+                       ret = -ENOTSUPP;
+                       break;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               if (inst->fmt_out->pixfmt == V4L2_PIX_FMT_H264_MVC &&
+                       ctrl->val >= V4L2_MPEG_VIDEO_H264_LEVEL_5_2) {
+                       dev_err(dev, "Level %x not supported for MVC\n",
+                               ctrl->val);
+                       ret = -ENOTSUPP;
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static int try_get_ctrl(struct vidc_inst *inst, struct v4l2_ctrl *ctrl)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hal_profile_level profile_level;
+       union hal_get_property hprop;
+       int ret = 0;
+
+       dev_dbg(dev, "get ctrl id: %x\n", ctrl->id);
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+       case V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE:
+       case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
+       case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE:
+               ret = hfi_session_get_property(inst,
+                                              HAL_PARAM_PROFILE_LEVEL_CURRENT,
+                                              &hprop);
+               if (ret) {
+                       dev_err(dev, "getting profile property (%d)\n", ret);
+                       return ret;
+               }
+
+               profile_level = hprop.profile_level;
+               ctrl->val = profile_level.profile;
+               dev_dbg(dev, "PROFILE ctrl->id:%x ctrl->val:%d\n",
+                       ctrl->id, ctrl->val);
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+       case V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL:
+       case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL:
+               ret = hfi_session_get_property(inst,
+                                              HAL_PARAM_PROFILE_LEVEL_CURRENT,
+                                              &hprop);
+               if (ret) {
+                       dev_err(dev, "getting level property(%d)\n", ret);
+                       return ret;
+               }
+
+               profile_level = hprop.profile_level;
+               ctrl->val = profile_level.level;
+               dev_dbg(dev, "LEVEL ctrl->id:%x ctrl->val:%d\n",
+                       ctrl->id, ctrl->val);
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD:
+               if (!(inst->flags & VIDC_SECURE) ||
+                   !inst->capability.secure_output2_threshold.max) {
+                       dprintk(VIDC_ERR, "%s id:%x invalid configuration\n",
+                               __func__, ctrl->id);
+                       ret = -EINVAL;
+                       break;
+               }
+               dev_dbg(dev, "Secure Scaling Threshold is %d",
+                       inst->capability.secure_output2_threshold.max);
+               ctrl->val = inst->capability.secure_output2_threshold.max;
+               break;
+       default:
+               dev_dbg(dev, "ctrl id: %x not supported\n", ctrl->id);
+               break;
+       }
+
+       return ret;
+}
+
+static int vdec_v4l2_to_hal(int id, int value)
+{
+       switch (id) {
+               /* H264 */
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               switch (value) {
+               case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+                       return HAL_H264_PROFILE_BASELINE;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+                       return HAL_H264_PROFILE_CONSTRAINED_BASE;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+                       return HAL_H264_PROFILE_MAIN;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
+                       return HAL_H264_PROFILE_EXTENDED;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+                       return HAL_H264_PROFILE_HIGH;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
+                       return HAL_H264_PROFILE_HIGH10;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
+                       return HAL_H264_PROFILE_HIGH422;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
+                       return HAL_H264_PROFILE_HIGH444;
+               default:
+                       return -EINVAL;
+               }
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               switch (value) {
+               case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
+                       return HAL_H264_LEVEL_1;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
+                       return HAL_H264_LEVEL_1b;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
+                       return HAL_H264_LEVEL_11;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
+                       return HAL_H264_LEVEL_12;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
+                       return HAL_H264_LEVEL_13;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
+                       return HAL_H264_LEVEL_2;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
+                       return HAL_H264_LEVEL_21;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
+                       return HAL_H264_LEVEL_22;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
+                       return HAL_H264_LEVEL_3;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
+                       return HAL_H264_LEVEL_31;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
+                       return HAL_H264_LEVEL_32;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
+                       return HAL_H264_LEVEL_4;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
+                       return HAL_H264_LEVEL_41;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
+                       return HAL_H264_LEVEL_42;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
+                       return HAL_H264_LEVEL_5;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
+                       return HAL_H264_LEVEL_51;
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static struct v4l2_ctrl *
+get_ctrl_from_cluster(int id, struct v4l2_ctrl **cluster, int ncontrols)
+{
+       int c;
+
+       for (c = 0; c < ncontrols; ++c)
+               if (cluster[c]->id == id)
+                       return cluster[c];
+
+       return NULL;
+}
+
+/* Small helper macro for quickly getting a control and err checking */
+#define TRY_GET_CTRL(__ctrl_id) ({ \
+               struct v4l2_ctrl *__temp; \
+               __temp = get_ctrl_from_cluster( \
+                       __ctrl_id, \
+                       ctrl->cluster, ctrl->ncontrols); \
+               if (!__temp) { \
+                       dprintk(VIDC_ERR, "Can't find %s (%x) in cluster\n", \
+                               #__ctrl_id, __ctrl_id); \
+                       /* Clusters are hardcoded, if we can't find */ \
+                       /* something then things are massively screwed up */ \
+                       BUG_ON(1); \
+               } \
+               __temp; \
+       })
+
+static int try_set_ctrl(struct vidc_inst *inst, struct v4l2_ctrl *ctrl)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hal_nal_stream_format_supported stream_format;
+       struct hal_enable_picture enable_picture;
+       struct hal_enable hal_property;
+       struct hal_extradata_enable extra;
+       struct hal_buffer_alloc_mode alloc_mode;
+       struct hal_multi_stream multi_stream;
+       struct hfi_scs_threshold scs_threshold;
+       struct hal_mvc_buffer_layout layout;
+       struct v4l2_ctrl *temp_ctrl = NULL;
+       struct hal_profile_level profile_level;
+       struct hal_frame_size frame_sz;
+       enum hal_property prop_id = 0;
+       u32 property_val = 0;
+       void *pdata = NULL;
+       int ret = 0;
+
+       ret = is_ctrl_valid_for_codec(inst, ctrl);
+       if (ret)
+               return ret;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT:
+               prop_id = HAL_PARAM_NAL_STREAM_FORMAT_SELECT;
+               stream_format.nal_stream_format_supported =
+                                       (0x00000001 << ctrl->val);
+               pdata = &stream_format;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER:
+               prop_id = HAL_PARAM_VDEC_OUTPUT_ORDER;
+               property_val = ctrl->val;
+               pdata = &property_val;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_PICTURE_TYPE:
+               prop_id = HAL_PARAM_VDEC_PICTURE_TYPE_DECODE;
+               enable_picture.picture_type = ctrl->val;
+               pdata = &enable_picture;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO:
+               prop_id = HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO;
+               hal_property.enable = ctrl->val;
+               pdata = &hal_property;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_POST_LOOP_DEBLOCKER_MODE:
+               prop_id = HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
+               hal_property.enable = ctrl->val;
+               pdata = &hal_property;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT:
+               prop_id = HAL_PARAM_DIVX_FORMAT;
+               property_val = ctrl->val;
+               pdata = &property_val;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_MB_ERROR_MAP_REPORTING:
+               prop_id = HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING;
+               hal_property.enable = ctrl->val;
+               pdata = &hal_property;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER:
+               prop_id = HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
+               hal_property.enable = ctrl->val;
+               pdata = &hal_property;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE:
+               switch (ctrl->val) {
+               case V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_DISABLE:
+                       inst->flags &= ~VIDC_THUMBNAIL;
+                       break;
+               case V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE:
+                       inst->flags |= VIDC_THUMBNAIL;
+                       break;
+               }
+
+               prop_id = HAL_PARAM_VDEC_SYNC_FRAME_DECODE;
+               hal_property.enable = ctrl->val;
+               pdata = &hal_property;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
+               inst->flags |= VIDC_SECURE;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA:
+               prop_id = HAL_PARAM_INDEX_EXTRADATA;
+               extra.index = vidc_comm_get_hal_extradata_index(ctrl->val);
+               extra.enable = 1;
+               pdata = &extra;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_INPUT:
+               if (ctrl->val == V4L2_MPEG_VIDC_VIDEO_DYNAMIC) {
+                       ret = -ENOTSUPP;
+                       break;
+               }
+               prop_id = HAL_PARAM_BUFFER_ALLOC_MODE;
+               alloc_mode.mode = get_buf_type(ctrl->val);
+               alloc_mode.type = HAL_BUFFER_INPUT;
+               inst->buffer_mode[OUTPUT_PORT] = alloc_mode.mode;
+               pdata = &alloc_mode;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY:
+               prop_id = HAL_PARAM_VDEC_FRAME_ASSEMBLY;
+               hal_property.enable = ctrl->val;
+               pdata = &hal_property;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT:
+               prop_id = HAL_PARAM_BUFFER_ALLOC_MODE;
+               alloc_mode.mode = get_buf_type(ctrl->val);
+
+               if (!(alloc_mode.mode &
+                       inst->capability.buffer_mode[CAPTURE_PORT])) {
+                       ret = -ENOTSUPP;
+                       break;
+               }
+
+               if (alloc_mode.mode == HAL_BUFFER_MODE_DYNAMIC &&
+                   (inst->flags & VIDC_SECURE) &&
+                   check_tz_dynamic_buffer_support(inst)) {
+                               ret = -ENOTSUPP;
+                               break;
+               }
+
+               alloc_mode.type = HAL_BUFFER_OUTPUT;
+               pdata = &alloc_mode;
+               inst->buffer_mode[CAPTURE_PORT] = alloc_mode.mode;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE:
+               if (ctrl->val && !(inst->capability.pixelprocess_capabilities &
+                   HAL_VIDEO_DECODER_MULTI_STREAM_CAPABILITY)) {
+                       dev_err(dev, "Downscaling not supported: %#x\n",
+                               ctrl->id);
+                       ret = -ENOTSUPP;
+                       break;
+               }
+               switch (ctrl->val) {
+               case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY:
+                       multi_stream.buffer_type = HAL_BUFFER_OUTPUT;
+                       multi_stream.enable = true;
+                       pdata = &multi_stream;
+                       prop_id = HAL_PARAM_VDEC_MULTI_STREAM;
+
+                       ret = hfi_session_set_property(inst, prop_id, pdata);
+                       if (ret) {
+                               dev_err(dev, "enabling OUTPUT port (%d)\n",
+                                       ret);
+                               break;
+                       }
+                       multi_stream.buffer_type = HAL_BUFFER_OUTPUT2;
+                       multi_stream.enable = false;
+                       pdata = &multi_stream;
+
+                       ret = hfi_session_set_property(inst, prop_id, pdata);
+                       if (ret)
+                               dev_err(dev, "disabling OUTPUT2 port (%d)\n",
+                                       ret);
+                       break;
+               case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY:
+                       multi_stream.buffer_type = HAL_BUFFER_OUTPUT2;
+                       multi_stream.enable = true;
+                       pdata = &multi_stream;
+                       prop_id = HAL_PARAM_VDEC_MULTI_STREAM;
+
+                       ret = hfi_session_set_property(inst, prop_id, pdata);
+                       if (ret) {
+                               dev_err(dev, "enabling OUTPUT2 port (%d)\n",
+                                       ret);
+                                       break;
+                       }
+                       multi_stream.buffer_type = HAL_BUFFER_OUTPUT;
+                       multi_stream.enable = false;
+                       pdata = &multi_stream;
+
+                       ret = hfi_session_set_property(inst, prop_id, pdata);
+                       if (ret) {
+                               dev_err(dev, "disabling OUTPUT port (%d)\n",
+                                       ret);
+                               break;
+                       }
+
+                       frame_sz.buffer_type = HAL_BUFFER_OUTPUT2;
+                       frame_sz.width = inst->width;
+                       frame_sz.height = inst->height;
+                       pdata = &frame_sz;
+                       prop_id = HAL_PARAM_FRAME_SIZE;
+
+                       dev_dbg(dev, "buftype: %d width: %d, height: %d\n",
+                               frame_sz.buffer_type, frame_sz.width,
+                               frame_sz.height);
+
+                       ret = hfi_session_set_property(inst, prop_id, pdata);
+                       if (ret)
+                               dev_err(dev, "setting OUTPUT2 size (%d)\n",
+                                       ret);
+                       break;
+               default:
+                       dev_err(dev, "unsupported multi stream setting\n");
+                       ret = -ENOTSUPP;
+                       break;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_SCS_THRESHOLD:
+               prop_id = HAL_PARAM_VDEC_SCS_THRESHOLD;
+               scs_threshold.threshold_value = ctrl->val;
+               pdata = &scs_threshold;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT:
+               prop_id = HAL_PARAM_MVC_BUFFER_LAYOUT;
+               layout.layout_type = vidc_comm_get_hal_buffer_layout(ctrl->val);
+               layout.bright_view_first = 0;
+               layout.ngap = 0;
+               pdata = &layout;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR:
+               prop_id = HAL_PARAM_VDEC_CONCEAL_COLOR;
+               property_val = ctrl->val;
+               pdata = &property_val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_LEVEL);
+               prop_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.profile = vdec_v4l2_to_hal(ctrl->id, ctrl->val);
+               profile_level.level =
+                       vdec_v4l2_to_hal(V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+                                        temp_ctrl->val);
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_PROFILE);
+               prop_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.level = vdec_v4l2_to_hal(ctrl->id, ctrl->val);
+               profile_level.profile =
+                       vdec_v4l2_to_hal(V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+                                        temp_ctrl->val);
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2:
+               prop_id = HAL_PARAM_VDEC_NON_SECURE_OUTPUT2;
+               hal_property.enable = ctrl->val;
+               dev_dbg(dev, "%s non_secure output2\n",
+                       ctrl->val ? "Enabling" : "Disabling");
+               pdata = &hal_property;
+               break;
+       default:
+               break;
+       }
+
+       if (!ret && prop_id) {
+               dev_dbg(dev,
+                       "Control: HAL property=%x, ctrl: id=%x, value=%x\n",
+                       prop_id, ctrl->id, ctrl->val);
+
+               ret = hfi_session_set_property(inst, prop_id, pdata);
+       }
+
+       return ret;
+}
+
+static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct vidc_inst *inst =
+               container_of(ctrl->handler, struct vidc_inst, ctrl_handler);
+       struct device *dev = &inst->core->res.pdev->dev;
+       int ret = 0, c = 0;
+
+       for (c = 0; c < ctrl->ncontrols; ++c) {
+               if (ctrl->cluster[c]->is_new) {
+                       ret = try_set_ctrl(inst, ctrl->cluster[c]);
+                       if (ret) {
+                               dprintk(VIDC_ERR, "Failed setting %x\n",
+                                       ctrl->cluster[c]->id);
+                               break;
+                       }
+               }
+       }
+
+       if (ret)
+               dev_err(dev, "setting control: %x (%s)",
+                       ctrl->id, v4l2_ctrl_get_name(ctrl->id));
+
+       return ret;
+}
+
+static int vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct vidc_inst *inst =
+               container_of(ctrl->handler, struct vidc_inst, ctrl_handler);
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct v4l2_ctrl *master = ctrl->cluster[0];
+       int ret, c;
+
+       for (c = 0; c < master->ncontrols; ++c) {
+               int d;
+
+               for (d = 0; d < NUM_CTRLS; ++d) {
+                       if (master->cluster[c]->id == inst->ctrls[d]->id &&
+                           inst->ctrls[d]->flags & V4L2_CTRL_FLAG_VOLATILE) {
+                               ret = try_get_ctrl(inst, master->cluster[c]);
+                               if (ret) {
+                                       dev_err(dev, "getting %x\n",
+                                               master->cluster[c]->id);
+                                       return ret;
+                               }
+                               break;
+                       }
+               }
+       }
+
+       return ret;
+}
+
+static const struct v4l2_ctrl_ops vdec_ctrl_ops = {
+       .s_ctrl = vdec_op_s_ctrl,
+       .g_volatile_ctrl = vdec_op_g_volatile_ctrl,
+};
+
+static struct v4l2_ctrl **get_super_cluster(struct vidc_inst *inst, int *size)
+{
+       int c = 0, sz = 0;
+       struct v4l2_ctrl **cluster = kmalloc(sizeof(struct v4l2_ctrl *) *
+                                            NUM_CTRLS, GFP_KERNEL);
+
+       if (!size || !cluster || !inst)
+               return NULL;
+
+       for (c = 0; c < NUM_CTRLS; c++)
+               cluster[sz++] = inst->ctrls[c];
+
+       *size = sz;
+       return cluster;
+}
+
+int vdec_ctrl_init(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct v4l2_ctrl_config cfg;
+       int cluster_size = 0;
+       int idx = 0;
+       int ret = 0;
+
+       inst->ctrls = kzalloc(sizeof(struct v4l2_ctrl *) * NUM_CTRLS,
+                             GFP_KERNEL);
+       if (!inst->ctrls)
+               return -ENOMEM;
+
+       ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, NUM_CTRLS);
+       if (ret) {
+               dev_err(dev, "control handler init (%d)\n", ret);
+               return ret;
+       }
+
+       for (; idx < NUM_CTRLS; idx++) {
+               struct v4l2_ctrl *ctrl = NULL;
+
+               if (IS_PRIV_CTRL(vdec_ctrls[idx].id)) {
+                       memset(&cfg, 0, sizeof(cfg));
+                       cfg.def = vdec_ctrls[idx].default_value;
+                       cfg.flags = 0;
+                       cfg.id = vdec_ctrls[idx].id;
+                       /* cfg.is_private = vdec_ctrls[idx].is_private;
+                        * cfg.is_volatile = vdec_ctrls[idx].is_volatile;
+                        */
+                       cfg.max = vdec_ctrls[idx].maximum;
+                       cfg.min = vdec_ctrls[idx].minimum;
+                       cfg.menu_skip_mask = vdec_ctrls[idx].menu_skip_mask;
+                       cfg.name = vdec_ctrls[idx].name;
+                       cfg.ops = &vdec_ctrl_ops;
+                       cfg.step = vdec_ctrls[idx].step;
+                       cfg.type = vdec_ctrls[idx].type;
+                       cfg.qmenu = vdec_ctrls[idx].qmenu;
+
+                       ctrl = v4l2_ctrl_new_custom(&inst->ctrl_handler, &cfg,
+                                                   NULL);
+               } else {
+                       if (vdec_ctrls[idx].type == V4L2_CTRL_TYPE_MENU) {
+                               ctrl = v4l2_ctrl_new_std_menu(
+                                       &inst->ctrl_handler,
+                                       &vdec_ctrl_ops,
+                                       vdec_ctrls[idx].id,
+                                       vdec_ctrls[idx].maximum,
+                                       vdec_ctrls[idx].menu_skip_mask,
+                                       vdec_ctrls[idx].default_value);
+                       } else {
+                               ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler,
+                                       &vdec_ctrl_ops,
+                                       vdec_ctrls[idx].id,
+                                       vdec_ctrls[idx].minimum,
+                                       vdec_ctrls[idx].maximum,
+                                       vdec_ctrls[idx].step,
+                                       vdec_ctrls[idx].default_value);
+                       }
+               }
+
+               if (!ctrl) {
+                       dev_err(dev, "invalid ctrl\n");
+                       return -EINVAL;
+               }
+
+               switch (vdec_ctrls[idx].id) {
+               case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+               case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+               case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               case V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE:
+               case V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL:
+               case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
+               case V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD:
+                       ctrl->flags |= vdec_ctrls[idx].flags;
+                       break;
+               }
+
+               ret = inst->ctrl_handler.error;
+               if (ret) {
+                       dev_err(dev, "adding ctrl (%s) to ctrl handle (%d)\n",
+                               vdec_ctrls[idx].name,
+                               inst->ctrl_handler.error);
+                       return ret;
+               }
+
+               inst->ctrls[idx] = ctrl;
+       }
+
+       /* Construct a super cluster of all controls */
+       inst->cluster = get_super_cluster(inst, &cluster_size);
+       if (!inst->cluster || !cluster_size) {
+               dev_err(dev, "setup super cluster\n");
+               return -EINVAL;
+       }
+
+       v4l2_ctrl_cluster(cluster_size, inst->cluster);
+
+       return ret;
+}
+
+void vdec_ctrl_deinit(struct vidc_inst *inst)
+{
+       kfree(inst->ctrls);
+       kfree(inst->cluster);
+       v4l2_ctrl_handler_free(&inst->ctrl_handler);
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vdec-ctrls.h b/drivers/media/platform/msm/vidc/msm_vdec-ctrls.h
new file mode 100644 (file)
index 0000000..e344f23
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _MSM_VDEC_CTRLS_H_
+#define _MSM_VDEC_CTRLS_H_
+
+int vdec_ctrl_init(struct vidc_inst *inst);
+void vdec_ctrl_deinit(struct vidc_inst *inst);
+
+#endif /* _MSM_VDEC_CTRLS_H_ */
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
new file mode 100644 (file)
index 0000000..7ed57ea
--- /dev/null
@@ -0,0 +1,1565 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/qcom_scm.h>
+#include <linux/qcom_iommu.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "msm_vdec.h"
+#include "msm_vdec-ctrls.h"
+#include "msm_vidc_internal.h"
+#include "msm_internal-buffers.h"
+#include "msm_vidc_common.h"
+#include "msm_vidc_load.h"
+#include "hfi/vidc_hfi_api.h"
+#include "msm_vidc_debug.h"
+#include "msm_hfi_interface.h"
+
+#define MIN_NUM_OUTPUT_BUFFERS         4
+#define MAX_NUM_OUTPUT_BUFFERS         VIDEO_MAX_FRAME
+#define MB_SIZE_IN_PIXEL               (16 * 16)
+
+/* Offset base for buffers on the destination queue - used to distinguish
+ * between source and destination buffers when mmapping - they receive the same
+ * offsets but for different queues */
+#define DST_QUEUE_OFF_BASE     (1 << 30)
+
+struct vdec_buffer {
+       struct vb2_buffer vb;
+       struct list_head list;
+       dma_addr_t dma_addr;
+       struct buffer_info bi;
+};
+
+#define to_vdec_buffer(buf)    container_of(buf, struct vdec_buffer, vb)
+
+static inline struct vidc_inst *to_inst(struct file *filp, void *fh)
+{
+       return container_of(filp->private_data, struct vidc_inst, fh);
+}
+
+static u32 get_framesize_nv12(int plane, u32 height, u32 width)
+{
+       u32 y_stride, uv_stride, y_plane;
+       u32 y_sclines, uv_sclines, uv_plane;
+       u32 size;
+
+       y_stride = ALIGN(width, 128);
+       uv_stride = ALIGN(width, 128);
+       y_sclines = ALIGN(height, 32);
+       uv_sclines = ALIGN(((height + 1) >> 1), 16);
+
+       y_plane = y_stride * y_sclines;
+       uv_plane = uv_stride * uv_sclines + SZ_4K;
+       size = y_plane + uv_plane + SZ_8K;
+       size = ALIGN(size, SZ_4K);
+
+       return size;
+}
+
+static u32 get_framesize_compressed(int plane, u32 mbs_per_frame,
+                                    u32 size_per_mb)
+{
+       return (mbs_per_frame * size_per_mb * 3 / 2) / 2;
+}
+
+static u32 get_framesize(struct vidc_inst *inst, const struct vidc_format *fmt,
+                        u32 fmt_type, u32 plane)
+{
+       struct vidc_core_capability *cap = &inst->capability;
+
+       if (fmt_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return fmt->get_framesize(plane, cap->mbs_per_frame.max,
+                                         MB_SIZE_IN_PIXEL);
+       else if (fmt_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return fmt->get_framesize(plane, inst->height, inst->width);
+
+       return 0;
+}
+
+static const struct vidc_format vdec_formats[] = {
+       {
+               .pixfmt = V4L2_PIX_FMT_NV12,
+               .num_planes = 1,
+               .get_framesize = get_framesize_nv12,
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_NV21,
+               .num_planes = 1,
+               .get_framesize = get_framesize_nv12,
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_MPEG4,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_MPEG2,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_H263,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_H264,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_VP8,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+};
+
+static const struct vidc_format *find_format(u32 pixfmt, u32 type)
+{
+       const struct vidc_format *fmt = vdec_formats;
+       unsigned int size = ARRAY_SIZE(vdec_formats);
+       unsigned int i;
+
+       for (i = 0; i < size; i++) {
+               if (fmt[i].pixfmt == pixfmt)
+                       break;
+       }
+
+       if (i == size || fmt[i].type != type)
+               return NULL;
+
+       return &fmt[i];
+}
+
+
+static const struct vidc_format *find_format_by_index(int index, u32 type)
+{
+       const struct vidc_format *fmt = vdec_formats;
+       unsigned int size = ARRAY_SIZE(vdec_formats);
+       int i, k = 0;
+
+       if (index < 0 || index > size)
+               return NULL;
+
+       for (i = 0; i < size; i++) {
+               if (fmt[i].type != type)
+                       continue;
+               if (k == index)
+                       break;
+               k++;
+       }
+
+       if (i == size)
+               return NULL;
+
+       return &fmt[i];
+}
+
+static struct vb2_queue *
+vdec_to_vb2q(struct vidc_inst *inst, enum v4l2_buf_type type)
+{
+       if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return &inst->bufq_cap;
+       else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return &inst->bufq_out;
+
+       return NULL;
+}
+
+static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
+       const struct vidc_format *fmt;
+       struct vidc_core_capability *cap = &inst->capability;
+       struct hfi_device *hdev = inst->core->hfidev;
+       int ret, i;
+
+       fmt = find_format(pixmp->pixelformat, f->type);
+       if (!fmt)
+               return -EINVAL;
+
+       ret = hfi_session_init(inst, inst->fmt_out->pixfmt);
+       if (ret)
+               return ret;
+
+       pixmp->width = clamp(pixmp->width, cap->width.min, cap->width.max);
+       pixmp->height = clamp(pixmp->height, cap->height.min, cap->height.max);
+       pixmp->field = V4L2_FIELD_NONE;
+       pixmp->colorspace = V4L2_COLORSPACE_DEFAULT;
+       pixmp->num_planes = fmt->num_planes;
+       pixmp->flags = 0;
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               enum color_fmts cfmt;
+               u32 *bytesperline = &pixmp->plane_fmt[0].bytesperline;
+
+               switch (fmt->pixfmt) {
+               case V4L2_PIX_FMT_NV12:
+                       cfmt = COLOR_FMT_NV12;
+               case V4L2_PIX_FMT_NV21:
+                       cfmt =  COLOR_FMT_NV21;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               call_hfi_op(hdev, get_stride_scanline, cfmt, pixmp->width,
+                           pixmp->height, bytesperline, NULL);
+
+               for (i = 0; i < pixmp->num_planes; i++)
+                       pixmp->plane_fmt[i].sizeimage =
+                                       get_framesize_nv12(i, pixmp->height,
+                                                          pixmp->width);
+       } else {
+               pixmp->plane_fmt[0].sizeimage =
+                                       get_framesize(inst, fmt, f->type, 0);
+               pixmp->plane_fmt[0].bytesperline = 0;
+       }
+
+       ret = hfi_session_deinit(inst);
+
+       inst->session = NULL;
+       vidc_inst_set_state(inst, INST_UNINIT);
+
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hfi_device *hdev = inst->core->hfidev;
+       const struct vidc_format *fmt;
+       struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
+       struct hal_buffer_requirements bufreq = {0};
+       int ret, i;
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               fmt = inst->fmt_cap;
+       else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               fmt = inst->fmt_out;
+       else
+               return -EINVAL;
+
+       pixmp->pixelformat = fmt->pixfmt;
+       pixmp->num_planes = fmt->num_planes;
+
+       if (inst->in_reconfig) {
+               if (vidc_comm_get_stream_output_mode(inst) ==
+                   HAL_VIDEO_DECODER_PRIMARY) {
+                       inst->height = inst->reconfig_height;
+                       inst->width = inst->reconfig_width;
+               }
+
+               ret = vidc_check_session_supported(inst);
+               if (ret) {
+                       dev_err(dev, "%s: unsupported session\n", __func__);
+                       goto exit;
+               }
+       }
+
+       pixmp->width = inst->width;
+       pixmp->height = inst->height;
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               for (i = 0; i < fmt->num_planes; ++i) {
+                       pixmp->plane_fmt[i].sizeimage =
+                                       get_framesize(inst, fmt, f->type, i);
+                       pixmp->plane_fmt[i].bytesperline = 0;
+               }
+       } else {
+               enum color_fmts cfmt;
+               u32 bytesperline = 0;
+
+               switch (fmt->pixfmt) {
+               case V4L2_PIX_FMT_NV12:
+                       cfmt = COLOR_FMT_NV12;
+               case V4L2_PIX_FMT_NV21:
+                       cfmt =  COLOR_FMT_NV21;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               call_hfi_op(hdev, get_stride_scanline, cfmt, inst->width,
+                           inst->height, &bytesperline, NULL);
+
+               ret = vidc_comm_bufrequirements(inst, HAL_BUFFER_OUTPUT,
+                                               &bufreq);
+               if (ret)
+                       return ret;
+
+               dev_dbg(dev, "buf requirements output: size:%d\n", bufreq.size);
+
+               pixmp->plane_fmt[0].sizeimage = bufreq.size;
+               pixmp->plane_fmt[0].bytesperline = bytesperline;
+       }
+
+exit:
+       return ret;
+}
+
+static int vdec_set_buffer_size(struct vidc_inst *inst, u32 buffer_size,
+                               enum hal_buffer buffer_type)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hal_buffer_size_actual buf_size_actual;
+       int ret;
+
+       dev_dbg(dev, "set actual buffer_size: %d for buffer type %d to fw\n",
+               buffer_size, buffer_type);
+
+       buf_size_actual.type = buffer_type;
+       buf_size_actual.size = buffer_size;
+
+       ret = hfi_session_set_property(inst, HAL_PARAM_BUFFER_SIZE_ACTUAL,
+                                      &buf_size_actual);
+       if (ret) {
+               dev_err(dev, "%s: failed to set actual buffer size %u\n",
+                       __func__, buffer_size);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int vdec_update_out_buf_size(struct vidc_inst *inst,
+                                   struct v4l2_format *f, int nplanes)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct v4l2_plane_pix_format *fmt = f->fmt.pix_mp.plane_fmt;
+       struct hal_buffer_requirements *bufreq;
+       int ret, i;
+
+       /*
+        * Compare set buffer size and update to firmware if it's bigger
+        * then firmware returned buffer size.
+        */
+       for (i = 0; i < nplanes; ++i) {
+               enum hal_buffer type = vidc_comm_get_hal_output_buffer(inst);
+
+               if (EXTRADATA_IDX(nplanes) && i == EXTRADATA_IDX(nplanes))
+                       type = HAL_BUFFER_EXTRADATA_OUTPUT;
+
+               bufreq = get_buff_req_buffer(inst, type);
+               if (!bufreq)
+                       return -EINVAL;
+
+               if (fmt[i].sizeimage > bufreq->size) {
+                       ret = vdec_set_buffer_size(inst, fmt[i].sizeimage,
+                                                  type);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       /* Query buffer requirements from firmware */
+       ret = vidc_comm_get_bufreqs(inst);
+       if (ret) {
+               dev_err(dev, "Failed to get buf req, %d\n", ret);
+               return ret;
+       }
+
+       /* Read back updated firmware size */
+       for (i = 0; i < nplanes; ++i) {
+               enum hal_buffer type = vidc_comm_get_hal_output_buffer(inst);
+
+               if (EXTRADATA_IDX(nplanes) && i == EXTRADATA_IDX(nplanes))
+                       type = HAL_BUFFER_EXTRADATA_OUTPUT;
+
+               bufreq = get_buff_req_buffer(inst, type);
+               fmt[i].sizeimage = bufreq ? bufreq->size : 0;
+
+               dev_dbg(dev, "updated buffer size for plane[%d] = %d\n",
+                       i, fmt[i].sizeimage);
+       }
+
+       return 0;
+}
+
+static int vdec_set_properties(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hfi_device *hdev = inst->core->hfidev;
+       enum hal_default_properties defaults;
+       int ret;
+
+       defaults = call_hfi_op(hdev, get_default_properties,
+                              hdev->hfi_device_data);
+       if (defaults < 0)
+               return defaults;
+
+       if (defaults & HAL_VIDEO_DYNAMIC_BUF_MODE) {
+               dev_dbg(dev, "Enable dynamic buffer mode\n");
+
+               inst->buffer_mode[CAPTURE_PORT] = HAL_VIDEO_DYNAMIC_BUF_MODE;
+       }
+
+       if (defaults & HAL_VIDEO_CONTINUE_DATA_TRANSFER) {
+               struct hal_enable prop = { 1 };
+               u32 prop_id = HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
+
+               dev_dbg(dev, "Enable continue data transfer\n");
+
+               ret = hfi_session_set_property(inst, prop_id, &prop);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int vdec_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct device *dev = &inst->core->res.pdev->dev;
+       const struct vidc_format *fmt;
+       struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
+       u32 pixfmt = pixmp->pixelformat;
+       int ret, i;
+
+       fmt = find_format(pixfmt, f->type);
+       if (!fmt)
+               return -EINVAL;
+
+       ret = vidc_comm_set_color_format(inst, HAL_BUFFER_OUTPUT, pixfmt);
+       if (ret)
+               return ret;
+
+       ret = vidc_comm_get_bufreqs(inst);
+       if (ret) {
+               for (i = 0; i < fmt->num_planes; ++i)
+                       pixmp->plane_fmt[i].sizeimage =
+                               get_framesize(inst, fmt, f->type, i);
+       } else {
+               ret = vdec_update_out_buf_size(inst, f, fmt->num_planes);
+               if (ret) {
+                       dev_err(dev, "%s: failed to update buffer size: %d\n",
+                               __func__, ret);
+                       return ret;
+               }
+       }
+
+       inst->width = pixmp->width;
+       inst->height = pixmp->height;
+       inst->fmt_cap = fmt;
+
+       pixmp->num_planes = fmt->num_planes;
+
+       return 0;
+}
+
+static int vdec_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hal_frame_size fs;
+       const struct vidc_format *fmt;
+       struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
+       u32 pixfmt = pixmp->pixelformat;
+       struct vidc_core_capability *cap = &inst->capability;
+       int ret, i;
+
+       fmt = find_format(pixfmt, f->type);
+       if (!fmt)
+               return -EINVAL;
+
+       if (!(vidc_comm_hal_codec_type(fmt->pixfmt) & inst->core->dec_codecs)) {
+               dev_err(dev, "codec (%x) is not supported\n", fmt->pixfmt);
+               return -ENOTSUPP;
+       }
+
+       inst->width = pixmp->width;
+       inst->height = pixmp->height;
+       inst->fmt_out = fmt;
+
+       ret = hfi_session_init(inst, fmt->pixfmt);
+       if (ret) {
+               dev_err(dev, "%s: session init failed (%d)\n", __func__, ret);
+               return ret;
+       }
+
+       ret = vidc_check_session_supported(inst);
+       if (ret) {
+               dev_err(dev, "%s: session not supported\n", __func__);
+               goto err;
+       }
+
+       fs.buffer_type = HAL_BUFFER_INPUT;
+       fs.width = inst->width;
+       fs.height = inst->height;
+
+       ret = hfi_session_set_property(inst, HAL_PARAM_FRAME_SIZE, &fs);
+       if (ret)
+               goto err;
+
+       for (i = 0; i < fmt->num_planes; i++) {
+               pixmp->plane_fmt[i].sizeimage =
+                       fmt->get_framesize(i, cap->mbs_per_frame.max,
+                                          MB_SIZE_IN_PIXEL);
+               pixmp->plane_fmt[i].bytesperline = 0;
+       }
+
+       pixmp->num_planes = fmt->num_planes;
+
+       return 0;
+
+err:
+       hfi_session_deinit(inst);
+       inst->session = NULL;
+       vidc_inst_set_state(inst, INST_UNINIT);
+
+       return ret;
+}
+
+static int
+vdec_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = vdec_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_reqbufs(queue, b);
+}
+
+static int
+vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+       strlcpy(cap->driver, VIDC_DRV_NAME, sizeof(cap->driver));
+       strlcpy(cap->card, "video decoder", sizeof(cap->card));
+       strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
+       cap->version = VIDC_VERSION;
+
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+                           V4L2_CAP_VIDEO_OUTPUT_MPLANE |
+                           V4L2_CAP_STREAMING |
+                           V4L2_CAP_DEVICE_CAPS;
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+                          V4L2_CAP_VIDEO_OUTPUT_MPLANE |
+                          V4L2_CAP_STREAMING;
+
+       return 0;
+}
+
+static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+       const struct vidc_format *fmt;
+
+       fmt = find_format_by_index(f->index, f->type);
+
+       memset(f->reserved, 0 , sizeof(f->reserved));
+
+       if (!fmt)
+               return -EINVAL;
+
+       f->pixelformat = fmt->pixfmt;
+
+       return 0;
+}
+
+static int vdec_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+       int ret = 0, i;
+
+       if (b->memory != V4L2_MEMORY_MMAP) {
+               dprintk(VIDC_ERR, "Only MMAP bufs can be queried\n");
+               return -EINVAL;
+       }
+
+       queue = vdec_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       ret = vb2_querybuf(queue, b);
+       if (ret)
+               return ret;
+
+       if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               for (i = 0; i < b->length; i++)
+                       b->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE;
+       }
+
+       return 0;
+}
+
+static int vdec_prepare_buf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = vdec_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_prepare_buf(queue, b);
+}
+
+static int vdec_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+       unsigned int state;
+
+       queue = vdec_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       mutex_lock(&inst->lock);
+       state = inst->state;
+       mutex_unlock(&inst->lock);
+
+       /*
+        * it is possible userspace to continue to queuing buffres even
+        * while we are in streamoff. Not sure is this a problem in
+        * videobuf2 core, still. Fix it here for now.
+        */
+       if (state >= INST_STOP)
+               return -EINVAL;
+
+       return vb2_qbuf(queue, b);
+}
+
+static int
+vdec_exportbuf(struct file *file, void *fh, struct v4l2_exportbuffer *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = vdec_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_expbuf(queue, b);
+}
+
+static int vdec_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = vdec_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_dqbuf(queue, b, file->f_flags & O_NONBLOCK);
+}
+
+static int vdec_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = vdec_to_vb2q(inst, type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_streamon(queue, type);
+}
+
+static int vdec_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = vdec_to_vb2q(inst, type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_streamoff(queue, type);
+}
+
+static int vdec_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct v4l2_fract *timeperframe = &a->parm.output.timeperframe;
+       u64 us_per_frame, fps;
+
+       if (!timeperframe->denominator ||
+           a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return -EINVAL;
+
+       us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
+       do_div(us_per_frame, timeperframe->denominator);
+
+       if (!us_per_frame)
+               return -EINVAL;
+
+       fps = (u64)USEC_PER_SEC;
+       do_div(fps, us_per_frame);
+
+       dev_dbg(dev, "%s: num:%d, denom:%d\n", __func__,
+               timeperframe->numerator, timeperframe->denominator);
+
+       inst->fps = fps;
+       inst->timeperframe = *timeperframe;
+
+       return 0;
+}
+
+static int vdec_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return -EINVAL;
+
+       memset(a, 0, sizeof(*a));
+       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+       a->parm.capture.timeperframe = inst->timeperframe;
+
+       return 0;
+}
+
+static int vdec_enum_framesizes(struct file *file, void *fh,
+                               struct v4l2_frmsizeenum *fsize)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vidc_core_capability *capability = &inst->capability;
+
+       fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+       fsize->stepwise.min_width = capability->width.min;
+       fsize->stepwise.max_width = capability->width.max;
+       fsize->stepwise.step_width = capability->width.step_size;
+       fsize->stepwise.min_height = capability->height.min;
+       fsize->stepwise.max_height = capability->height.max;
+       fsize->stepwise.step_height = capability->height.step_size;
+
+       return 0;
+}
+
+static int vdec_subscribe_event(struct v4l2_fh *fh,
+                               const struct  v4l2_event_subscription *sub)
+{
+       switch (sub->type) {
+       case V4L2_EVENT_EOS:
+               return v4l2_event_subscribe(fh, sub, 2, NULL);
+       case V4L2_EVENT_SOURCE_CHANGE:
+               return v4l2_src_change_event_subscribe(fh, sub);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int vdec_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vidc_core *core = inst->core;
+       int ret = 0;
+
+       return 0;
+
+       switch (dec->cmd) {
+       case V4L2_DEC_QCOM_CMD_FLUSH:
+               if (core->state != CORE_INVALID &&
+                   inst->state == INST_INVALID) {
+                       ret = vidc_comm_kill_session(inst);
+                       if (ret)
+                               dprintk(VIDC_ERR, "session kill (%d)\n", ret);
+               }
+
+               ret = vidc_comm_session_flush(inst, dec->flags);
+               if (ret)
+                       dprintk(VIDC_ERR, "Failed to flush buffers: %d\n", ret);
+               break;
+       case V4L2_DEC_CMD_STOP:
+               if (core->state != CORE_INVALID &&
+                   inst->state == INST_INVALID) {
+                       ret = vidc_comm_kill_session(inst);
+                       if (ret)
+                               dprintk(VIDC_ERR, "session kill (%d)\n", ret);
+               }
+
+               ret = release_scratch_buffers(inst, false);
+               if (ret)
+                       dprintk(VIDC_ERR,
+                               "release scratch buffers (%d)\n", ret);
+
+               ret = release_persist_buffers(inst);
+               if (ret)
+                       dprintk(VIDC_ERR,
+                               "release persist buffers (%d)\n", ret);
+
+               if (inst->state == INST_INVALID ||
+                   core->state == CORE_INVALID) {
+                       dprintk(VIDC_ERR,
+                               "core and/or instance are in invalid state\n");
+                       vidc_queue_v4l2_event(inst,
+                                             V4L2_EVENT_MSM_VIDC_CLOSE_DONE);
+                       goto exit;
+               }
+
+               ret = hfi_session_deinit(inst);
+
+               inst->session = NULL;
+               vidc_inst_set_state(inst, INST_UNINIT);
+
+               /* Clients rely on this event for joining poll thread.
+                * This event should be returned even if firmware has
+                * failed to respond
+                */
+               vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_CLOSE_DONE);
+               break;
+       default:
+               return -ENOTSUPP;
+       }
+
+exit:
+       return ret;
+}
+
+static const struct v4l2_ioctl_ops vdec_ioctl_ops = {
+       .vidioc_querycap = vdec_querycap,
+       .vidioc_enum_fmt_vid_cap_mplane = vdec_enum_fmt,
+       .vidioc_enum_fmt_vid_out_mplane = vdec_enum_fmt,
+       .vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt_cap,
+       .vidioc_s_fmt_vid_out_mplane = vdec_s_fmt_out,
+       .vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt,
+       .vidioc_g_fmt_vid_out_mplane = vdec_g_fmt,
+       .vidioc_try_fmt_vid_cap_mplane = vdec_try_fmt,
+       .vidioc_try_fmt_vid_out_mplane = vdec_try_fmt,
+       .vidioc_reqbufs = vdec_reqbufs,
+       .vidioc_querybuf = vdec_querybuf,
+       .vidioc_prepare_buf = vdec_prepare_buf,
+       .vidioc_qbuf = vdec_qbuf,
+       .vidioc_expbuf = vdec_exportbuf,
+       .vidioc_dqbuf = vdec_dqbuf,
+       .vidioc_streamon = vdec_streamon,
+       .vidioc_streamoff = vdec_streamoff,
+       .vidioc_s_parm = vdec_s_parm,
+       .vidioc_g_parm = vdec_g_parm,
+       .vidioc_enum_framesizes = vdec_enum_framesizes,
+       .vidioc_subscribe_event = vdec_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+       .vidioc_decoder_cmd = vdec_cmd,
+};
+
+static int vdec_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+                           unsigned int *num_buffers,
+                           unsigned int *num_planes, unsigned int sizes[],
+                           void *alloc_ctxs[])
+{
+       struct vidc_inst *inst = vb2_get_drv_priv(q);
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hal_buffer_requirements bufreq;
+       struct hal_buffer_count_actual buf_count;
+       enum hal_property prop_id;
+       int i, ret = 0;
+
+       switch (q->type) {
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+               *num_planes = inst->fmt_out->num_planes;
+
+               *num_buffers = clamp_val(*num_buffers, MIN_NUM_OUTPUT_BUFFERS,
+                                        MAX_NUM_OUTPUT_BUFFERS);
+
+               for (i = 0; i < *num_planes; i++) {
+                       sizes[i] =
+                               get_framesize(inst, inst->fmt_out, q->type, i);
+                       alloc_ctxs[i] = inst->vb2_ctx_out;
+               }
+
+               prop_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+               buf_count.type = HAL_BUFFER_INPUT;
+               buf_count.count_actual = *num_buffers;
+
+               ret = hfi_session_set_property(inst, prop_id, &buf_count);
+               if (ret) {
+                       dev_err(dev, "set buffer count %d failed (%d)\n",
+                               buf_count.count_actual, ret);
+                       return ret;
+               }
+               break;
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+               *num_planes = inst->fmt_cap->num_planes;
+
+               ret = vidc_comm_bufrequirements(inst, HAL_BUFFER_OUTPUT,
+                                               &bufreq);
+               if (ret)
+                       return ret;
+
+               *num_buffers = max(*num_buffers, bufreq.count_min);
+
+               if (*num_buffers != bufreq.count_actual) {
+                       struct hal_buffer_display_hold_count_actual display;
+
+                       prop_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+                       buf_count.type = HAL_BUFFER_OUTPUT;
+                       buf_count.count_actual = *num_buffers;
+
+                       ret = hfi_session_set_property(inst, prop_id,
+                                                      &buf_count);
+                       if (ret) {
+                               dev_err(dev, "set buf count failed (%d)", ret);
+                               break;
+                       }
+
+                       prop_id = HAL_PARAM_BUFFER_DISPLAY_HOLD_COUNT_ACTUAL;
+                       display.buffer_type = HAL_BUFFER_OUTPUT;
+                       display.hold_count =
+                                       *num_buffers - bufreq.count_actual;
+
+                       ret = hfi_session_set_property(inst, prop_id, &display);
+                       if (ret) {
+                               dev_err(dev, "display hold count failed (%d)",
+                                       ret);
+                               break;
+                       }
+               }
+
+               sizes[0] = bufreq.size;
+               alloc_ctxs[0] = inst->vb2_ctx_cap;
+
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int vdec_buf_init(struct vb2_buffer *vb)
+{
+       struct vb2_queue *q = vb->vb2_queue;
+       struct vidc_inst *inst = vb2_get_drv_priv(q);
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hfi_device *hdev = inst->core->hfidev;
+       struct vdec_buffer *buf = to_vdec_buffer(vb);
+       struct vidc_buffer_addr_info *bai;
+       struct buffer_info *bi;
+       int ret;
+
+       bi = &buf->bi;
+       bai = &bi->bai;
+
+       memset(bai, 0, sizeof(*bai));
+
+       if (q->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return 0;
+
+       bai->buffer_size = vb2_plane_size(vb, 0);
+       bai->buffer_type = vidc_comm_get_hal_output_buffer(inst);
+       bai->num_buffers = 1;
+       bai->device_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+       ret = call_hfi_op(hdev, session_set_buffers, inst->session, bai);
+       if (ret) {
+               dev_err(dev, "%s: session: set buffer failed\n", __func__);
+               return ret;
+       }
+
+       mutex_lock(&inst->registeredbufs.lock);
+       list_add_tail(&bi->list, &inst->registeredbufs.list);
+       mutex_unlock(&inst->registeredbufs.lock);
+
+       return 0;
+}
+
+static int vdec_buf_prepare(struct vb2_buffer *vb)
+{
+       struct vdec_buffer *buf = to_vdec_buffer(vb);
+
+       buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+       return 0;
+}
+
+static void __fill_flags(struct vidc_frame_data *frame_data, __u32 vb_flags)
+{
+       u32 *flags = &frame_data->flags;
+
+       if (vb_flags & V4L2_QCOM_BUF_FLAG_EOS)
+               *flags = HAL_BUFFERFLAG_EOS;
+
+       if (vb_flags & V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP)
+               *flags |= HAL_BUFFERFLAG_YUV_601_709_CSC_CLAMP;
+
+       if (vb_flags & V4L2_QCOM_BUF_FLAG_CODECCONFIG)
+               *flags |= HAL_BUFFERFLAG_CODECCONFIG;
+
+       if (vb_flags & V4L2_QCOM_BUF_FLAG_DECODEONLY)
+               *flags |= HAL_BUFFERFLAG_DECODEONLY;
+
+       if (vb_flags & V4L2_QCOM_BUF_TS_DISCONTINUITY)
+               *flags |= HAL_BUFFERFLAG_TS_DISCONTINUITY;
+
+       if (vb_flags & V4L2_QCOM_BUF_TS_ERROR)
+               *flags |= HAL_BUFFERFLAG_TS_ERROR;
+
+       if (vb_flags & V4L2_QCOM_BUF_TIMESTAMP_INVALID)
+               frame_data->timestamp = LLONG_MAX;
+}
+
+static int vdec_set_session_buf(struct vb2_buffer *vb)
+{
+       struct vb2_queue *q = vb->vb2_queue;
+       struct vidc_inst *inst = vb2_get_drv_priv(q);
+       struct vidc_core *core = inst->core;
+       struct device *dev = &core->res.pdev->dev;
+       struct hfi_device *hdev = core->hfidev;
+       struct vdec_buffer *buf = to_vdec_buffer(vb);
+       struct vidc_frame_data fdata;
+       s64 time_usec;
+       int ret;
+
+       if (inst->state == INST_INVALID || core->state == CORE_INVALID) {
+               dev_err(dev, "core id:%d is in bad state\n", core->id);
+               return -EINVAL;
+       }
+
+       time_usec = timeval_to_ns(&vb->v4l2_buf.timestamp);
+       do_div(time_usec, NSEC_PER_USEC);
+
+       memset(&fdata, 0 , sizeof(fdata));
+
+       fdata.alloc_len = vb2_plane_size(vb, 0);
+       fdata.device_addr = buf->dma_addr;
+       fdata.timestamp = time_usec;
+       fdata.flags = 0;
+       fdata.clnt_data = buf->dma_addr;
+
+       if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               fdata.buffer_type = HAL_BUFFER_INPUT;
+               fdata.filled_len = vb2_get_plane_payload(vb, 0);
+               fdata.offset = vb->v4l2_planes[0].data_offset;
+
+               __fill_flags(&fdata, vb->v4l2_buf.flags);
+
+               ret = call_hfi_op(hdev, session_etb, inst->session, &fdata);
+       } else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               fdata.buffer_type = vidc_comm_get_hal_output_buffer(inst);
+               fdata.filled_len = 0;
+               fdata.offset = 0;
+
+               ret = call_hfi_op(hdev, session_ftb, inst->session, &fdata);
+       } else {
+               ret = -EINVAL;
+       }
+
+       if (ret) {
+               dev_err(dev, "failed to set session buffer\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int vdec_rel_session_bufs(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct vidc_buffer_addr_info *bai;
+       struct buffer_info *bi, *tmp;
+       int ret = 0;
+
+       mutex_lock(&inst->registeredbufs.lock);
+       list_for_each_entry_safe(bi, tmp, &inst->registeredbufs.list, list) {
+               list_del(&bi->list);
+               bai = &bi->bai;
+               bai->response_required = 1;
+               ret = hfi_session_release_buffers(inst, bai);
+               if (ret) {
+                       dev_err(dev, "%s: session release buffers failed\n",
+                               __func__);
+                       break;
+               }
+       }
+       mutex_unlock(&inst->registeredbufs.lock);
+
+       return ret;
+}
+
+static int start_streaming(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct list_head *ptr, *next;
+       struct vdec_buffer *buf;
+       int ret;
+
+       inst->in_reconfig = false;
+
+       ret = vdec_set_properties(inst);
+       if (ret)
+               return ret;
+
+       ret = set_scratch_buffers(inst);
+       if (ret) {
+               dev_err(dev, "failed to set scratch buffers: %d\n", ret);
+               return ret;
+       }
+
+       ret = set_persist_buffers(inst);
+       if (ret) {
+               dev_err(dev, "Failed to set persist buffers: %d\n", ret);
+               return ret;
+       }
+
+       msm_comm_scale_clocks(inst->core);
+
+       ret = hfi_session_load_res(inst);
+       if (ret)
+               return ret;
+
+       ret = hfi_session_start(inst);
+       if (ret)
+               return ret;
+
+       mutex_lock(&inst->bufqueue_lock);
+       list_for_each_safe(ptr, next, &inst->bufqueue) {
+               buf = list_entry(ptr, struct vdec_buffer, list);
+
+               ret = vdec_set_session_buf(&buf->vb);
+               if (ret)
+                       break;
+       }
+       mutex_unlock(&inst->bufqueue_lock);
+
+       return ret;
+}
+
+static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct vidc_inst *inst = vb2_get_drv_priv(q);
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct vb2_queue *queue;
+
+       dev_dbg(dev, "%s: type: %d, count: %d\n", __func__, q->type, count);
+
+       switch (q->type) {
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+               queue = &inst->bufq_cap;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+               queue = &inst->bufq_out;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (vb2_is_streaming(queue))
+               return start_streaming(inst);
+
+       return 0;
+}
+
+static int stop_streaming(struct vidc_inst *inst)
+{
+       struct vidc_core *core = inst->core;
+       struct device *dev = &core->res.pdev->dev;
+       int ret, streamoff;
+
+       mutex_lock(&inst->lock);
+       streamoff = inst->streamoff;
+       mutex_unlock(&inst->lock);
+
+       if (streamoff)
+               return 0;
+
+       ret = hfi_session_stop(inst);
+       if (ret) {
+               dev_err(dev, "session: stop failed\n");
+               goto abort;
+       }
+
+       ret = hfi_session_release_res(inst);
+       if (ret) {
+               dev_err(dev, "session: release resources failed\n");
+               goto abort;
+       }
+
+       ret = vdec_rel_session_bufs(inst);
+       if (ret) {
+               dev_err(dev, "failed to release capture buffers: %d\n", ret);
+               goto abort;
+       }
+
+       ret = release_scratch_buffers(inst, false);
+       if (ret) {
+               dev_err(dev, "failed to release scratch buffers: %d\n", ret);
+               goto abort;
+       }
+
+       ret = release_persist_buffers(inst);
+       if (ret) {
+               dev_err(dev, "failed to release persist buffers: %d\n", ret);
+               goto abort;
+       }
+
+       if (inst->state == INST_INVALID || core->state == CORE_INVALID) {
+               dev_err(dev, "core id:%d is in invalid state\n", core->id);
+               ret = -EINVAL;
+               goto abort;
+       }
+
+       ret = hfi_session_deinit(inst);
+
+       mutex_lock(&inst->lock);
+       inst->streamoff = 1;
+       mutex_unlock(&inst->lock);
+
+abort:
+       if (ret)
+               hfi_session_abort(inst);
+
+       inst->session = NULL;
+       vidc_inst_set_state(inst, INST_UNINIT);
+
+       return ret;
+}
+
+static void vdec_stop_streaming(struct vb2_queue *q)
+{
+       struct vidc_inst *inst = vb2_get_drv_priv(q);
+       struct device *dev = &inst->core->res.pdev->dev;
+       int ret;
+
+       dev_dbg(dev, "%s: type: %d\n", __func__, q->type);
+
+       ret = stop_streaming(inst);
+
+       msm_comm_scale_clocks(inst->core);
+
+       if (ret)
+               dev_err(dev, "stop streaming failed type: %d, ret: %d\n",
+                       q->type, ret);
+}
+
+static void vdec_buf_queue(struct vb2_buffer *vb)
+{
+       struct vidc_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
+       struct vidc_core *core = inst->core;
+       struct device *dev = &core->res.pdev->dev;
+       struct vdec_buffer *buf = to_vdec_buffer(vb);
+       int ret;
+
+       if (inst->state == INST_INVALID || core->state == CORE_INVALID) {
+               dev_err(dev, "core or instance are in invalid state\n");
+               return;
+       }
+
+       dev_dbg(dev, "%s: vb:%p, type:%d, addr:%pa\n", __func__, vb,
+               vb->vb2_queue->type, &buf->dma_addr);
+
+       mutex_lock(&inst->bufqueue_lock);
+       list_add_tail(&buf->list, &inst->bufqueue);
+       mutex_unlock(&inst->bufqueue_lock);
+
+       if (!vb2_is_streaming(&inst->bufq_cap) ||
+           !vb2_is_streaming(&inst->bufq_out))
+               return;
+
+       ret = vdec_set_session_buf(vb);
+       if (ret) {
+               vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+               dev_err(dev, "cannot set session buffer\n");
+       }
+}
+
+static const struct vb2_ops vdec_vb2_ops = {
+       .queue_setup = vdec_queue_setup,
+       .buf_init = vdec_buf_init,
+       .buf_prepare = vdec_buf_prepare,
+       .start_streaming = vdec_start_streaming,
+       .stop_streaming = vdec_stop_streaming,
+       .buf_queue = vdec_buf_queue,
+};
+
+static struct vb2_buffer *
+vdec_get_vb2buffer(struct vidc_inst *inst, dma_addr_t addr)
+{
+       struct vdec_buffer *buf;
+       struct vb2_buffer *vb = NULL;
+
+       mutex_lock(&inst->bufqueue_lock);
+
+       list_for_each_entry(buf, &inst->bufqueue, list) {
+               if (buf->dma_addr == addr) {
+                       vb = &buf->vb;
+                       break;
+               }
+       }
+
+       if (vb)
+               list_del(&buf->list);
+
+       mutex_unlock(&inst->bufqueue_lock);
+
+       return vb;
+}
+
+static int vdec_empty_buf_done(struct vidc_inst *inst, u32 addr,
+                              u32 bytesused, u32 data_offset, u32 flags)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct vb2_buffer *vb;
+
+       vb = vdec_get_vb2buffer(inst, addr);
+       if (!vb)
+               return -EFAULT;
+
+       vb->v4l2_planes[0].bytesused = bytesused;
+       vb->v4l2_planes[0].data_offset = data_offset;
+       vb->v4l2_buf.flags = flags;
+
+       if (vb->v4l2_planes[0].data_offset > vb->v4l2_planes[0].length)
+               dev_dbg(dev, "data_offset overflow length\n");
+
+       if (vb->v4l2_planes[0].bytesused > vb->v4l2_planes[0].length)
+               dev_dbg(dev, "bytesused overflow length\n");
+
+       if (flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED)
+               dev_dbg(dev, "unsupported input stream\n");
+
+       if (flags & V4L2_QCOM_BUF_DATA_CORRUPT)
+               dev_dbg(dev, "corrupted input stream\n");
+
+       if (flags & V4L2_MSM_VIDC_BUF_START_CODE_NOT_FOUND)
+               dev_dbg(dev, "start code not found\n");
+
+       inst->count.ebd++;
+
+       vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+
+       return 0;
+}
+
+static int vdec_fill_buf_done(struct vidc_inst *inst, u32 addr,
+                             u32 bytesused, u32 data_offset, u32 flags,
+                             struct timeval *timestamp)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct vb2_buffer *vb;
+
+       vb = vdec_get_vb2buffer(inst, addr);
+       if (!vb)
+               return -EFAULT;
+
+       vb->v4l2_planes[0].bytesused = bytesused;
+       vb->v4l2_planes[0].data_offset = data_offset;
+       vb->v4l2_buf.flags = flags;
+       vb->v4l2_buf.timestamp = *timestamp;
+
+       if (vb->v4l2_planes[0].data_offset > vb->v4l2_planes[0].length)
+               dev_warn(dev, "overflow data_offset:%d, length:%d\n",
+                        vb->v4l2_planes[0].data_offset,
+                        vb->v4l2_planes[0].length);
+
+       if (vb->v4l2_planes[0].bytesused > vb->v4l2_planes[0].length)
+               dev_warn(dev, "overflow bytesused:%d, length:%d\n",
+                        vb->v4l2_planes[0].bytesused,
+                        vb->v4l2_planes[0].length);
+
+       inst->count.fbd++;
+
+       vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+
+       return 0;
+}
+
+static int vdec_event_notify(struct vidc_inst *inst, u32 event,
+                            struct vidc_cb_event *data)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+
+       switch (event) {
+       case SESSION_ERROR:
+               /* the instance lock is already taken just change the state */
+               inst->state = INST_INVALID;
+               dev_warn(dev, "event session error\n");
+               break;
+       case SYS_EVENT_CHANGE:
+               switch (data->hal_event_type) {
+               case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
+                       dev_dbg(dev, "event sufficient resources\n");
+                       break;
+               case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
+                       dev_dbg(dev, "event not sufficient resources\n");
+                       inst->reconfig_height = data->height;
+                       inst->reconfig_width = data->width;
+                       inst->in_reconfig = true;
+                       break;
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void vdec_inst_init(struct vidc_inst *inst)
+{
+       inst->fmt_out = &vdec_formats[2];
+       inst->fmt_cap = &vdec_formats[0];
+       inst->height = DEFAULT_HEIGHT;
+       inst->width = DEFAULT_WIDTH;
+       inst->capability.height.min = MIN_SUPPORTED_HEIGHT;
+       inst->capability.height.max = DEFAULT_HEIGHT;
+       inst->capability.width.min = MIN_SUPPORTED_WIDTH;
+       inst->capability.width.max = DEFAULT_WIDTH;
+       inst->capability.buffer_mode[OUTPUT_PORT] = HAL_BUFFER_MODE_STATIC;
+       inst->capability.buffer_mode[CAPTURE_PORT] = HAL_BUFFER_MODE_STATIC;
+       inst->capability.secure_output2_threshold.min = 0;
+       inst->capability.secure_output2_threshold.max = 0;
+       inst->buffer_mode[OUTPUT_PORT] = HAL_BUFFER_MODE_STATIC;
+       inst->buffer_mode[CAPTURE_PORT] = HAL_BUFFER_MODE_STATIC;
+       inst->fps = 30;
+}
+
+static void vdec_release_video_device(struct video_device *pvdev)
+{
+}
+
+extern const struct v4l2_file_operations vidc_fops;
+
+int vdec_init(struct vidc_core *core, struct video_device *dec)
+{
+       int ret;
+
+       /* setup the decoder device */
+       dec->release = vdec_release_video_device;
+       dec->fops = &vidc_fops;
+       dec->ioctl_ops = &vdec_ioctl_ops;
+       dec->vfl_dir = VFL_DIR_M2M;
+       dec->v4l2_dev = &core->v4l2_dev;
+
+       ret = video_register_device(dec, VFL_TYPE_GRABBER, 32);
+       if (ret) {
+               dprintk(VIDC_ERR, "Failed to register video decoder device");
+               return ret;
+       }
+
+       video_set_drvdata(dec, core);
+
+       return 0;
+}
+
+void vdec_deinit(struct vidc_core *core, struct video_device *dec)
+{
+       video_unregister_device(dec);
+}
+
+int vdec_open(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct vb2_queue *q;
+       struct device *iommu_dev;
+       int ret;
+
+       /* TODO: use iommu dt bindings when they are exist */
+       iommu_dev = msm_iommu_get_ctx("venus_ns");
+       if (IS_ERR(iommu_dev)) {
+               dev_err(dev, "cannot find iommu nonsecure ctx\n");
+               return PTR_ERR(iommu_dev);
+       }
+
+       vdec_inst_init(inst);
+
+       ret = vdec_ctrl_init(inst);
+       if (ret)
+               return ret;
+
+       inst->vb2_ctx_cap = vb2_dma_contig_init_ctx(iommu_dev);
+       if (IS_ERR(inst->vb2_ctx_cap))
+               return PTR_ERR(inst->vb2_ctx_cap);
+
+       inst->vb2_ctx_out = vb2_dma_contig_init_ctx(iommu_dev);
+       if (IS_ERR(inst->vb2_ctx_out)) {
+               ret = PTR_ERR(inst->vb2_ctx_out);
+               goto err_cleanup_cap;
+       }
+
+       q = &inst->bufq_cap;
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       q->io_modes = VB2_MMAP | VB2_DMABUF;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       q->ops = &vdec_vb2_ops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->drv_priv = inst;
+       q->buf_struct_size = sizeof(struct vdec_buffer);
+       q->allow_zero_bytesused = 1;
+       ret = vb2_queue_init(q);
+       if (ret)
+               goto err_cleanup_out;
+
+       q = &inst->bufq_out;
+       q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       q->io_modes = VB2_MMAP;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       q->ops = &vdec_vb2_ops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->drv_priv = inst;
+       q->buf_struct_size = sizeof(struct vdec_buffer);
+       q->allow_zero_bytesused = 1;
+       ret = vb2_queue_init(q);
+       if (ret)
+               goto err_cap_queue_release;
+
+       inst->empty_buf_done = vdec_empty_buf_done;
+       inst->fill_buf_done = vdec_fill_buf_done;
+       inst->event_notify = vdec_event_notify;
+
+       return 0;
+
+err_cap_queue_release:
+       vb2_queue_release(&inst->bufq_cap);
+err_cleanup_out:
+       vb2_dma_contig_cleanup_ctx(inst->vb2_ctx_out);
+err_cleanup_cap:
+       vb2_dma_contig_cleanup_ctx(inst->vb2_ctx_cap);
+       return ret;
+}
+
+void vdec_close(struct vidc_inst *inst)
+{
+       vb2_queue_release(&inst->bufq_out);
+       vb2_queue_release(&inst->bufq_cap);
+
+       vb2_dma_contig_cleanup_ctx(inst->vb2_ctx_out);
+       vb2_dma_contig_cleanup_ctx(inst->vb2_ctx_cap);
+
+       vdec_ctrl_deinit(inst);
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.h b/drivers/media/platform/msm/vidc/msm_vdec.h
new file mode 100644 (file)
index 0000000..be50777
--- /dev/null
@@ -0,0 +1,23 @@
+/* Copyright (c) 2012, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _MSM_VDEC_H_
+#define _MSM_VDEC_H_
+
+#include "msm_vidc_internal.h"
+
+int vdec_init(struct vidc_core *core, struct video_device *dec);
+void vdec_deinit(struct vidc_core *core, struct video_device *dec);
+int vdec_open(struct vidc_inst *inst);
+void vdec_close(struct vidc_inst *inst);
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/msm_venc-ctrls.c b/drivers/media/platform/msm/vidc/msm_venc-ctrls.c
new file mode 100644 (file)
index 0000000..9b0389f
--- /dev/null
@@ -0,0 +1,2409 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/cpumask.h>
+#include <linux/types.h>
+#include <linux/v4l2-controls.h>
+#include <linux/qcom_scm.h>
+#include <media/msm-v4l2-controls.h>
+#include <linux/kernel.h>
+
+#include "msm_vidc_debug.h"
+#include "msm_vidc_common.h"
+#include "msm_vidc_load.h"
+#include "msm_hfi_interface.h"
+#include "msm_venc.h"
+
+#define MIN_BIT_RATE           32000
+#define MAX_BIT_RATE           160000000
+#define DEFAULT_BIT_RATE       64000
+#define BIT_RATE_STEP          100
+#define DEFAULT_FRAME_RATE     15
+#define MAX_SLICE_BYTE_SIZE    1024
+#define MIN_SLICE_BYTE_SIZE    1024
+#define MAX_SLICE_MB_SIZE      300
+#define I_FRAME_QP             26
+#define P_FRAME_QP             28
+#define B_FRAME_QP             30
+#define MAX_INTRA_REFRESH_MBS  300
+#define MAX_NUM_B_FRAMES       4
+#define MAX_LTR_FRAME_COUNT    10
+
+#define L_MODE \
+               V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY
+#define CODING \
+               V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY
+#define BITSTREAM_RESTRICT_ENABLED     \
+               V4L2_MPEG_VIDC_VIDEO_H264_VUI_BITSTREAM_RESTRICT_ENABLED
+#define BITSTREAM_RESTRICT_DISABLED    \
+       V4L2_MPEG_VIDC_VIDEO_H264_VUI_BITSTREAM_RESTRICT_DISABLED
+
+#define MIN_TIME_RESOLUTION            1
+#define MAX_TIME_RESOLUTION            0xffffff
+#define DEFAULT_TIME_RESOLUTION                0x7530
+
+#define IS_PRIV_CTRL(idx)      ( \
+               (V4L2_CTRL_ID2CLASS(idx) == V4L2_CTRL_CLASS_MPEG) && \
+               V4L2_CTRL_DRIVER_PRIV(idx))
+
+static const char *const mpeg_video_rate_control[] = {
+       "No Rate Control",
+       "VBR VFR",
+       "VBR CFR",
+       "CBR VFR",
+       "CBR CFR",
+       NULL
+};
+
+static const char *const mpeg_video_rotation[] = {
+       "No Rotation",
+       "90 Degree Rotation",
+       "180 Degree Rotation",
+       "270 Degree Rotation",
+       NULL
+};
+
+static const char *const h264_video_entropy_cabac_model[] = {
+       "Model 0",
+       "Model 1",
+       "Model 2",
+       NULL
+};
+
+static const char *const h263_level[] = {
+       "1.0",
+       "2.0",
+       "3.0",
+       "4.0",
+       "4.5",
+       "5.0",
+       "6.0",
+       "7.0",
+};
+
+static const char *const h263_profile[] = {
+       "Baseline",
+       "H320 Coding",
+       "Backward Compatible",
+       "ISWV2",
+       "ISWV3",
+       "High Compression",
+       "Internet",
+       "Interlace",
+       "High Latency",
+};
+
+static const char *const hevc_tier_level[] = {
+       "Main Tier Level 1",
+       "Main Tier Level 2",
+       "Main Tier Level 2.1",
+       "Main Tier Level 3",
+       "Main Tier Level 3.1",
+       "Main Tier Level 4",
+       "Main Tier Level 4.1",
+       "Main Tier Level 5",
+       "Main Tier Level 5.1",
+       "Main Tier Level 5.2",
+       "Main Tier Level 6",
+       "Main Tier Level 6.1",
+       "Main Tier Level 6.2",
+       "High Tier Level 1",
+       "High Tier Level 2",
+       "High Tier Level 2.1",
+       "High Tier Level 3",
+       "High Tier Level 3.1",
+       "High Tier Level 4",
+       "High Tier Level 4.1",
+       "High Tier Level 5",
+       "High Tier Level 5.1",
+       "High Tier Level 5.2",
+       "High Tier Level 6",
+       "High Tier Level 6.1",
+       "High Tier Level 6.2",
+};
+
+static const char *const hevc_profile[] = {
+       "Main",
+       "Main10",
+       "Main Still Pic",
+};
+
+static const char *const vp8_profile_level[] = {
+       "Unused",
+       "0.0",
+       "1.0",
+       "2.0",
+       "3.0",
+};
+
+static const char *const mpeg_video_vidc_extradata[] = {
+       "Extradata none",
+       "Extradata MB Quantization",
+       "Extradata Interlace Video",
+       "Extradata VC1 Framedisp",
+       "Extradata VC1 Seqdisp",
+       "Extradata timestamp",
+       "Extradata S3D Frame Packing",
+       "Extradata Frame Rate",
+       "Extradata Panscan Window",
+       "Extradata Recovery point SEI",
+       "Extradata Closed Caption UD",
+       "Extradata AFD UD",
+       "Extradata Multislice info",
+       "Extradata number of concealed MB",
+       "Extradata metadata filler",
+       "Extradata input crop",
+       "Extradata digital zoom",
+       "Extradata aspect ratio",
+       "Extradata macroblock metadata",
+};
+
+static const char *const perf_level[] = {
+       "Nominal",
+       "Performance",
+       "Turbo"
+};
+
+static const char *const intra_refresh_modes[] = {
+       "None",
+       "Cyclic",
+       "Adaptive",
+       "Cyclic Adaptive",
+       "Random"
+};
+
+static const char *const timestamp_mode[] = {
+       "Honor",
+       "Ignore",
+};
+
+static struct vidc_ctrl venc_ctrls[] = {
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD,
+               .name = "IDR Period",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = INT_MAX,
+               .default_value = DEFAULT_FRAME_RATE,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES,
+               .name = "Intra Period for P frames",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .default_value = 2 * DEFAULT_FRAME_RATE - 1,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES,
+               .name = "Intra Period for B frames",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME,
+               .name = "Request I Frame",
+               .type = V4L2_CTRL_TYPE_BUTTON,
+               .minimum = 0,
+               .maximum = 0,
+               .default_value = 0,
+               .step = 0,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL,
+               .name = "Video Framerate and Bitrate Control",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF,
+               .maximum = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR,
+               .default_value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF,
+               .step = 0,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF) |
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR) |
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR) |
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR) |
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR)),
+               .qmenu = mpeg_video_rate_control,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+               .name = "Bitrate Control",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+               .maximum = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+               .default_value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+               .step = 0,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
+                       (1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)),
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE,
+               .name = "Bit Rate",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = MIN_BIT_RATE,
+               .maximum = MAX_BIT_RATE,
+               .default_value = DEFAULT_BIT_RATE,
+               .step = BIT_RATE_STEP,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+               .name = "Peak Bit Rate",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = MIN_BIT_RATE,
+               .maximum = MAX_BIT_RATE,
+               .default_value = DEFAULT_BIT_RATE,
+               .step = BIT_RATE_STEP,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
+               .name = "Entropy Mode",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+               .maximum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+               .default_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+               .step = 0,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
+                       (1 << V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)),
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL,
+               .name = "CABAC Model",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0,
+               .maximum = V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_1,
+               .default_value = V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0,
+               .step = 0,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0) |
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_1) |
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_2)),
+               .qmenu = h264_video_entropy_cabac_model,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
+               .name = "MPEG4 Profile",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
+               .maximum = CODING,
+               .default_value = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
+               .step = 1,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
+               .name = "MPEG4 Level",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
+               .maximum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
+               .default_value = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
+               .step = 1,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+               .name = "H264 Profile",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+               .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
+               .default_value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+               .step = 1,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+               .name = "H264 Level",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+               .maximum = V4L2_MPEG_VIDEO_H264_LEVEL_5_2,
+               .default_value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+               .step = 0,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE,
+               .name = "H263 Profile",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE,
+               .menu_skip_mask = ~(
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_H320CODING) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BACKWARDCOMPATIBLE) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV2) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV3) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHCOMPRESSION) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERNET) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERLACE) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY)),
+               .qmenu = h263_profile,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL,
+               .name = "H263 Level",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_2_0) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_3_0) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_0) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_5_0) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_6_0) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0)),
+               .qmenu = h263_level,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL,
+               .name = "VP8 Profile Level",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0) |
+                       (1 << V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1)),
+               .qmenu = vp8_profile_level,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE,
+               .name = "HEVC Profile",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN,
+               .step = 0,
+               .menu_skip_mask =  ~(
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC)),
+               .qmenu = hevc_profile,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL,
+               .name = "HEVC Tier and Level",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_2,
+               .default_value =
+                       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1,
+               .step = 0,
+               .menu_skip_mask = ~(
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1)
+               ),
+               .qmenu = hevc_tier_level,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_ROTATION,
+               .name = "Rotation",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_NONE,
+               .maximum = V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270,
+               .default_value = V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_NONE,
+               .step = 0,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_NONE) |
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90) |
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_180) |
+                       (1 << V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270)),
+               .qmenu = mpeg_video_rotation,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
+               .name = "I Frame Quantization",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 51,
+               .default_value = I_FRAME_QP,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
+               .name = "P Frame Quantization",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 51,
+               .default_value = P_FRAME_QP,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
+               .name = "B Frame Quantization",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 51,
+               .default_value = B_FRAME_QP,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+               .name = "H264 Minimum QP",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 51,
+               .default_value = 1,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+               .name = "H264 Maximum QP",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 51,
+               .default_value = 51,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_MIN_QP,
+               .name = "VP8 Minimum QP",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 128,
+               .default_value = 1,
+               .step = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_MAX_QP,
+               .name = "VP8 Maximum QP",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 128,
+               .default_value = 128,
+               .step = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
+               .name = "Slice Mode",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
+               .maximum = V4L2_MPEG_VIDEO_MULTI_SLICE_GOB,
+               .default_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
+               .step = 1,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) |
+                       (1 << V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) |
+                       (1 << V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) |
+                       (1 << V4L2_MPEG_VIDEO_MULTI_SLICE_GOB)),
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
+               .name = "Slice Byte Size",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = MIN_SLICE_BYTE_SIZE,
+               .maximum = MAX_SLICE_BYTE_SIZE,
+               .default_value = MIN_SLICE_BYTE_SIZE,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
+               .name = "Slice MB Size",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = MAX_SLICE_MB_SIZE,
+               .default_value = 1,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_GOB,
+               .name = "Slice GOB",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = MAX_SLICE_MB_SIZE,
+               .default_value = 1,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE,
+               .name = "Slice delivery mode",
+               .type = V4L2_CTRL_TYPE_BUTTON,
+               .minimum = 0,
+               .maximum = 1,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE,
+               .name = "Intra Refresh Mode",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_NONE,
+               .maximum = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM,
+               .default_value = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_NONE,
+               .step = 0,
+               .menu_skip_mask = ~(
+               (1 << V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_NONE) |
+               (1 << V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_CYCLIC) |
+               (1 << V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_ADAPTIVE) |
+               (1 << V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_CYCLIC_ADAPTIVE) |
+               (1 << V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM)),
+               .qmenu = intra_refresh_modes,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS,
+               .name = "Intra Refresh AIR MBS",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = MAX_INTRA_REFRESH_MBS,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_AIR_REF,
+               .name = "Intra Refresh AIR REF",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = MAX_INTRA_REFRESH_MBS,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_CIR_MBS,
+               .name = "Intra Refresh CIR MBS",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = MAX_INTRA_REFRESH_MBS,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA,
+               .name = "H.264 Loop Filter Alpha Offset",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = -6,
+               .maximum = 6,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA,
+               .name = "H.264 Loop Filter Beta Offset",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = -6,
+               .maximum = 6,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+               .name = "H.264 Loop Filter Mode",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED,
+               .maximum = L_MODE,
+               .default_value = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED,
+               .step = 1,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED) |
+                       (1 << V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED) |
+                       (1 << L_MODE)),
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEADER_MODE,
+               .name = "Sequence Header Mode",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+               .maximum = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME,
+               .default_value =
+                               V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME,
+               .step = 1,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
+                       (1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME)),
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE,
+               .name = "Secure mode",
+               .type = V4L2_CTRL_TYPE_BUTTON,
+               .minimum = 0,
+               .maximum = 0,
+               .default_value = 0,
+               .step = 0,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA,
+               .name = "Extradata Type",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
+               .maximum = V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI,
+               .default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
+               .menu_skip_mask = ~(
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_MB_QUANTIZATION) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_VC1_FRAMEDISP) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_LTR) |
+                       (1 << V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI)),
+               .qmenu = mpeg_video_vidc_extradata,
+               .step = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO,
+               .name = "H264 VUI Timing Info",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED,
+               .default_value =
+                       V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED,
+               .step = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_H264_AU_DELIMITER,
+               .name = "H264 AU Delimiter",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_H264_AU_DELIMITER_DISABLED,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_H264_AU_DELIMITER_ENABLED,
+               .step = 1,
+               .default_value =
+                       V4L2_MPEG_VIDC_VIDEO_H264_AU_DELIMITER_DISABLED,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
+               .name = "Intra Refresh CIR MBS",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = MAX_INTRA_REFRESH_MBS,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_BITSTREAM_RESTRICT,
+               .name = "H264 VUI Timing Info",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = BITSTREAM_RESTRICT_DISABLED,
+               .maximum = BITSTREAM_RESTRICT_ENABLED,
+               .default_value = BITSTREAM_RESTRICT_ENABLED,
+               .step = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_PRESERVE_TEXT_QUALITY,
+               .name = "Preserve Text Qualty",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_PRESERVE_TEXT_QUALITY_DISABLED,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_PRESERVE_TEXT_QUALITY_ENABLED,
+               .default_value =
+                       V4L2_MPEG_VIDC_VIDEO_PRESERVE_TEXT_QUALITY_DISABLED,
+               .step = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE,
+               .name = "Deinterlace for encoder",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED,
+               .maximum = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_ENABLED,
+               .default_value = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED,
+               .step = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG4_TIME_RESOLUTION,
+               .name = "Vop time increment resolution",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = MIN_TIME_RESOLUTION,
+               .maximum = MAX_TIME_RESOLUTION,
+               .default_value = DEFAULT_TIME_RESOLUTION,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_SEQ_HEADER,
+               .name = "Request Seq Header",
+               .type = V4L2_CTRL_TYPE_BUTTON,
+               .minimum = 0,
+               .maximum = 0,
+               .default_value = 0,
+               .step = 0,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME,
+               .name = "H264 Use LTR",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = MAX_LTR_FRAME_COUNT - 1,
+               .default_value = 0,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT,
+               .name = "Ltr Count",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = MAX_LTR_FRAME_COUNT,
+               .default_value = 0,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE,
+               .name = "Ltr Mode",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_PERIODIC,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME,
+               .name = "H264 Mark LTR",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (MAX_LTR_FRAME_COUNT - 1),
+               .default_value = 0,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS,
+               .name = "Set Hier P num layers",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 3,
+               .default_value = 0,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE,
+               .name = "Encoder Timestamp Mode",
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum =
+                       V4L2_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE_HONOR,
+               .maximum =
+                       V4L2_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE_IGNORE,
+               .default_value =
+                       V4L2_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE_HONOR,
+               .menu_skip_mask = ~(
+               (1 << V4L2_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE_HONOR) |
+               (1 << V4L2_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE_IGNORE)),
+               .qmenu = timestamp_mode,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE,
+               .name = "VP8 Error Resilience mode",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE_DISABLED,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE_ENABLED,
+               .default_value =
+                       V4L2_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE_DISABLED,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_INITIAL_QP,
+               .name = "Enable setting initial QP",
+               .type = V4L2_CTRL_TYPE_BITMASK,
+               .minimum = 0,
+               .maximum = V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_INITIAL_QP_IFRAME |
+                       V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_INITIAL_QP_PFRAME |
+                       V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_INITIAL_QP_BFRAME,
+               .default_value = 0,
+               .step = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP,
+               .name = "Iframe initial QP",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 51,
+               .default_value = 1,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP,
+               .name = "Pframe initial QP",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 51,
+               .default_value = 1,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP,
+               .name = "Bframe initial QP",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 51,
+               .default_value = 1,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_X_RANGE,
+               .name = "I-Frame X coordinate search range",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 4,
+               .maximum = 128,
+               .default_value = 4,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_Y_RANGE,
+               .name = "I-Frame Y coordinate search range",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 4,
+               .maximum = 128,
+               .default_value = 4,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_PFRAME_X_RANGE,
+               .name = "P-Frame X coordinate search range",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 4,
+               .maximum = 128,
+               .default_value = 4,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_PFRAME_Y_RANGE,
+               .name = "P-Frame Y coordinate search range",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 4,
+               .maximum = 128,
+               .default_value = 4,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_BFRAME_X_RANGE,
+               .name = "B-Frame X coordinate search range",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 4,
+               .maximum = 128,
+               .default_value = 4,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_BFRAME_Y_RANGE,
+               .name = "B-Frame Y coordinate search range",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 4,
+               .maximum = 128,
+               .default_value = 4,
+               .step = 1,
+               .menu_skip_mask = 0,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC,
+               .name = "Enable H264 SVC NAL",
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC_DISABLED,
+               .maximum = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC_ENABLED,
+               .default_value = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC_DISABLED,
+               .step = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE,
+               .name = "Set Encoder performance mode",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY,
+               .maximum = V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE,
+               .default_value = V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS,
+               .name = "Set Hier B num layers",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 3,
+               .default_value = 0,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE,
+               .name = "Set Hybrid Hier P mode",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 5,
+               .default_value = 0,
+               .step = 1,
+               .qmenu = NULL,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED,
+               .maximum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED,
+               .default_value = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 12,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+};
+
+#define NUM_CTRLS      ARRAY_SIZE(venc_ctrls)
+
+/* Helper function to translate V4L2_* to HAL_* */
+static inline int venc_v4l2_to_hal(int id, int value)
+{
+       switch (id) {
+       /* MPEG4 */
+       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+               switch (value) {
+               case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0:
+                       return HAL_MPEG4_LEVEL_0;
+               case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B:
+                       return HAL_MPEG4_LEVEL_0b;
+               case V4L2_MPEG_VIDEO_MPEG4_LEVEL_1:
+                       return HAL_MPEG4_LEVEL_1;
+               case V4L2_MPEG_VIDEO_MPEG4_LEVEL_2:
+                       return HAL_MPEG4_LEVEL_2;
+               case V4L2_MPEG_VIDEO_MPEG4_LEVEL_3:
+                       return HAL_MPEG4_LEVEL_3;
+               case V4L2_MPEG_VIDEO_MPEG4_LEVEL_4:
+                       return HAL_MPEG4_LEVEL_4;
+               case V4L2_MPEG_VIDEO_MPEG4_LEVEL_5:
+                       return HAL_MPEG4_LEVEL_5;
+               default:
+                       goto unknown_value;
+               }
+       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+               switch (value) {
+               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
+                       return HAL_MPEG4_PROFILE_SIMPLE;
+               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
+                       return HAL_MPEG4_PROFILE_ADVANCEDSIMPLE;
+               default:
+                       goto unknown_value;
+               }
+       /* H264 */
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               switch (value) {
+               case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+                       return HAL_H264_PROFILE_BASELINE;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+                       return HAL_H264_PROFILE_CONSTRAINED_BASE;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+                       return HAL_H264_PROFILE_MAIN;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
+                       return HAL_H264_PROFILE_EXTENDED;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+                       return HAL_H264_PROFILE_HIGH;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
+                       return HAL_H264_PROFILE_HIGH10;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
+                       return HAL_H264_PROFILE_HIGH422;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
+                       return HAL_H264_PROFILE_HIGH444;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
+                       return HAL_H264_PROFILE_CONSTRAINED_HIGH;
+               default:
+                       goto unknown_value;
+               }
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               switch (value) {
+               case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
+                       return HAL_H264_LEVEL_1;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
+                       return HAL_H264_LEVEL_1b;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
+                       return HAL_H264_LEVEL_11;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
+                       return HAL_H264_LEVEL_12;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
+                       return HAL_H264_LEVEL_13;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
+                       return HAL_H264_LEVEL_2;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
+                       return HAL_H264_LEVEL_21;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
+                       return HAL_H264_LEVEL_22;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
+                       return HAL_H264_LEVEL_3;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
+                       return HAL_H264_LEVEL_31;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
+                       return HAL_H264_LEVEL_32;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
+                       return HAL_H264_LEVEL_4;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
+                       return HAL_H264_LEVEL_41;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
+                       return HAL_H264_LEVEL_42;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
+                       return HAL_H264_LEVEL_5;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
+                       return HAL_H264_LEVEL_51;
+               case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
+                       return HAL_H264_LEVEL_52;
+               default:
+                       goto unknown_value;
+               }
+       /* H263 */
+       case V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE:
+               switch (value) {
+               case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE:
+                       return HAL_H263_PROFILE_BASELINE;
+               case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_H320CODING:
+                       return HAL_H263_PROFILE_H320CODING;
+               case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BACKWARDCOMPATIBLE:
+                       return HAL_H263_PROFILE_BACKWARDCOMPATIBLE;
+               case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV2:
+                       return HAL_H263_PROFILE_ISWV2;
+               case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV3:
+                       return HAL_H263_PROFILE_ISWV3;
+               case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHCOMPRESSION:
+                       return HAL_H263_PROFILE_HIGHCOMPRESSION;
+               case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERNET:
+                       return HAL_H263_PROFILE_INTERNET;
+               case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERLACE:
+                       return HAL_H263_PROFILE_INTERLACE;
+               case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY:
+                       return HAL_H263_PROFILE_HIGHLATENCY;
+               default:
+                       goto unknown_value;
+               }
+       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+               switch (value) {
+               case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
+                       return HAL_H264_ENTROPY_CAVLC;
+               case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
+                       return HAL_H264_ENTROPY_CABAC;
+               default:
+                       goto unknown_value;
+               }
+       case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL:
+               switch (value) {
+               case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0:
+                       return HAL_H264_CABAC_MODEL_0;
+               case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_1:
+                       return HAL_H264_CABAC_MODEL_1;
+               case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_2:
+                       return HAL_H264_CABAC_MODEL_2;
+               default:
+                       goto unknown_value;
+               }
+       case V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL:
+               switch (value) {
+               case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0:
+                       return HAL_H263_LEVEL_10;
+               case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_2_0:
+                       return HAL_H263_LEVEL_20;
+               case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_3_0:
+                       return HAL_H263_LEVEL_30;
+               case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_0:
+                       return HAL_H263_LEVEL_40;
+               case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_5:
+                       return HAL_H263_LEVEL_45;
+               case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_5_0:
+                       return HAL_H263_LEVEL_50;
+               case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_6_0:
+                       return HAL_H263_LEVEL_60;
+               case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0:
+                       return HAL_H263_LEVEL_70;
+               default:
+                       goto unknown_value;
+               }
+       case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
+               switch (value) {
+               case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0:
+                       return HAL_VPX_PROFILE_VERSION_0;
+               case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1:
+                       return HAL_VPX_PROFILE_VERSION_1;
+               case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_2:
+                       return HAL_VPX_PROFILE_VERSION_2;
+               case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3:
+                       return HAL_VPX_PROFILE_VERSION_3;
+               case V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED:
+                       return HAL_VPX_PROFILE_UNUSED;
+               default:
+                       goto unknown_value;
+               }
+       case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
+               switch (value) {
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN:
+                       return HAL_HEVC_PROFILE_MAIN;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10:
+                       return HAL_HEVC_PROFILE_MAIN10;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC:
+                       return HAL_HEVC_PROFILE_MAIN_STILL_PIC;
+               default:
+                       goto unknown_value;
+               }
+       case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
+               switch (value) {
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_2;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_2_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_3;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_3_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_4;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_4_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_5;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_5_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_5_2;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_6;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_6_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2:
+                       return HAL_HEVC_MAIN_TIER_LEVEL_6_2;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_2;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_2_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_3;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_3_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_4;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_4_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_5;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_5_1;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_5_2;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_6;
+               case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1:
+                       return HAL_HEVC_HIGH_TIER_LEVEL_6_1;
+               default:
+                       goto unknown_value;
+               }
+       case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION:
+               switch (value) {
+               case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_NONE:
+                       return HAL_ROTATE_NONE;
+               case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90:
+                       return HAL_ROTATE_90;
+               case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_180:
+                       return HAL_ROTATE_180;
+               case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270:
+                       return HAL_ROTATE_270;
+               default:
+                       goto unknown_value;
+               }
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+               switch (value) {
+               case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED:
+                       return HAL_H264_DB_MODE_DISABLE;
+               case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED:
+                       return HAL_H264_DB_MODE_ALL_BOUNDARY;
+               case L_MODE:
+                       return HAL_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
+               default:
+                       goto unknown_value;
+               }
+       }
+
+unknown_value:
+       dprintk(VIDC_WARN, "Unknown control (%x, %d)\n", id, value);
+       return -EINVAL;
+}
+
+static struct v4l2_ctrl *
+get_ctrl_from_cluster(int id, struct v4l2_ctrl **cluster, int ncontrols)
+{
+       int c;
+
+       for (c = 0; c < ncontrols; ++c)
+               if (cluster[c]->id == id)
+                       return cluster[c];
+
+       return NULL;
+}
+
+/* Small helper macro for quickly getting a control and err checking */
+#define TRY_GET_CTRL(__ctrl_id) ({ \
+               struct v4l2_ctrl *__temp; \
+               __temp = get_ctrl_from_cluster( \
+                       __ctrl_id, \
+                       ctrl->cluster, ctrl->ncontrols); \
+               if (!__temp) { \
+                       dprintk(VIDC_ERR, "Can't find %s (%x) in cluster\n", \
+                               #__ctrl_id, __ctrl_id); \
+                       /* Clusters are hardcoded, if we can't find */ \
+                       /* something then things are massively screwed up */ \
+                       BUG_ON(1); \
+               } \
+               __temp; \
+       })
+
+static int try_set_ctrl(struct vidc_inst *inst, struct v4l2_ctrl *ctrl)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct vidc_core_capability *cap = &inst->capability;
+       struct hal_request_iframe request_iframe;
+       struct hal_bitrate bitrate;
+       struct hal_profile_level profile_level;
+       struct hal_h264_entropy_control h264_entropy_control;
+       struct hal_quantization quantization;
+       struct hal_intra_period intra_period;
+       struct hal_idr_period idr_period;
+       struct hal_operations operations;
+       struct hal_intra_refresh intra_refresh;
+       struct hal_multi_slice_control multi_slice_control;
+       struct hal_h264_db_control h264_db_control;
+       struct hal_enable enable;
+       struct hal_h264_vui_timing_info vui_timing_info;
+       struct hal_quantization_range qp_range;
+       struct hal_h264_vui_bitstream_restrc vui_bitstream_restrict;
+       struct hal_preserve_text_quality preserve_text_quality;
+       struct hal_extradata_enable extra;
+       struct hal_mpeg4_time_resolution time_res;
+       struct hal_ltr_use use_ltr;
+       struct hal_ltr_mark mark_ltr;
+       struct hal_hybrid_hierp hyb_hierp;
+       struct hal_ltr_mode ltr_mode;
+       struct hal_vc1e_perf_cfg_type search_range = { {0} };
+       struct hal_initial_quantization quant;
+       u32 hier_p_layers = 0;
+       struct hal_venc_perf_mode venc_mode;
+       u32 property_id = 0, property_val = 0;
+       void *pdata = NULL;
+       struct v4l2_ctrl *temp_ctrl = NULL;
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD:
+               if (inst->fmt_cap->pixfmt != V4L2_PIX_FMT_H264 &&
+                   inst->fmt_cap->pixfmt != V4L2_PIX_FMT_H264_NO_SC) {
+                       dev_err(dev, "Control 0x%x only valid for H264\n",
+                               ctrl->id);
+                       ret = -ENOTSUPP;
+                       break;
+               }
+
+               property_id = HAL_CONFIG_VENC_IDR_PERIOD;
+               idr_period.idr_period = ctrl->val;
+               pdata = &idr_period;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES:
+       case V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES: {
+               int num_p, num_b;
+
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES);
+               num_b = temp_ctrl->val;
+
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES);
+               num_p = temp_ctrl->val;
+
+               if (ctrl->id == V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES)
+                       num_p = ctrl->val;
+               else if (ctrl->id == V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES)
+                       num_b = ctrl->val;
+
+               if (num_b) {
+                       u32 max_num_b_frames = MAX_NUM_B_FRAMES;
+
+                       property_id = HAL_PARAM_VENC_MAX_NUM_B_FRAMES;
+                       pdata = &max_num_b_frames;
+
+                       ret = hfi_session_set_property(inst, property_id,
+                                                      pdata);
+                       if (ret) {
+                               dev_err(dev,
+                                       "Failed : Setprop MAX_NUM_B_FRAMES %d\n",
+                                       ret);
+                               break;
+                       }
+               }
+
+               property_id = HAL_CONFIG_VENC_INTRA_PERIOD;
+               intra_period.pframes = num_p;
+               intra_period.bframes = num_b;
+               pdata = &intra_period;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME:
+               property_id = HAL_CONFIG_VENC_REQUEST_IFRAME;
+               request_iframe.enable = true;
+               pdata = &request_iframe;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL:
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: {
+               struct v4l2_ctrl update_ctrl = {.id = 0};
+               int final_mode = 0;
+
+               /* V4L2_CID_MPEG_VIDEO_BITRATE_MODE and _RATE_CONTROL
+                * manipulate the same thing.  If one control's state
+                * changes, try to mirror the state in the other control's
+                * value */
+               if (ctrl->id == V4L2_CID_MPEG_VIDEO_BITRATE_MODE) {
+                       if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
+                               final_mode = HAL_RATE_CONTROL_VBR_CFR;
+                               update_ctrl.val =
+                               V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR;
+                       } else {/* ...if (ctrl->val == _BITRATE_MODE_CBR) */
+                               final_mode = HAL_RATE_CONTROL_CBR_CFR;
+                               update_ctrl.val =
+                               V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR;
+                       }
+
+                       update_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL;
+
+               } else if (ctrl->id == V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL) {
+                       switch (ctrl->val) {
+                       case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF:
+                       case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR:
+                       case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR:
+                               update_ctrl.val =
+                                       V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
+                       case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR:
+                       case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR:
+                               update_ctrl.val =
+                                       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+                       }
+
+                       final_mode = ctrl->val;
+                       update_ctrl.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
+               }
+
+               if (update_ctrl.id) {
+                       temp_ctrl = TRY_GET_CTRL(update_ctrl.id);
+                       temp_ctrl->val = update_ctrl.val;
+               }
+
+               property_id = HAL_PARAM_VENC_RATE_CONTROL;
+               property_val = final_mode;
+               pdata = &property_val;
+
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_BITRATE: {
+               struct v4l2_ctrl *hier_p = TRY_GET_CTRL(
+                               V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS);
+
+               bitrate.layer_id = 0;
+
+               if (hier_p->val && inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264) {
+                       ret = venc_set_bitrate_for_each_layer(inst, hier_p->val,
+                                                             ctrl->val);
+                       if (ret) {
+                               dev_err(dev, "set bitrate for multiple layers\n");
+                               break;
+                       }
+               } else {
+                       property_id = HAL_CONFIG_VENC_TARGET_BITRATE;
+                       bitrate.bit_rate = ctrl->val;
+                       bitrate.layer_id = 0;
+                       pdata = &bitrate;
+               }
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: {
+               struct v4l2_ctrl *avg_bitrate =
+                               TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_BITRATE);
+
+               if (ctrl->val < avg_bitrate->val) {
+                       dev_err(dev,
+                               "Peak bitrate (%d) is lower than average bitrate (%d)\n",
+                               ctrl->val, avg_bitrate->val);
+                       ret = -EINVAL;
+                       break;
+               } else if (ctrl->val < avg_bitrate->val * 2) {
+                       dev_err(dev,
+                               "Peak bitrate (%d) ideally should be twice the average bitrate (%d)\n",
+                               ctrl->val, avg_bitrate->val);
+               }
+
+               property_id = HAL_CONFIG_VENC_MAX_BITRATE;
+               bitrate.bit_rate = ctrl->val;
+               bitrate.layer_id = 0;
+               pdata = &bitrate;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+               temp_ctrl = TRY_GET_CTRL(
+                       V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL);
+
+               property_id = HAL_PARAM_VENC_H264_ENTROPY_CONTROL;
+               h264_entropy_control.entropy_mode = venc_v4l2_to_hal(
+                       V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, ctrl->val);
+               h264_entropy_control.cabac_model = venc_v4l2_to_hal(
+                       V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL,
+                       temp_ctrl->val);
+               pdata = &h264_entropy_control;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE);
+
+               property_id = HAL_PARAM_VENC_H264_ENTROPY_CONTROL;
+               h264_entropy_control.cabac_model = venc_v4l2_to_hal(
+                       V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, ctrl->val);
+               h264_entropy_control.entropy_mode = venc_v4l2_to_hal(
+                       V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL,
+                       temp_ctrl->val);
+               pdata = &h264_entropy_control;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL);
+
+               property_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.profile = venc_v4l2_to_hal(ctrl->id, ctrl->val);
+               profile_level.level = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
+                               temp_ctrl->val);
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE);
+
+               property_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.level = venc_v4l2_to_hal(ctrl->id, ctrl->val);
+               profile_level.profile = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
+                               temp_ctrl->val);
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_LEVEL);
+
+               property_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.profile = venc_v4l2_to_hal(ctrl->id, ctrl->val);
+               profile_level.level = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+                               temp_ctrl->val);
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_PROFILE);
+
+               property_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.level = venc_v4l2_to_hal(ctrl->id, ctrl->val);
+               profile_level.profile = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+                               temp_ctrl->val);
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL);
+
+               property_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.profile = venc_v4l2_to_hal(ctrl->id, ctrl->val);
+               profile_level.level = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL,
+                               temp_ctrl->val);
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE);
+
+               property_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.level = venc_v4l2_to_hal(ctrl->id, ctrl->val);
+               profile_level.profile = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE,
+                               ctrl->val);
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
+               property_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.profile = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL,
+                               ctrl->val);
+               profile_level.level = HAL_VPX_PROFILE_UNUSED;
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
+               temp_ctrl =
+                       TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL);
+
+               property_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.profile = venc_v4l2_to_hal(ctrl->id, ctrl->val);
+               profile_level.level = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL,
+                               temp_ctrl->val);
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE);
+
+               property_id = HAL_PARAM_PROFILE_LEVEL_CURRENT;
+               profile_level.level = venc_v4l2_to_hal(ctrl->id, ctrl->val);
+               profile_level.profile = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE,
+                               temp_ctrl->val);
+               pdata = &profile_level;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION: {
+               struct v4l2_ctrl *deinterlace = NULL;
+
+               if (!(inst->capability.pixelprocess_capabilities &
+                   HAL_VIDEO_ENCODER_ROTATION_CAPABILITY)) {
+                       dev_err(dev, "Rotation not supported: 0x%x\n",
+                               ctrl->id);
+                       ret = -ENOTSUPP;
+                       break;
+               }
+
+               deinterlace =
+                       TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE);
+               if (ctrl->val && deinterlace && deinterlace->val !=
+                   V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED) {
+                       dev_err(dev,
+                               "Rotation not supported with deinterlacing\n");
+                       ret = -EINVAL;
+                       break;
+               }
+               property_id = HAL_CONFIG_VPE_OPERATIONS;
+               operations.rotate = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDC_VIDEO_ROTATION,
+                               ctrl->val);
+               operations.flip = HAL_FLIP_NONE;
+               pdata = &operations;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: {
+               struct v4l2_ctrl *qpp, *qpb;
+
+               qpp = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP);
+               qpb = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP);
+
+               property_id = HAL_PARAM_VENC_SESSION_QP;
+               quantization.qpi = ctrl->val;
+               quantization.qpp = qpp->val;
+               quantization.qpb = qpb->val;
+               quantization.layer_id = 0;
+
+               pdata = &quantization;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: {
+               struct v4l2_ctrl *qpi, *qpb;
+
+               qpi = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP);
+               qpb = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP);
+
+               property_id = HAL_PARAM_VENC_SESSION_QP;
+               quantization.qpp = ctrl->val;
+               quantization.qpi = qpi->val;
+               quantization.qpb = qpb->val;
+               quantization.layer_id = 0;
+
+               pdata = &quantization;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: {
+               struct v4l2_ctrl *qpi, *qpp;
+
+               qpi = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP);
+               qpp = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP);
+
+               property_id = HAL_PARAM_VENC_SESSION_QP;
+               quantization.qpb = ctrl->val;
+               quantization.qpi = qpi->val;
+               quantization.qpp = qpp->val;
+               quantization.layer_id = 0;
+
+               pdata = &quantization;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: {
+               struct v4l2_ctrl *qp_max;
+
+               qp_max = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_MAX_QP);
+               if (ctrl->val >= qp_max->val) {
+                       dev_err(dev, "Bad range: Min QP (%d) > Max QP(%d)\n",
+                               ctrl->val, qp_max->val);
+                       ret = -ERANGE;
+                       break;
+               }
+
+               property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
+               qp_range.layer_id = 0;
+               qp_range.max_qp = qp_max->val;
+               qp_range.min_qp = ctrl->val;
+
+               pdata = &qp_range;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: {
+               struct v4l2_ctrl *qp_min;
+
+               qp_min = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_MIN_QP);
+               if (ctrl->val <= qp_min->val) {
+                       dev_err(dev, "Bad range: Max QP (%d) < Min QP(%d)\n",
+                               ctrl->val, qp_min->val);
+                       ret = -ERANGE;
+                       break;
+               }
+
+               property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
+               qp_range.layer_id = 0;
+               qp_range.max_qp = ctrl->val;
+               qp_range.min_qp = qp_min->val;
+
+               pdata = &qp_range;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDC_VIDEO_VP8_MIN_QP: {
+               struct v4l2_ctrl *qp_max;
+
+               qp_max = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_VP8_MAX_QP);
+               property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
+               qp_range.layer_id = 0;
+               qp_range.max_qp = qp_max->val;
+               qp_range.min_qp = ctrl->val;
+               pdata = &qp_range;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDC_VIDEO_VP8_MAX_QP: {
+               struct v4l2_ctrl *qp_min;
+
+               qp_min = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_VP8_MIN_QP);
+               property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
+               qp_range.layer_id = 0;
+               qp_range.max_qp = ctrl->val;
+               qp_range.min_qp = qp_min->val;
+               pdata = &qp_range;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: {
+               int temp = 0;
+
+               switch (ctrl->val) {
+               case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB:
+                       temp = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
+                       break;
+               case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES:
+                       temp = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
+                       break;
+               case V4L2_MPEG_VIDEO_MULTI_SLICE_GOB:
+                       temp = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_GOB;
+                       break;
+               case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
+               default:
+                       temp = 0;
+                       break;
+               }
+
+               if (temp)
+                       temp_ctrl = TRY_GET_CTRL(temp);
+
+               property_id = HAL_PARAM_VENC_MULTI_SLICE_CONTROL;
+               multi_slice_control.multi_slice = ctrl->val;
+               multi_slice_control.slice_size = temp ? temp_ctrl->val : 0;
+
+               pdata = &multi_slice_control;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_GOB:
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE);
+
+               property_id = HAL_PARAM_VENC_MULTI_SLICE_CONTROL;
+               multi_slice_control.multi_slice = temp_ctrl->val;
+               multi_slice_control.slice_size = ctrl->val;
+               pdata = &multi_slice_control;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE: {
+               temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE);
+
+               if ((temp_ctrl->val == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB)
+                   && (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
+                       inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264_NO_SC)) {
+                       property_id = HAL_PARAM_VENC_SLICE_DELIVERY_MODE;
+                       enable.enable = true;
+               } else {
+                       dev_warn(dev,
+                               "Failed : slice delivery mode is valid "\
+                               "only for H264 encoder and MB based slicing\n");
+                       enable.enable = false;
+               }
+               pdata = &enable;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE: {
+               struct v4l2_ctrl *air_mbs, *air_ref, *cir_mbs;
+
+               air_mbs = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS);
+               air_ref = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_REF);
+               cir_mbs = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_CIR_MBS);
+
+               property_id = HAL_PARAM_VENC_INTRA_REFRESH;
+
+               intra_refresh.mode = ctrl->val;
+               intra_refresh.air_mbs = air_mbs->val;
+               intra_refresh.air_ref = air_ref->val;
+               intra_refresh.cir_mbs = cir_mbs->val;
+
+               pdata = &intra_refresh;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS: {
+               struct v4l2_ctrl *ir_mode, *air_ref, *cir_mbs;
+
+               ir_mode = TRY_GET_CTRL(
+                               V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE);
+               air_ref = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_REF);
+               cir_mbs = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_CIR_MBS);
+
+               property_id = HAL_PARAM_VENC_INTRA_REFRESH;
+
+               intra_refresh.air_mbs = ctrl->val;
+               intra_refresh.mode = ir_mode->val;
+               intra_refresh.air_ref = air_ref->val;
+               intra_refresh.cir_mbs = cir_mbs->val;
+
+               pdata = &intra_refresh;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDC_VIDEO_AIR_REF: {
+               struct v4l2_ctrl *ir_mode, *air_mbs, *cir_mbs;
+
+               ir_mode = TRY_GET_CTRL(
+                               V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE);
+               air_mbs = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS);
+               cir_mbs = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_CIR_MBS);
+
+               property_id = HAL_PARAM_VENC_INTRA_REFRESH;
+
+               intra_refresh.air_ref = ctrl->val;
+               intra_refresh.air_mbs = air_mbs->val;
+               intra_refresh.mode = ir_mode->val;
+               intra_refresh.cir_mbs = cir_mbs->val;
+
+               pdata = &intra_refresh;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDC_VIDEO_CIR_MBS: {
+               struct v4l2_ctrl *ir_mode, *air_mbs, *air_ref;
+
+               ir_mode = TRY_GET_CTRL(
+                               V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE);
+               air_mbs = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS);
+               air_ref = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_REF);
+
+               property_id = HAL_PARAM_VENC_INTRA_REFRESH;
+
+               intra_refresh.cir_mbs = ctrl->val;
+               intra_refresh.air_mbs = air_mbs->val;
+               intra_refresh.air_ref = air_ref->val;
+               intra_refresh.mode = ir_mode->val;
+
+               pdata = &intra_refresh;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: {
+               struct v4l2_ctrl *air_mbs, *air_ref;
+
+               air_mbs = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS);
+               air_ref = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_REF);
+
+               property_id = HAL_PARAM_VENC_INTRA_REFRESH;
+
+               intra_refresh.cir_mbs = ctrl->val;
+               intra_refresh.air_mbs = air_mbs->val;
+               intra_refresh.air_ref = air_ref->val;
+               intra_refresh.mode = HAL_INTRA_REFRESH_CYCLIC;
+
+               pdata = &intra_refresh;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: {
+               struct v4l2_ctrl *alpha, *beta;
+
+               alpha = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA);
+               beta = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA);
+
+               property_id = HAL_PARAM_VENC_H264_DEBLOCK_CONTROL;
+               h264_db_control.slice_alpha_offset = alpha->val;
+               h264_db_control.slice_beta_offset = beta->val;
+               h264_db_control.mode = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+                               ctrl->val);
+               pdata = &h264_db_control;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: {
+               struct v4l2_ctrl *mode, *beta;
+
+               mode = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE);
+               beta = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA);
+
+               property_id = HAL_PARAM_VENC_H264_DEBLOCK_CONTROL;
+               h264_db_control.slice_alpha_offset = ctrl->val;
+               h264_db_control.slice_beta_offset = beta->val;
+               h264_db_control.mode = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+                               mode->val);
+               pdata = &h264_db_control;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: {
+               struct v4l2_ctrl *mode, *alpha;
+
+               mode = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE);
+               alpha = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA);
+
+               property_id = HAL_PARAM_VENC_H264_DEBLOCK_CONTROL;
+               h264_db_control.slice_alpha_offset = alpha->val;
+               h264_db_control.slice_beta_offset = ctrl->val;
+               h264_db_control.mode = venc_v4l2_to_hal(
+                               V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+                               mode->val);
+               pdata = &h264_db_control;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+               property_id = HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER;
+
+               switch (ctrl->val) {
+               case V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE:
+                       enable.enable = 0;
+                       break;
+               case V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME:
+                       enable.enable = 1;
+                       break;
+               case V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME:
+               default:
+                       ret = -ENOTSUPP;
+                       break;
+               }
+               pdata = &enable;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
+               inst->flags |= VIDC_SECURE;
+               dev_info(dev, "Setting secure mode to: %d\n",
+                       !!(inst->flags & VIDC_SECURE));
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA:
+               property_id = HAL_PARAM_INDEX_EXTRADATA;
+               extra.index = vidc_comm_get_hal_extradata_index(ctrl->val);
+               extra.enable = 1;
+               pdata = &extra;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO: {
+               struct v4l2_ctrl *rc_mode;
+               u32 cfr = 0;
+
+               property_id = HAL_PARAM_VENC_H264_VUI_TIMING_INFO;
+               rc_mode = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL);
+
+               switch (rc_mode->val) {
+               case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR:
+               case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR:
+                       cfr = 1;
+                       break;
+               default:
+                       cfr = 0;
+                       break;
+               }
+
+               switch (ctrl->val) {
+               case V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED:
+                       vui_timing_info.enable = 0;
+                       break;
+               case V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED:
+                       vui_timing_info.enable = 1;
+                       vui_timing_info.fixed_frame_rate = cfr;
+                       vui_timing_info.time_scale = NSEC_PER_SEC;
+               }
+
+               pdata = &vui_timing_info;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDC_VIDEO_H264_AU_DELIMITER:
+               property_id = HAL_PARAM_VENC_H264_GENERATE_AUDNAL;
+
+               switch (ctrl->val) {
+               case V4L2_MPEG_VIDC_VIDEO_H264_AU_DELIMITER_DISABLED:
+                       enable.enable = 0;
+                       break;
+               case V4L2_MPEG_VIDC_VIDEO_H264_AU_DELIMITER_ENABLED:
+                       enable.enable = 1;
+                       break;
+               default:
+                       ret = -ENOTSUPP;
+                       break;
+               }
+
+               pdata = &enable;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_BITSTREAM_RESTRICT:
+               property_id = HAL_PARAM_VENC_H264_VUI_BITSTREAM_RESTRC;
+               vui_bitstream_restrict.enable = ctrl->val;
+               pdata = &vui_bitstream_restrict;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_PRESERVE_TEXT_QUALITY:
+               property_id = HAL_PARAM_VENC_PRESERVE_TEXT_QUALITY;
+               preserve_text_quality.enable = ctrl->val;
+               pdata = &preserve_text_quality;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_MPEG4_TIME_RESOLUTION:
+               property_id = HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION;
+               time_res.time_increment_resolution = ctrl->val;
+               pdata = &time_res;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE: {
+               struct v4l2_ctrl *rotation = NULL;
+
+               if (!(inst->capability.pixelprocess_capabilities &
+                       HAL_VIDEO_ENCODER_DEINTERLACE_CAPABILITY)) {
+                       dev_err(dev, "Deinterlace not supported: 0x%x\n",
+                               ctrl->id);
+                       ret = -ENOTSUPP;
+                       break;
+               }
+
+               rotation = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_ROTATION);
+               if (ctrl->val && rotation && rotation->val !=
+                       V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_NONE) {
+                       dev_err(dev, "Deinterlacing not supported with rotation");
+                       ret = -EINVAL;
+                       break;
+               }
+               property_id = HAL_CONFIG_VPE_DEINTERLACE;
+               switch (ctrl->val) {
+               case V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_ENABLED:
+                       enable.enable = 1;
+                       break;
+               case V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED:
+               default:
+                       enable.enable = 0;
+                       break;
+               }
+               pdata = &enable;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_SEQ_HEADER:
+               atomic_inc(&inst->seq_hdr_reqs);
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME:
+               property_id = HAL_CONFIG_VENC_USELTRFRAME;
+               use_ltr.ref_ltr = (1 << ctrl->val);
+               use_ltr.use_constraint = false;
+               use_ltr.frames = 0;
+               pdata = &use_ltr;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME:
+               property_id = HAL_CONFIG_VENC_MARKLTRFRAME;
+               mark_ltr.mark_frame = ctrl->val;
+               pdata = &mark_ltr;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS:
+               property_id = HAL_CONFIG_VENC_HIER_P_NUM_FRAMES;
+               hier_p_layers = ctrl->val;
+
+               ret = venc_toggle_hier_p(inst, ctrl->val);
+               if (ret)
+                       break;
+
+               if (hier_p_layers > inst->capability.hier_p.max) {
+                       dev_err(dev, "Error setting hier p num layers %d, max supported %d\n",
+                               hier_p_layers, inst->capability.hier_p.max);
+                       ret= -ENOTSUPP;
+                       break;
+               }
+               pdata = &hier_p_layers;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE:
+               property_id = HAL_PARAM_VENC_DISABLE_RC_TIMESTAMP;
+               enable.enable = (ctrl->val ==
+                       V4L2_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE_IGNORE);
+               pdata = &enable;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE:
+               property_id = HAL_PARAM_VENC_VPX_ERROR_RESILIENCE_MODE;
+               enable.enable = ctrl->val;
+               pdata = &enable;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC:
+               property_id = HAL_PARAM_VENC_H264_NAL_SVC_EXT;
+               enable.enable = ctrl->val;
+               pdata = &enable;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE:
+               property_id = HAL_CONFIG_VENC_PERF_MODE;
+               venc_mode.mode = ctrl->val;
+               pdata = &venc_mode;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE:
+               property_id = HAL_PARAM_VENC_HIER_P_HYBRID_MODE;
+               hyb_hierp.layers = ctrl->val;
+               pdata = &hyb_hierp;
+               break;
+
+       case V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE:
+               if (ctrl->val != V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE) {
+                       ret = venc_toggle_hier_p(inst, false);
+                       if (ret)
+                               break;
+               }
+
+               ltr_mode.mode = ctrl->val;
+               ltr_mode.trust_mode = 1;
+               property_id = HAL_PARAM_VENC_LTRMODE;
+               pdata = &ltr_mode;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT:
+               ltr_mode.count = ctrl->val;
+               if (ltr_mode.count > cap->ltr_count.max) {
+                       dev_err(dev, "Invalid LTR count %d, max supported %d\n",
+                               ltr_mode.count, cap->ltr_count.max);
+                       /*
+                        * FIXME: Return an error (-EINVAL)
+                        * here once VP8 supports LTR count
+                        * capability
+                        */
+                       ltr_mode.count = 1;
+               }
+               ltr_mode.trust_mode = 1;
+               property_id = HAL_PARAM_VENC_LTRMODE;
+               pdata = &ltr_mode;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_INITIAL_QP:
+               property_id = HAL_PARAM_VENC_ENABLE_INITIAL_QP;
+               quant.init_qp_enable = ctrl->val;
+               pdata = &quant;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP:
+               quant.qpi = ctrl->val;
+               property_id = HAL_PARAM_VENC_ENABLE_INITIAL_QP;
+               pdata = &quant;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP:
+               quant.qpp = ctrl->val;
+               property_id = HAL_PARAM_VENC_ENABLE_INITIAL_QP;
+               pdata = &quant;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP:
+               quant.qpb = ctrl->val;
+               property_id = HAL_PARAM_VENC_ENABLE_INITIAL_QP;
+               pdata = &quant;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_X_RANGE:
+               search_range.i_frame.x_subsampled = ctrl->val;
+               property_id = HAL_PARAM_VENC_SEARCH_RANGE;
+               pdata = &search_range;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_Y_RANGE:
+               search_range.i_frame.y_subsampled = ctrl->val;
+               property_id = HAL_PARAM_VENC_SEARCH_RANGE;
+               pdata = &search_range;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_PFRAME_X_RANGE:
+               search_range.p_frame.x_subsampled = ctrl->val;
+               property_id = HAL_PARAM_VENC_SEARCH_RANGE;
+               pdata = &search_range;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_PFRAME_Y_RANGE:
+               search_range.p_frame.y_subsampled = ctrl->val;
+               property_id = HAL_PARAM_VENC_SEARCH_RANGE;
+               pdata = &search_range;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_BFRAME_X_RANGE:
+               search_range.b_frame.x_subsampled = ctrl->val;
+               property_id = HAL_PARAM_VENC_SEARCH_RANGE;
+               pdata = &search_range;
+               break;
+       case V4L2_CID_MPEG_VIDC_VIDEO_BFRAME_Y_RANGE:
+               search_range.b_frame.y_subsampled = ctrl->val;
+               property_id = HAL_PARAM_VENC_SEARCH_RANGE;
+               pdata = &search_range;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+       case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:
+       case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
+               ret = 0;
+               property_id = 0;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       if (!ret && property_id) {
+               dev_dbg(dev, "control: hal property:%x, value:%d\n",
+                       property_id, ctrl->val);
+               ret = hfi_session_set_property(inst, property_id, pdata);
+       }
+
+       return ret;
+}
+
+static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct vidc_inst *inst =
+               container_of(ctrl->handler, struct vidc_inst, ctrl_handler);
+       struct device *dev = &inst->core->res.pdev->dev;
+       int ret = 0, c;
+
+       for (c = 0; c < ctrl->ncontrols; ++c) {
+               struct v4l2_ctrl *temp = ctrl->cluster[c];
+
+               if (!ctrl->cluster[c]->is_new)
+                       continue;
+
+               ret = try_set_ctrl(inst, temp);
+               if (ret) {
+                       dev_err(dev, "try set ctrl: %s id: %x (%d)\n",
+                               v4l2_ctrl_get_name(temp->id), temp->id,
+                               ret);
+                       break;
+               }
+       }
+
+       if (ret)
+               dev_err(dev, "setting control: %x (%s) failed\n",
+                       ctrl->id, v4l2_ctrl_get_name(ctrl->id));
+
+       return ret;
+}
+
+static const struct v4l2_ctrl_ops venc_ctrl_ops = {
+       .s_ctrl = venc_op_s_ctrl,
+};
+
+static struct v4l2_ctrl **get_super_cluster(struct vidc_inst *inst, int *size)
+{
+       int c, sz = 0;
+       struct v4l2_ctrl **cluster = kmalloc(sizeof(struct v4l2_ctrl *) *
+                                            NUM_CTRLS, GFP_KERNEL);
+
+       if (!size || !cluster || !inst)
+               return NULL;
+
+       for (c = 0; c < NUM_CTRLS; c++)
+               cluster[sz++] = inst->ctrls[c];
+
+       *size = sz;
+
+       return cluster;
+}
+
+int venc_ctrl_init(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct v4l2_ctrl_config cfg;
+       int cluster_size = 0;
+       unsigned int idx;
+       int ret;
+
+       inst->ctrls = kzalloc(sizeof(struct v4l2_ctrl *) * NUM_CTRLS,
+                             GFP_KERNEL);
+       if (!inst->ctrls)
+               return -ENOMEM;
+
+       ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, NUM_CTRLS);
+       if (ret) {
+               dev_err(dev, "ctrl handler init (%d)\n", ret);
+               return ret;
+       }
+
+       for (idx = 0; idx < NUM_CTRLS; idx++) {
+               struct v4l2_ctrl *ctrl;
+
+               if (IS_PRIV_CTRL(venc_ctrls[idx].id)) {
+                       memset(&cfg, 0, sizeof(cfg));
+                       cfg.def = venc_ctrls[idx].default_value;
+                       cfg.flags = 0;
+                       cfg.id = venc_ctrls[idx].id;
+                       cfg.max = venc_ctrls[idx].maximum;
+                       cfg.min = venc_ctrls[idx].minimum;
+                       cfg.menu_skip_mask = venc_ctrls[idx].menu_skip_mask;
+                       cfg.name = venc_ctrls[idx].name;
+                       cfg.ops = &venc_ctrl_ops;
+                       cfg.step = venc_ctrls[idx].step;
+                       cfg.type = venc_ctrls[idx].type;
+                       cfg.qmenu = venc_ctrls[idx].qmenu;
+                       ctrl = v4l2_ctrl_new_custom(&inst->ctrl_handler, &cfg,
+                                                   NULL);
+               } else {
+                       if (venc_ctrls[idx].type == V4L2_CTRL_TYPE_MENU) {
+                               ctrl = v4l2_ctrl_new_std_menu(
+                                               &inst->ctrl_handler,
+                                               &venc_ctrl_ops,
+                                               venc_ctrls[idx].id,
+                                               venc_ctrls[idx].maximum,
+                                               venc_ctrls[idx].menu_skip_mask,
+                                               venc_ctrls[idx].default_value);
+                       } else {
+                               ctrl = v4l2_ctrl_new_std(
+                                               &inst->ctrl_handler,
+                                               &venc_ctrl_ops,
+                                               venc_ctrls[idx].id,
+                                               venc_ctrls[idx].minimum,
+                                               venc_ctrls[idx].maximum,
+                                               venc_ctrls[idx].step,
+                                               venc_ctrls[idx].default_value);
+                       }
+               }
+
+               ret = inst->ctrl_handler.error;
+               if (ret) {
+                       dev_err(dev, "adding ctrl (%s) to ctrl handle (%d)\n",
+                               venc_ctrls[idx].name, ret);
+                       return ret;
+               }
+
+               inst->ctrls[idx] = ctrl;
+       }
+
+       /* Construct a super cluster of all controls */
+       inst->cluster = get_super_cluster(inst, &cluster_size);
+       if (!inst->cluster || !cluster_size) {
+               dev_err(dev, "setup super cluster\n");
+               return -EINVAL;
+       }
+
+       v4l2_ctrl_cluster(cluster_size, inst->cluster);
+
+       return 0;
+}
+
+void venc_ctrl_deinit(struct vidc_inst *inst)
+{
+       kfree(inst->ctrls);
+       kfree(inst->cluster);
+       v4l2_ctrl_handler_free(&inst->ctrl_handler);
+}
diff --git a/drivers/media/platform/msm/vidc/msm_venc-ctrls.h b/drivers/media/platform/msm/vidc/msm_venc-ctrls.h
new file mode 100644 (file)
index 0000000..802f8d6
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _MSM_VENC_CTRLS_H_
+#define _MSM_VENC_CTRLS_H_
+
+int venc_ctrl_init(struct vidc_inst *inst);
+void venc_ctrl_deinit(struct vidc_inst *inst);
+
+#endif /* _MSM_VENC_CTRLS_H_ */
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
new file mode 100644 (file)
index 0000000..7c741cd
--- /dev/null
@@ -0,0 +1,1521 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/qcom_iommu.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "msm_vidc_internal.h"
+#include "msm_vidc_common.h"
+#include "hfi/vidc_hfi_api.h"
+#include "msm_vidc_debug.h"
+#include "msm_internal-buffers.h"
+#include "msm_vidc_load.h"
+#include "msm_hfi_interface.h"
+#include "msm_venc-ctrls.h"
+
+#define MIN_NUM_OUTPUT_BUFFERS         4
+#define MIN_NUM_CAPTURE_BUFFERS                4
+
+/* Offset base for buffers on the destination queue - used to distinguish
+ * between source and destination buffers when mmapping - they receive the same
+ * offsets but for different queues */
+#define DST_QUEUE_OFF_BASE     (1 << 30)
+
+/*
+ * Default 601 to 709 conversion coefficients for resolution: 176x144 negative
+ * coeffs are converted to s4.9 format (e.g. -22 converted to ((1<<13) - 22)
+ * 3x3 transformation matrix coefficients in s4.9 fixed point format
+ */
+static u32 vpe_csc_601_to_709_matrix_coeff[HAL_MAX_MATRIX_COEFFS] = {
+       470, 8170, 8148, 0, 490, 50, 0, 34, 483
+};
+
+/* offset coefficients in s9 fixed point format */
+static u32 vpe_csc_601_to_709_bias_coeff[HAL_MAX_BIAS_COEFFS] = {
+       34, 0, 4
+};
+
+/* clamping value for Y/U/V([min,max] for Y/U/V) */
+static u32 vpe_csc_601_to_709_limit_coeff[HAL_MAX_LIMIT_COEFFS] = {
+       16, 235, 16, 240, 16, 240
+};
+
+struct venc_buffer {
+       struct vb2_buffer vb;
+       struct list_head list;
+       dma_addr_t dma_addr;
+       struct buffer_info bi;
+};
+
+#define to_venc_buffer(buf)    container_of(buf, struct venc_buffer, vb)
+
+static inline struct vidc_inst *to_inst(struct file *filp, void *fh)
+{
+       return container_of(filp->private_data, struct vidc_inst, fh);
+}
+
+static u32 get_framesize_nv12(int plane, u32 height, u32 width)
+{
+       u32 y_stride, uv_stride, y_plane;
+       u32 y_sclines, uv_sclines, uv_plane;
+       u32 size;
+
+       y_stride = ALIGN(width, 128);
+       uv_stride = ALIGN(width, 128);
+       y_sclines = ALIGN(height, 32);
+       uv_sclines = ALIGN(((height + 1) >> 1), 16);
+
+       y_plane = y_stride * y_sclines;
+       uv_plane = uv_stride * uv_sclines + SZ_4K;
+       size = y_plane + uv_plane + SZ_8K;
+       size = ALIGN(size, SZ_4K);
+
+       return size;
+}
+
+static u32 get_framesize_nv21(int plane, u32 height, u32 width)
+{
+       return get_framesize_nv12(plane, height, width);
+}
+
+static u32 get_framesize_compressed(int plane, u32 height, u32 width)
+{
+       u32 sz = ALIGN(height, 32) * ALIGN(width, 32) * 3 / 2;
+
+       return ALIGN(sz, SZ_4K);
+}
+
+static const struct vidc_format venc_formats[] = {
+       {
+               .pixfmt = V4L2_PIX_FMT_NV12,
+               .num_planes = 1,
+               .get_framesize = get_framesize_nv12,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_NV21,
+               .num_planes = 1,
+               .get_framesize = get_framesize_nv21,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_MPEG4,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_H263,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_H264,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+       },
+       {
+               .pixfmt = V4L2_PIX_FMT_VP8,
+               .num_planes = 1,
+               .get_framesize = get_framesize_compressed,
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+       },
+};
+
+static const struct vidc_format *find_format(u32 pixfmt, int type)
+{
+       const struct vidc_format *fmt = venc_formats;
+       unsigned int size = ARRAY_SIZE(venc_formats);
+       unsigned int i;
+
+       for (i = 0; i < size; i++) {
+               if (fmt[i].pixfmt == pixfmt)
+                       break;
+       }
+
+       if (i == size || fmt[i].type != type)
+               return NULL;
+
+       return &fmt[i];
+}
+
+static const struct vidc_format *find_format_by_index(int index, int type)
+{
+       const struct vidc_format *fmt = venc_formats;
+       unsigned int size = ARRAY_SIZE(venc_formats);
+       int i, k = 0;
+
+       if (index < 0 || index > size)
+               return NULL;
+
+       for (i = 0; i < size; i++) {
+               if (fmt[i].type != type)
+                       continue;
+               if (k == index)
+                       break;
+               k++;
+       }
+
+       if (i == size)
+               return NULL;
+
+       return &fmt[i];
+}
+
+static struct vb2_queue *
+venc_to_vb2q(struct vidc_inst *inst, enum v4l2_buf_type type)
+{
+       if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return &inst->bufq_cap;
+       else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return &inst->bufq_out;
+
+       return NULL;
+}
+
+int venc_toggle_hier_p(struct vidc_inst *inst, int layers)
+{
+       int num_enh_layers = 0;
+       u32 prop_id;
+       int ret;
+
+       if (inst->fmt_cap->pixfmt != V4L2_PIX_FMT_VP8 &&
+           inst->fmt_cap->pixfmt != V4L2_PIX_FMT_H264)
+               return 0;
+
+       num_enh_layers = layers ? : 0;
+
+       dprintk(VIDC_DBG, "%s Hier-P in firmware\n",
+               num_enh_layers ? "Enable" : "Disable");
+
+       prop_id = HAL_PARAM_VENC_HIER_P_MAX_ENH_LAYERS;
+
+       ret = hfi_session_set_property(inst, prop_id, &num_enh_layers);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+int venc_set_bitrate_for_each_layer(struct vidc_inst *inst, u32 num_enh_layers,
+                                   u32 total_bitrate)
+{
+       struct hal_bitrate bitrate;
+       u32 bitrate_table[3][4] = {
+               {50, 50, 0, 0},
+               {34, 33, 33, 0},
+               {25, 25, 25, 25}
+       };
+       u32 prop_id, i;
+       int ret;
+
+       if (!num_enh_layers || num_enh_layers > ARRAY_SIZE(bitrate_table))
+               return -EINVAL;
+
+       prop_id = HAL_CONFIG_VENC_TARGET_BITRATE;
+
+       for (i = 0; !ret && i <= num_enh_layers; i++) {
+               bitrate.bit_rate = (total_bitrate *
+                               bitrate_table[num_enh_layers - 1][i]) / 100;
+               bitrate.layer_id = i;
+
+               ret = hfi_session_set_property(inst, prop_id, &bitrate);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int venc_set_csc(struct vidc_inst *inst)
+{
+       struct hal_vpe_color_space_conversion vpe_csc;
+       enum hal_property prop_id;
+       int ret, count = 0;
+
+       if (!vidc_vpe_csc_601_to_709)
+               return 0;
+
+       while (count < HAL_MAX_MATRIX_COEFFS) {
+               if (count < HAL_MAX_BIAS_COEFFS)
+                       vpe_csc.csc_bias[count] =
+                               vpe_csc_601_to_709_bias_coeff[count];
+               if (count < HAL_MAX_LIMIT_COEFFS)
+                       vpe_csc.csc_limit[count] =
+                               vpe_csc_601_to_709_limit_coeff[count];
+               vpe_csc.csc_matrix[count] =
+                       vpe_csc_601_to_709_matrix_coeff[count];
+               count++;
+       }
+
+       prop_id = HAL_PARAM_VPE_COLOR_SPACE_CONVERSION;
+
+       ret = hfi_session_set_property(inst, prop_id, &vpe_csc);
+       if (ret) {
+               dprintk(VIDC_ERR, "Setting VPE coefficients failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int venc_set_properties(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hal_frame_rate framerate;
+       struct v4l2_ctrl *ctrl;
+       u32 prop_id;
+       s32 value;
+       int ret;
+
+       prop_id = HAL_CONFIG_FRAME_RATE;
+       framerate.buffer_type = HAL_BUFFER_OUTPUT;
+       framerate.frame_rate = inst->fps * (1 << 16);
+
+       ret = hfi_session_set_property(inst, prop_id, &framerate);
+       if (ret) {
+               dev_err(dev, "set framerate failed (%d)\n", ret);
+               return ret;
+       }
+
+       /* set VUI timing info */
+       ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
+                             V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO);
+       if (ctrl)
+               ret = v4l2_ctrl_s_ctrl(ctrl,
+                       V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED);
+
+       ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
+                             V4L2_CID_MPEG_VIDEO_BITRATE);
+       if (ctrl) {
+               value = v4l2_ctrl_g_ctrl(ctrl);
+
+               ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
+                                     V4L2_CID_MPEG_VIDEO_BITRATE_PEAK);
+               if (ctrl) {
+                       value = value * 2;
+                       ret = v4l2_ctrl_s_ctrl(ctrl, value);
+               }
+       }
+
+       return 0;
+}
+
+static int
+venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+       strlcpy(cap->driver, VIDC_DRV_NAME, sizeof(cap->driver));
+       strlcpy(cap->card, "video encoder", sizeof(cap->card));
+       strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
+       cap->version = VIDC_VERSION;
+
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+                           V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING |
+                           V4L2_CAP_DEVICE_CAPS;
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+                          V4L2_CAP_VIDEO_OUTPUT_MPLANE |
+                          V4L2_CAP_STREAMING;
+
+       return 0;
+}
+
+static int venc_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+       const struct vidc_format *fmt;
+
+       fmt = find_format_by_index(f->index, f->type);
+
+       memset(f->reserved, 0 , sizeof(f->reserved));
+
+       if (!fmt)
+               return -EINVAL;
+
+       f->pixelformat = fmt->pixfmt;
+
+       return 0;
+}
+
+static int venc_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
+       u32 pixelformat = pixmp->pixelformat;
+       const struct vidc_format *fmt;
+       struct vidc_core_capability *cap = &inst->capability;
+
+       fmt = find_format(pixelformat, f->type);
+       if (!fmt)
+               return -EINVAL;
+
+       pixmp->width = clamp(pixmp->width, cap->width.min, cap->width.max);
+       pixmp->height = clamp(pixmp->height, cap->height.min, cap->height.max);
+       pixmp->field = V4L2_FIELD_NONE;
+       pixmp->colorspace = V4L2_COLORSPACE_DEFAULT;
+       pixmp->num_planes = fmt->num_planes;
+       pixmp->flags = 0;
+
+       return 0;
+}
+
+static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct hfi_device *hdev = inst->core->hfidev;
+       struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
+       const struct vidc_format *fmt;
+       int ret, i;
+
+       ret = venc_set_csc(inst);
+       if (ret)
+               return ret;
+
+       inst->width = pixmp->width;
+       inst->height = pixmp->height;
+
+       fmt = find_format(pixmp->pixelformat, f->type);
+       if (!fmt)
+               return -EINVAL;
+
+       ret = vidc_check_session_supported(inst);
+       if (ret) {
+               dprintk(VIDC_ERR, "%s: session not supported\n", __func__);
+               return ret;
+       }
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = hfi_session_init(inst, fmt->pixfmt);
+               if (ret) {
+                       dprintk(VIDC_ERR, "Failed to init session (%d)\n", ret);
+                       return ret;
+               }
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               struct hal_uncompressed_format_select hal_fmt;
+               struct hal_buffer_requirements *bufreq;
+               struct hal_frame_size fs;
+               int extra_idx;
+
+               fs.buffer_type = HAL_BUFFER_INPUT;
+               fs.width = inst->width;
+               fs.height = inst->height;
+
+               ret = hfi_session_set_property(inst, HAL_PARAM_FRAME_SIZE, &fs);
+               if (ret) {
+                       dprintk(VIDC_ERR,
+                               "set framesize for input failed (%d)\n", ret);
+                       return ret;
+               }
+
+               fs.buffer_type = HAL_BUFFER_OUTPUT;
+               fs.width = inst->width;
+               fs.height = inst->height;
+
+               ret = hfi_session_set_property(inst, HAL_PARAM_FRAME_SIZE, &fs);
+               if (ret) {
+                       dprintk(VIDC_ERR,
+                               "set framesize for output failed (%d)\n", ret);
+                       return ret;
+               }
+
+               switch (fmt->pixfmt) {
+               case V4L2_PIX_FMT_NV12:
+                       hal_fmt.format = HAL_COLOR_FORMAT_NV12;
+                       break;
+               case V4L2_PIX_FMT_NV21:
+                       hal_fmt.format = HAL_COLOR_FORMAT_NV21;
+                       break;
+               default:
+                       return -ENOTSUPP;
+               }
+
+               hal_fmt.buffer_type = HAL_BUFFER_INPUT;
+
+               ret = hfi_session_set_property(inst,
+                               HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT, &hal_fmt);
+               if (ret) {
+                       dprintk(VIDC_ERR,
+                               "setting uncompressed color format failed (%d)\n",
+                               ret);
+                       return ret;
+               }
+
+               extra_idx = EXTRADATA_IDX(fmt->num_planes);
+               if (extra_idx && extra_idx < VIDEO_MAX_PLANES) {
+                       bufreq = get_buff_req_buffer(inst,
+                                               HAL_BUFFER_EXTRADATA_INPUT);
+                       pixmp->plane_fmt[extra_idx].sizeimage =
+                                               bufreq ? bufreq->size : 0;
+               }
+       }
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               inst->fmt_cap = fmt;
+       else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               inst->fmt_out = fmt;
+       else
+               return -EINVAL;
+
+       pixmp->num_planes = fmt->num_planes;
+
+       for (i = 0; i < fmt->num_planes; ++i) {
+               pixmp->plane_fmt[i].sizeimage =
+                       fmt->get_framesize(i, pixmp->height, pixmp->width);
+
+               pixmp->plane_fmt[i].bytesperline = 0;
+
+               if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+                       u32 bytesperline;
+
+                       call_hfi_op(hdev, get_stride_scanline, COLOR_FMT_NV12,
+                                   pixmp->width, pixmp->height,
+                                   &bytesperline, NULL);
+
+                       pixmp->plane_fmt[i].bytesperline = bytesperline;
+               }
+       }
+
+       return 0;
+}
+
+static int venc_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct hfi_device *hdev = inst->core->hfidev;
+       struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
+       struct hal_buffer_requirements *bufreq = NULL;
+       const struct vidc_format *fmt = NULL;
+       unsigned int extra_idx = 0;
+       u32 height, width;
+       int ret = 0, i;
+
+       ret = vidc_comm_get_bufreqs(inst);
+       if (ret) {
+               dprintk(VIDC_WARN, "Getting buffer requirements failed: %d\n",
+                       ret);
+               return ret;
+       }
+
+       height = inst->height;
+       width = inst->width;
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               fmt = inst->fmt_cap;
+       else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               fmt = inst->fmt_out;
+       else
+               return -ENOTSUPP;
+
+       pixmp->pixelformat = fmt->pixfmt;
+       pixmp->height = height;
+       pixmp->width = width;
+       pixmp->num_planes = fmt->num_planes;
+
+       for (i = 0; i < fmt->num_planes; ++i) {
+               pixmp->plane_fmt[i].sizeimage =
+                               fmt->get_framesize(i, height, width);
+
+               pixmp->plane_fmt[i].bytesperline = 0;
+
+               if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+                       u32 bytesperline;
+
+                       call_hfi_op(hdev, get_stride_scanline, COLOR_FMT_NV12,
+                                   width, height, &bytesperline, NULL);
+
+                       pixmp->plane_fmt[i].bytesperline = bytesperline;
+               }
+       }
+
+       extra_idx = EXTRADATA_IDX(fmt->num_planes);
+       if (extra_idx && extra_idx < VIDEO_MAX_PLANES) {
+               if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+                       bufreq = get_buff_req_buffer(inst,
+                                               HAL_BUFFER_EXTRADATA_OUTPUT);
+               else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+                       bufreq = get_buff_req_buffer(inst,
+                                               HAL_BUFFER_EXTRADATA_INPUT);
+
+               pixmp->plane_fmt[extra_idx].sizeimage =
+                                       bufreq ? bufreq->size : 0;
+       }
+
+       return ret;
+}
+
+static int
+venc_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = venc_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_reqbufs(queue, b);
+}
+
+static int venc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+       int ret = 0, i;
+
+       if (b->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+
+       queue = venc_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       ret = vb2_querybuf(queue, b);
+       if (ret)
+               return ret;
+
+       if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               for (i = 0; i < b->length; i++)
+                       b->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE;
+       }
+
+       return 0;
+}
+
+static int venc_prepare_buf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = venc_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_prepare_buf(queue, b);
+}
+
+static int venc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+       unsigned int state;
+
+       queue = venc_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       mutex_lock(&inst->lock);
+       state = inst->state;
+       mutex_unlock(&inst->lock);
+
+       /*
+        * it is possible userspace to continue to queuing buffres even
+        * while we are in streamoff. Not sure is this a problem in
+        * videobuf2 core, still. Fix it here for now.
+        */
+       if (state >= INST_STOP)
+               return -EINVAL;
+
+       return vb2_qbuf(queue, b);
+}
+
+static int
+venc_exportbuf(struct file *file, void *fh, struct v4l2_exportbuffer *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = venc_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_expbuf(queue, b);
+}
+
+static int venc_return_buf_error(struct vidc_inst *inst, struct v4l2_buffer *b)
+{
+       struct vb2_queue *qcap, *qout;
+       struct list_head *ptr, *next;
+       struct venc_buffer *buf;
+
+       qcap = &inst->bufq_cap;
+       qout = &inst->bufq_out;
+
+       if (vb2_is_streaming(qcap) && vb2_is_streaming(qout))
+               return 0;
+
+       mutex_lock(&inst->bufqueue_lock);
+       list_for_each_safe(ptr, next, &inst->bufqueue) {
+               buf = list_entry(ptr, struct venc_buffer, list);
+
+               if (buf->vb.v4l2_buf.type != b->type)
+                       continue;
+
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+       }
+       mutex_unlock(&inst->bufqueue_lock);
+
+       return 0;
+}
+
+static int venc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = venc_to_vb2q(inst, b->type);
+       if (!queue)
+               return -EINVAL;
+
+       venc_return_buf_error(inst, b);
+
+       return vb2_dqbuf(queue, b, file->f_flags & O_NONBLOCK);
+}
+
+static int venc_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = venc_to_vb2q(inst, type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_streamon(queue, type);
+}
+
+static int venc_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vb2_queue *queue;
+
+       queue = venc_to_vb2q(inst, type);
+       if (!queue)
+               return -EINVAL;
+
+       return vb2_streamoff(queue, type);
+}
+
+static int venc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+       u64 us_per_frame, fps;
+
+       if (!timeperframe->denominator ||
+           a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return -EINVAL;
+
+       us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
+       do_div(us_per_frame, timeperframe->denominator);
+
+       if (!us_per_frame)
+               return -EINVAL;
+
+       fps = (u64)USEC_PER_SEC;
+       do_div(fps, us_per_frame);
+
+       dev_dbg(dev, "%s: num:%d, denom:%d\n", __func__,
+               timeperframe->numerator, timeperframe->denominator);
+
+       inst->fps = fps;
+       inst->timeperframe = *timeperframe;
+
+       return 0;
+}
+
+static int venc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return -EINVAL;
+
+       memset(a, 0, sizeof(*a));
+       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+       a->parm.capture.timeperframe = inst->timeperframe;
+
+       return 0;
+}
+
+static int venc_enum_framesizes(struct file *file, void *fh,
+                               struct v4l2_frmsizeenum *fsize)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vidc_core_capability *cap = &inst->capability;
+
+       fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+       fsize->stepwise.min_width = cap->width.min;
+       fsize->stepwise.max_width = cap->width.max;
+       fsize->stepwise.step_width = cap->width.step_size;
+       fsize->stepwise.min_height = cap->height.min;
+       fsize->stepwise.max_height = cap->height.max;
+       fsize->stepwise.step_height = cap->height.step_size;
+
+       return 0;
+}
+
+static int venc_subscribe_event(struct v4l2_fh *fh,
+                               const struct  v4l2_event_subscription *sub)
+{
+       switch (sub->type) {
+       case V4L2_EVENT_EOS:
+               return v4l2_event_subscribe(fh, sub, 2, NULL);
+       case V4L2_EVENT_SOURCE_CHANGE:
+               return v4l2_src_change_event_subscribe(fh, sub);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int venc_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
+{
+       struct vidc_inst *inst = to_inst(file, fh);
+       struct vidc_core *core = inst->core;
+       int ret = 0;
+
+       switch (enc->cmd) {
+       case V4L2_ENC_QCOM_CMD_FLUSH:
+               ret = vidc_comm_session_flush(inst, enc->flags);
+               break;
+       case V4L2_ENC_CMD_STOP:
+               if (inst->state == INST_INVALID || core->state == CORE_INVALID)
+                       return ret;
+
+               ret = release_scratch_buffers(inst, false);
+               if (ret)
+                       dprintk(VIDC_ERR, "Failed to release scratch buf:%d\n",
+                               ret);
+
+               ret = release_persist_buffers(inst);
+               if (ret)
+                       dprintk(VIDC_ERR, "Failed to release persist buf:%d\n",
+                               ret);
+
+               ret = hfi_session_deinit(inst);
+               if (ret)
+                       return ret;
+
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static const struct v4l2_ioctl_ops venc_ioctl_ops = {
+       .vidioc_querycap = venc_querycap,
+       .vidioc_enum_fmt_vid_cap_mplane = venc_enum_fmt,
+       .vidioc_enum_fmt_vid_out_mplane = venc_enum_fmt,
+       .vidioc_s_fmt_vid_cap_mplane = venc_s_fmt,
+       .vidioc_s_fmt_vid_out_mplane = venc_s_fmt,
+       .vidioc_g_fmt_vid_cap_mplane = venc_g_fmt,
+       .vidioc_g_fmt_vid_out_mplane = venc_g_fmt,
+       .vidioc_try_fmt_vid_cap_mplane = venc_try_fmt,
+       .vidioc_try_fmt_vid_out_mplane = venc_try_fmt,
+       .vidioc_reqbufs = venc_reqbufs,
+       .vidioc_querybuf = venc_querybuf,
+       .vidioc_prepare_buf = venc_prepare_buf,
+       .vidioc_qbuf = venc_qbuf,
+       .vidioc_expbuf = venc_exportbuf,
+       .vidioc_dqbuf = venc_dqbuf,
+       .vidioc_streamon = venc_streamon,
+       .vidioc_streamoff = venc_streamoff,
+       .vidioc_s_parm = venc_s_parm,
+       .vidioc_g_parm = venc_g_parm,
+       .vidioc_enum_framesizes = venc_enum_framesizes,
+       .vidioc_subscribe_event = venc_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+       .vidioc_encoder_cmd = venc_cmd,
+};
+
+static int venc_queue_setup(struct vb2_queue *q,
+                           const struct v4l2_format *fmt,
+                           unsigned int *num_buffers,
+                           unsigned int *num_planes, unsigned int sizes[],
+                           void *alloc_ctxs[])
+{
+       struct vidc_inst *inst = vb2_get_drv_priv(q);
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hal_buffer_count_actual buf_count;
+       struct hal_buffer_requirements *buff_req;
+       enum hal_property property_id;
+       int i, ret = 0;
+
+       ret = vidc_comm_get_bufreqs(inst);
+       if (ret) {
+               dev_err(dev, "buffer requirements (%d)\n", ret);
+               return ret;
+       }
+
+       switch (q->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+               *num_planes = inst->fmt_cap->num_planes;
+
+               buff_req = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
+               if (!buff_req) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               *num_buffers = max(*num_buffers, buff_req->count_actual);
+
+               *num_buffers = clamp_val(*num_buffers, MIN_NUM_CAPTURE_BUFFERS,
+                                        VIDEO_MAX_FRAME);
+
+               for (i = 0; i < *num_planes; i++) {
+                       sizes[i] = inst->fmt_cap->get_framesize(i, inst->height,
+                                                               inst->width);
+                       alloc_ctxs[i] = inst->vb2_ctx_cap;
+               }
+
+               property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+               buf_count.type = HAL_BUFFER_OUTPUT;
+               buf_count.count_actual = *num_buffers;
+
+               ret = hfi_session_set_property(inst, property_id, &buf_count);
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+               *num_planes = inst->fmt_out->num_planes;
+
+               buff_req = get_buff_req_buffer(inst, HAL_BUFFER_INPUT);
+               if (!buff_req) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               *num_buffers = max(*num_buffers, buff_req->count_actual);
+
+               property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+               buf_count.type = HAL_BUFFER_INPUT;
+               buf_count.count_actual = *num_buffers;
+
+               ret = hfi_session_set_property(inst, property_id, &buf_count);
+               if (ret)
+                       break;
+
+               sizes[0] = inst->fmt_out->get_framesize(0, inst->height,
+                                                       inst->width);
+               alloc_ctxs[0] = inst->vb2_ctx_out;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int venc_buf_init(struct vb2_buffer *vb)
+{
+       struct vb2_queue *q = vb->vb2_queue;
+       struct vidc_inst *inst = vb2_get_drv_priv(q);
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct hfi_device *hdev = inst->core->hfidev;
+       struct venc_buffer *buf = to_venc_buffer(vb);
+       struct vidc_buffer_addr_info *bai;
+       struct buffer_info *bi;
+       int ret;
+
+       bi = &buf->bi;
+       bai = &bi->bai;
+
+       memset(bai, 0, sizeof(*bai));
+
+       if (q->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return 0;
+
+       bai->buffer_size = vb2_plane_size(vb, 0);
+       bai->buffer_type = HAL_BUFFER_OUTPUT;
+       bai->num_buffers = 1;
+       bai->device_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+       ret = call_hfi_op(hdev, session_set_buffers, inst->session, bai);
+       if (ret) {
+               dev_err(dev, "%s: session: set buffer failed\n", __func__);
+               return ret;
+       }
+
+       mutex_lock(&inst->registeredbufs.lock);
+       list_add_tail(&bi->list, &inst->registeredbufs.list);
+       mutex_unlock(&inst->registeredbufs.lock);
+
+       return 0;
+}
+
+static int venc_buf_prepare(struct vb2_buffer *vb)
+{
+       struct venc_buffer *buf = to_venc_buffer(vb);
+
+       buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+       return 0;
+}
+
+static void __fill_flags(struct vidc_frame_data *frame_data, __u32 vb_flags)
+{
+       u32 *flags = &frame_data->flags;
+
+       if (vb_flags & V4L2_QCOM_BUF_FLAG_EOS)
+               *flags = HAL_BUFFERFLAG_EOS;
+
+       if (vb_flags & V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP)
+               *flags |= HAL_BUFFERFLAG_YUV_601_709_CSC_CLAMP;
+
+       if (vb_flags & V4L2_QCOM_BUF_FLAG_CODECCONFIG)
+               *flags |= HAL_BUFFERFLAG_CODECCONFIG;
+
+       if (vb_flags & V4L2_QCOM_BUF_FLAG_DECODEONLY)
+               *flags |= HAL_BUFFERFLAG_DECODEONLY;
+
+       if (vb_flags & V4L2_QCOM_BUF_TS_DISCONTINUITY)
+               *flags |= HAL_BUFFERFLAG_TS_DISCONTINUITY;
+
+       if (vb_flags & V4L2_QCOM_BUF_TS_ERROR)
+               *flags |= HAL_BUFFERFLAG_TS_ERROR;
+
+       if (vb_flags & V4L2_QCOM_BUF_TIMESTAMP_INVALID)
+               frame_data->timestamp = LLONG_MAX;
+}
+
+static int venc_set_session_buf(struct vb2_buffer *vb)
+{
+       struct vb2_queue *q = vb->vb2_queue;
+       struct vidc_inst *inst = vb2_get_drv_priv(q);
+       struct vidc_core *core = inst->core;
+       struct device *dev = &core->res.pdev->dev;
+       struct hfi_device *hdev = core->hfidev;
+       struct venc_buffer *buf = to_venc_buffer(vb);
+       struct vidc_frame_data fdata;
+       s64 time_usec;
+       int ret;
+
+       if (inst->state == INST_INVALID || core->state == CORE_INVALID) {
+               dev_err(dev, "core id:%d is in bad state\n", core->id);
+               return -EINVAL;
+       }
+
+       time_usec = timeval_to_ns(&vb->v4l2_buf.timestamp);
+       do_div(time_usec, NSEC_PER_USEC);
+
+       memset(&fdata, 0 , sizeof(fdata));
+
+       fdata.alloc_len = vb2_plane_size(vb, 0);
+       fdata.device_addr = buf->dma_addr;
+       fdata.timestamp = time_usec;
+       fdata.flags = 0;
+       fdata.clnt_data = buf->dma_addr;
+
+       if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               fdata.buffer_type = HAL_BUFFER_INPUT;
+               fdata.filled_len = vb2_get_plane_payload(vb, 0);
+               fdata.offset = vb->v4l2_planes[0].data_offset;
+
+               __fill_flags(&fdata, vb->v4l2_buf.flags);
+
+               ret = call_hfi_op(hdev, session_etb, inst->session, &fdata);
+       } else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               fdata.buffer_type = HAL_BUFFER_OUTPUT;
+               fdata.filled_len = 0;
+               fdata.offset = 0;
+
+               ret = call_hfi_op(hdev, session_ftb, inst->session, &fdata);
+       } else {
+               ret = -EINVAL;
+       }
+
+       if (ret) {
+               dev_err(dev, "failed to set session buffer\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int start_streaming(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct list_head *ptr, *next;
+       struct venc_buffer *buf;
+       int ret;
+
+       ret = venc_set_properties(inst);
+       if (ret) {
+               dev_err(dev, "set properties (%d)\n", ret);
+               return ret;
+       }
+
+       ret = vidc_comm_get_bufreqs(inst);
+       if (ret) {
+               dev_err(dev, "buffers requirements (%d)\n", ret);
+               return ret;
+       }
+
+       ret = set_scratch_buffers(inst);
+       if (ret) {
+               dev_err(dev, "set scratch buffers failed (%d)\n", ret);
+               return ret;
+       }
+
+       ret = set_persist_buffers(inst);
+       if (ret) {
+               dev_err(dev, "set persist buffers failed (%d)\n", ret);
+               return ret;
+       }
+
+       msm_comm_scale_clocks(inst->core);
+
+       ret = hfi_session_load_res(inst);
+       if (ret) {
+               dev_err(dev, "session load resources failed (%d)\n", ret);
+               return ret;
+       }
+
+       ret = hfi_session_start(inst);
+       if (ret) {
+               dev_err(dev, "session start failed (%d)\n", ret);
+               return ret;
+       }
+
+       mutex_lock(&inst->bufqueue_lock);
+       list_for_each_safe(ptr, next, &inst->bufqueue) {
+               buf = list_entry(ptr, struct venc_buffer, list);
+
+               ret = venc_set_session_buf(&buf->vb);
+               if (ret)
+                       break;
+       }
+       mutex_unlock(&inst->bufqueue_lock);
+
+       return 0;
+}
+
+static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct vidc_inst *inst = vb2_get_drv_priv(q);
+       struct vb2_queue *queue;
+
+       switch (q->type) {
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+               queue = &inst->bufq_cap;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+               queue = &inst->bufq_out;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (vb2_is_streaming(queue))
+               return start_streaming(inst);
+
+       return 0;
+}
+
+static void venc_buf_queue(struct vb2_buffer *vb)
+{
+       struct vidc_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
+       struct vidc_core *core = inst->core;
+       struct device *dev = &core->res.pdev->dev;
+       struct venc_buffer *buf = to_venc_buffer(vb);
+       int ret;
+
+       if (inst->state == INST_INVALID || core->state == CORE_INVALID) {
+               dev_err(dev, "core or instance are in invalid state\n");
+               return;
+       }
+
+       mutex_lock(&inst->bufqueue_lock);
+       list_add_tail(&buf->list, &inst->bufqueue);
+       mutex_unlock(&inst->bufqueue_lock);
+
+       if (!vb2_is_streaming(&inst->bufq_cap) ||
+           !vb2_is_streaming(&inst->bufq_out))
+               return;
+
+       ret = venc_set_session_buf(vb);
+       if (ret) {
+               vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+               dev_err(dev, "cannot set session buffer\n");
+       }
+
+       return;
+}
+
+static int venc_rel_session_bufs(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct vidc_buffer_addr_info *bai;
+       struct buffer_info *bi, *tmp;
+       int ret = 0;
+
+       mutex_lock(&inst->registeredbufs.lock);
+       list_for_each_entry_safe(bi, tmp, &inst->registeredbufs.list, list) {
+               list_del(&bi->list);
+               bai = &bi->bai;
+               bai->response_required = 1;
+               ret = hfi_session_release_buffers(inst, bai);
+               if (ret) {
+                       dev_err(dev, "%s: session release buffers failed\n",
+                               __func__);
+                       break;
+               }
+       }
+       mutex_unlock(&inst->registeredbufs.lock);
+
+       return ret;
+}
+
+static int stop_streaming(struct vidc_inst *inst)
+{
+       struct vidc_core *core = inst->core;
+       struct device *dev = &core->res.pdev->dev;
+       int ret, streamoff;
+
+       mutex_lock(&inst->lock);
+       streamoff = inst->streamoff;
+       mutex_unlock(&inst->lock);
+
+       if (streamoff)
+               return 0;
+
+       ret = hfi_session_stop(inst);
+       if (ret) {
+               dev_err(dev, "session: stop failed\n");
+               goto abort;
+       }
+
+       ret = hfi_session_release_res(inst);
+       if (ret) {
+               dev_err(dev, "session: release resources failed\n");
+               goto abort;
+       }
+
+       ret = venc_rel_session_bufs(inst);
+       if (ret) {
+               dev_err(dev, "failed to release capture buffers: %d\n", ret);
+               goto abort;
+       }
+
+       ret = release_scratch_buffers(inst, false);
+       if (ret) {
+               dev_err(dev, "failed to release scratch buffers: %d\n", ret);
+               goto abort;
+       }
+
+       ret = release_persist_buffers(inst);
+       if (ret) {
+               dev_err(dev, "failed to release persist buffers: %d\n", ret);
+               goto abort;
+       }
+
+       if (inst->state == INST_INVALID || core->state == CORE_INVALID) {
+               dev_err(dev, "core id:%d is in invalid state\n", core->id);
+               ret = -EINVAL;
+               goto abort;
+       }
+
+       ret = hfi_session_deinit(inst);
+
+       mutex_lock(&inst->lock);
+       inst->streamoff = 1;
+       mutex_unlock(&inst->lock);
+
+abort:
+       if (ret)
+               hfi_session_abort(inst);
+
+       return ret;
+}
+
+static void venc_stop_streaming(struct vb2_queue *q)
+{
+       struct vidc_inst *inst = vb2_get_drv_priv(q);
+       struct device *dev = &inst->core->res.pdev->dev;
+       int ret;
+
+       dev_dbg(dev, "%s: type: %d\n", __func__, q->type);
+
+       ret = stop_streaming(inst);
+
+       msm_comm_scale_clocks(inst->core);
+
+       if (ret)
+               dev_err(dev, "stop streaming failed type: %d, ret: %d\n",
+                       q->type, ret);
+}
+
+static const struct vb2_ops venc_vb2_ops = {
+       .queue_setup = venc_queue_setup,
+       .buf_init = venc_buf_init,
+       .buf_prepare = venc_buf_prepare,
+       .start_streaming = venc_start_streaming,
+       .stop_streaming = venc_stop_streaming,
+       .buf_queue = venc_buf_queue,
+};
+
+static struct vb2_buffer *
+venc_get_vb2buffer(struct vidc_inst *inst, dma_addr_t addr)
+{
+       struct venc_buffer *buf;
+       struct vb2_buffer *vb = NULL;
+
+       mutex_lock(&inst->bufqueue_lock);
+
+       list_for_each_entry(buf, &inst->bufqueue, list) {
+               if (buf->dma_addr == addr) {
+                       vb = &buf->vb;
+                       break;
+               }
+       }
+
+       if (vb)
+               list_del(&buf->list);
+
+       mutex_unlock(&inst->bufqueue_lock);
+
+       return vb;
+}
+
+static int venc_empty_buf_done(struct vidc_inst *inst, u32 addr,
+                              u32 bytesused, u32 data_offset, u32 flags)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct vb2_buffer *buf;
+
+       buf = venc_get_vb2buffer(inst, addr);
+       if (!buf)
+               return -EFAULT;
+
+       buf->v4l2_planes[0].bytesused = bytesused;
+       buf->v4l2_planes[0].data_offset = data_offset;
+       buf->v4l2_buf.flags = flags;
+
+       if (buf->v4l2_planes[0].data_offset > buf->v4l2_planes[0].length)
+               dev_dbg(dev, "data_offset overflow length\n");
+
+       if (buf->v4l2_planes[0].bytesused > buf->v4l2_planes[0].length)
+               dev_dbg(dev, "bytesused overflow length\n");
+
+       if (flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED)
+               dev_dbg(dev, "unsupported input stream\n");
+
+       if (flags & V4L2_QCOM_BUF_DATA_CORRUPT)
+               dev_dbg(dev, "corrupted input stream\n");
+
+       if (flags & V4L2_MSM_VIDC_BUF_START_CODE_NOT_FOUND)
+               dev_dbg(dev, "start code not found\n");
+
+       inst->count.ebd++;
+
+       vb2_buffer_done(buf, VB2_BUF_STATE_DONE);
+
+       return 0;
+}
+
+static int venc_fill_buf_done(struct vidc_inst *inst, u32 addr,
+                             u32 bytesused, u32 data_offset, u32 flags,
+                             struct timeval *timestamp)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct vb2_buffer *buf;
+
+       buf = venc_get_vb2buffer(inst, addr);
+       if (!buf)
+               return -EFAULT;
+
+       buf->v4l2_planes[0].bytesused = bytesused;
+       buf->v4l2_planes[0].data_offset = data_offset;
+       buf->v4l2_buf.flags = flags;
+       buf->v4l2_buf.timestamp = *timestamp;
+
+       if (buf->v4l2_planes[0].data_offset > buf->v4l2_planes[0].length)
+               dev_warn(dev, "overflow data_offset:%d, length:%d\n",
+                        buf->v4l2_planes[0].data_offset,
+                        buf->v4l2_planes[0].length);
+
+       if (buf->v4l2_planes[0].bytesused > buf->v4l2_planes[0].length)
+               dev_warn(dev, "overflow bytesused:%d, length:%d\n",
+                        buf->v4l2_planes[0].bytesused,
+                        buf->v4l2_planes[0].length);
+
+       inst->count.fbd++;
+
+       vb2_buffer_done(buf, VB2_BUF_STATE_DONE);
+
+       return 0;
+}
+
+static int venc_event_notify(struct vidc_inst *inst, u32 event,
+                            struct vidc_cb_event *data)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+
+       switch (event) {
+       case SESSION_ERROR:
+               /* the instance lock is already taken just change the state */
+               inst->state = INST_INVALID;
+               dev_warn(dev, "event session error\n");
+               break;
+       case SYS_EVENT_CHANGE:
+               switch (data->hal_event_type) {
+               case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
+                       dev_dbg(dev, "event sufficient resources\n");
+                       break;
+               case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
+                       dev_dbg(dev, "event not sufficient resources\n");
+                       inst->reconfig_height = data->height;
+                       inst->reconfig_width = data->width;
+                       inst->in_reconfig = true;
+                       break;
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void venc_inst_init(struct vidc_inst *inst)
+{
+       inst->fmt_cap = &venc_formats[2];
+       inst->fmt_out = &venc_formats[0];
+       inst->height = DEFAULT_HEIGHT;
+       inst->width = DEFAULT_WIDTH;
+       inst->fps = 15;
+       inst->capability.pixelprocess_capabilities = 0;
+       inst->buffer_mode[OUTPUT_PORT] = HAL_BUFFER_MODE_STATIC;
+       inst->buffer_mode[CAPTURE_PORT] = HAL_BUFFER_MODE_STATIC;
+}
+
+static void venc_release_video_device(struct video_device *pvdev)
+{
+}
+
+extern const struct v4l2_file_operations vidc_fops;
+
+int venc_init(struct vidc_core *core, struct video_device *enc)
+{
+       int ret;
+
+       /* setup the decoder device */
+       enc->release = venc_release_video_device;
+       enc->fops = &vidc_fops;
+       enc->ioctl_ops = &venc_ioctl_ops;
+       enc->vfl_dir = VFL_DIR_M2M;
+       enc->v4l2_dev = &core->v4l2_dev;
+
+       ret = video_register_device(enc, VFL_TYPE_GRABBER, 33);
+       if (ret) {
+               dprintk(VIDC_ERR, "Failed to register video encoder device");
+               return ret;
+       }
+
+       video_set_drvdata(enc, core);
+
+       return 0;
+}
+
+void venc_deinit(struct vidc_core *core, struct video_device *enc)
+{
+       video_unregister_device(enc);
+}
+
+int venc_open(struct vidc_inst *inst)
+{
+       struct device *dev = &inst->core->res.pdev->dev;
+       struct vb2_queue *q;
+       struct device *iommu_dev;
+       int ret;
+
+       /* TODO: use iommu dt bindings when they are exist */
+       iommu_dev = msm_iommu_get_ctx("venus_ns");
+       if (IS_ERR(iommu_dev)) {
+               dev_err(dev, "cannot find iommu nonsecure ctx\n");
+               return PTR_ERR(iommu_dev);
+       }
+
+       venc_inst_init(inst);
+
+       ret = venc_ctrl_init(inst);
+       if (ret)
+               return ret;
+
+       inst->vb2_ctx_cap = vb2_dma_contig_init_ctx(iommu_dev);
+       if (IS_ERR(inst->vb2_ctx_cap))
+               return PTR_ERR(inst->vb2_ctx_cap);
+
+       inst->vb2_ctx_out = vb2_dma_contig_init_ctx(iommu_dev);
+       if (IS_ERR(inst->vb2_ctx_out)) {
+               ret = PTR_ERR(inst->vb2_ctx_out);
+               goto err_cleanup_cap;
+       }
+
+       q = &inst->bufq_cap;
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       q->io_modes = VB2_MMAP;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       q->ops = &venc_vb2_ops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->drv_priv = inst;
+       q->buf_struct_size = sizeof(struct venc_buffer);
+       q->allow_zero_bytesused = 1;
+       ret = vb2_queue_init(q);
+       if (ret)
+               goto err_cleanup_out;
+
+       q = &inst->bufq_out;
+       q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       q->io_modes = VB2_MMAP | VB2_DMABUF;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       q->ops = &venc_vb2_ops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->drv_priv = inst;
+       q->buf_struct_size = sizeof(struct venc_buffer);
+       q->allow_zero_bytesused = 1;
+       ret = vb2_queue_init(q);
+       if (ret)
+               goto err_cap_queue_release;
+
+       inst->empty_buf_done = venc_empty_buf_done;
+       inst->fill_buf_done = venc_fill_buf_done;
+       inst->event_notify = venc_event_notify;
+
+       return 0;
+
+err_cap_queue_release:
+       vb2_queue_release(&inst->bufq_cap);
+err_cleanup_out:
+       vb2_dma_contig_cleanup_ctx(inst->vb2_ctx_out);
+err_cleanup_cap:
+       vb2_dma_contig_cleanup_ctx(inst->vb2_ctx_cap);
+       return ret;
+}
+
+void venc_close(struct vidc_inst *inst)
+{
+       vb2_queue_release(&inst->bufq_out);
+       vb2_queue_release(&inst->bufq_cap);
+
+       vb2_dma_contig_cleanup_ctx(inst->vb2_ctx_out);
+       vb2_dma_contig_cleanup_ctx(inst->vb2_ctx_cap);
+
+       venc_ctrl_deinit(inst);
+}
diff --git a/drivers/media/platform/msm/vidc/msm_venc.h b/drivers/media/platform/msm/vidc/msm_venc.h
new file mode 100644 (file)
index 0000000..052c21f
--- /dev/null
@@ -0,0 +1,27 @@
+/* Copyright (c) 2012-2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _MSM_VENC_H_
+#define _MSM_VENC_H_
+
+#include "msm_vidc_internal.h"
+
+int venc_init(struct vidc_core *core, struct video_device *enc);
+void venc_deinit(struct vidc_core *core, struct video_device *enc);
+int venc_open(struct vidc_inst *inst);
+void venc_close(struct vidc_inst *inst);
+
+int venc_set_bitrate_for_each_layer(struct vidc_inst *inst, u32 num_enh_layers,
+                                   u32 total_bitrate);
+int venc_toggle_hier_p(struct vidc_inst *inst, int layers);
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.h b/drivers/media/platform/msm/vidc/msm_vidc.h
new file mode 100644 (file)
index 0000000..c939253
--- /dev/null
@@ -0,0 +1,19 @@
+/* Copyright (c) 2012-2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MSM_VIDC_H_
+#define _MSM_VIDC_H_
+
+
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
new file mode 100644 (file)
index 0000000..7220a82
--- /dev/null
@@ -0,0 +1,831 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <media/videobuf2-dma-contig.h>
+#include <asm/div64.h>
+
+#include "msm_smem.h"
+#include "msm_vdec.h"
+#include "msm_vidc_common.h"
+#include "hfi/vidc_hfi_api.h"
+#include "msm_vidc_debug.h"
+#include "msm_vidc_load.h"
+
+#define TIMEOUT                msecs_to_jiffies(vidc_hw_rsp_timeout)
+
+enum multi_stream vidc_comm_get_stream_output_mode(struct vidc_inst *inst)
+{
+       return HAL_VIDEO_DECODER_PRIMARY;
+}
+
+enum hal_domain vidc_comm_get_hal_domain(int session_type)
+{
+       switch (session_type) {
+       case VIDC_ENCODER:
+               return HAL_VIDEO_DOMAIN_ENCODER;
+       case VIDC_DECODER:
+               return HAL_VIDEO_DOMAIN_DECODER;
+       default:
+               dprintk(VIDC_ERR, "Wrong domain\n");
+               return HAL_UNUSED_DOMAIN;
+       }
+}
+
+enum hal_video_codec vidc_comm_hal_codec_type(u32 pixfmt)
+{
+       dprintk(VIDC_DBG, "codec is %#x\n", pixfmt);
+
+       switch (pixfmt) {
+       case V4L2_PIX_FMT_H264:
+       case V4L2_PIX_FMT_H264_NO_SC:
+               return HAL_VIDEO_CODEC_H264;
+       case V4L2_PIX_FMT_H264_MVC:
+               return HAL_VIDEO_CODEC_MVC;
+       case V4L2_PIX_FMT_H263:
+               return HAL_VIDEO_CODEC_H263;
+       case V4L2_PIX_FMT_MPEG1:
+               return HAL_VIDEO_CODEC_MPEG1;
+       case V4L2_PIX_FMT_MPEG2:
+               return HAL_VIDEO_CODEC_MPEG2;
+       case V4L2_PIX_FMT_MPEG4:
+               return HAL_VIDEO_CODEC_MPEG4;
+       case V4L2_PIX_FMT_VC1_ANNEX_G:
+       case V4L2_PIX_FMT_VC1_ANNEX_L:
+               return HAL_VIDEO_CODEC_VC1;
+       case V4L2_PIX_FMT_VP8:
+               return HAL_VIDEO_CODEC_VP8;
+       default:
+               dprintk(VIDC_ERR, "Wrong codec: %d\n", pixfmt);
+               return HAL_UNUSED_CODEC;
+       }
+}
+
+struct vidc_core *vidc_get_core(int core_id)
+{
+       struct vidc_core *core;
+       int found = 0;
+
+       if (core_id > VIDC_CORES_MAX)
+               return ERR_PTR(-EINVAL);
+
+       mutex_lock(&vidc_driver->lock);
+       list_for_each_entry(core, &vidc_driver->cores, list) {
+               if (core->id == core_id) {
+                       found = 1;
+                       break;
+               }
+       }
+       mutex_unlock(&vidc_driver->lock);
+
+       if (found)
+               return core;
+
+       return ERR_PTR(-ENOENT);
+}
+
+void vidc_inst_set_state(struct vidc_inst *inst, u32 state)
+{
+       mutex_lock(&inst->lock);
+       if (inst->state == INST_INVALID) {
+               dprintk(VIDC_DBG,
+                       "Inst: %p is in bad state can't change state\n",
+                       inst);
+               goto exit;
+       }
+
+       dprintk(VIDC_DBG, "Moved inst: %p from state: %d to state: %d\n",
+               inst, inst->state, state);
+
+       inst->state = state;
+exit:
+       mutex_unlock(&inst->lock);
+}
+
+static unsigned int vidc_inst_get_state(struct vidc_inst *inst)
+{
+       unsigned int state;
+
+       mutex_lock(&inst->lock);
+       state = inst->state;
+       mutex_unlock(&inst->lock);
+
+       return state;
+}
+
+void vidc_queue_v4l2_event(struct vidc_inst *inst, int event_type)
+{
+       struct v4l2_event event = {.id = 0, .type = event_type};
+
+       /* TODO: this prevents NULL pointer dereference */
+       return;
+       v4l2_event_queue_fh(&inst->fh, &event);
+}
+
+enum hal_buffer vidc_comm_get_hal_output_buffer(struct vidc_inst *inst)
+{
+       if (vidc_comm_get_stream_output_mode(inst) ==
+           HAL_VIDEO_DECODER_SECONDARY)
+               return HAL_BUFFER_OUTPUT2;
+       else
+               return HAL_BUFFER_OUTPUT;
+}
+
+struct hal_buffer_requirements *
+get_buff_req_buffer(struct vidc_inst *inst, enum hal_buffer type)
+{
+       int i;
+
+       for (i = 0; i < HAL_BUFFER_MAX; i++) {
+               if (inst->buff_req.buffer[i].type == type)
+                       return &inst->buff_req.buffer[i];
+       }
+
+       return NULL;
+}
+
+/* HFI interface functions start here */
+
+int hfi_core_init(struct vidc_core *core)
+{
+       struct hfi_device *hdev = core->hfidev;
+       int ret;
+
+       mutex_lock(&core->lock);
+
+       if (core->state >= CORE_INIT) {
+               mutex_unlock(&core->lock);
+               return 0;
+       }
+
+       init_completion(&core->done);
+
+       ret = call_hfi_op(hdev, core_init, hdev->hfi_device_data);
+       if (ret) {
+               mutex_unlock(&core->lock);
+               return ret;
+       }
+
+       ret = wait_for_completion_timeout(&core->done, TIMEOUT);
+       if (!ret) {
+               mutex_unlock(&core->lock);
+               return -ETIMEDOUT;
+       }
+
+       core->state = CORE_INIT;
+
+       mutex_unlock(&core->lock);
+
+       return 0;
+}
+
+int hfi_core_deinit(struct vidc_core *core)
+{
+       mutex_lock(&core->lock);
+       if (core->state == CORE_UNINIT) {
+               mutex_unlock(&core->lock);
+               return 0;
+       }
+       mutex_unlock(&core->lock);
+
+       msm_comm_scale_clocks(core);
+
+       mutex_lock(&core->lock);
+       if (list_empty(&core->instances)) {
+               /*
+                * Delay unloading of firmware. This is useful
+                * in avoiding firmware download delays in cases where we
+                * will have a burst of back to back video playback sessions
+                * e.g. thumbnail generation.
+                */
+       }
+       mutex_unlock(&core->lock);
+
+       return 0;
+}
+
+int hfi_core_suspend(struct vidc_core *core)
+{
+       struct hfi_device *hdev = core->hfidev;
+
+       return call_hfi_op(hdev, suspend, hdev->hfi_device_data);
+}
+
+int hfi_session_init(struct vidc_inst *inst, u32 pixfmt)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       unsigned int state = vidc_inst_get_state(inst);
+       enum hal_domain domain;
+       enum hal_video_codec codec;
+       int ret;
+
+       if (state != INST_UNINIT)
+               return -EINVAL;
+
+       init_completion(&inst->done);
+
+       domain = vidc_comm_get_hal_domain(inst->session_type);
+       codec = vidc_comm_hal_codec_type(pixfmt);
+
+       inst->session = call_hfi_op(hdev, session_init, hdev->hfi_device_data,
+                                   inst, domain, codec);
+       if (IS_ERR(inst->session))
+               return PTR_ERR(inst->session);
+
+       ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+       if (!ret)
+               return -ETIMEDOUT;
+
+       vidc_inst_set_state(inst, INST_OPEN);
+
+       return 0;
+}
+
+int hfi_session_deinit(struct vidc_inst *inst)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       unsigned int state = vidc_inst_get_state(inst);
+       int ret;
+
+       if (state == INST_CLOSE)
+               return 0;
+
+       if (state < INST_OPEN)
+               return -EINVAL;
+
+       init_completion(&inst->done);
+
+       ret = call_hfi_op(hdev, session_end, inst->session);
+       if (ret)
+               return ret;
+
+       ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+       if (!ret)
+               return -ETIMEDOUT;
+
+       vidc_inst_set_state(inst, INST_CLOSE);
+
+       return 0;
+}
+
+int hfi_session_start(struct vidc_inst *inst)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       unsigned int state = vidc_inst_get_state(inst);
+       int ret;
+
+       if (state != INST_LOAD_RESOURCES)
+               return -EINVAL;
+
+       init_completion(&inst->done);
+
+       ret = call_hfi_op(hdev, session_start, inst->session);
+       if (ret)
+               return ret;
+
+       ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+       if (!ret)
+               return -ETIMEDOUT;
+
+       vidc_inst_set_state(inst, INST_START);
+
+       return 0;
+}
+
+int hfi_session_stop(struct vidc_inst *inst)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       unsigned int state = vidc_inst_get_state(inst);
+       int ret;
+
+       if (state != INST_START)
+               return -EINVAL;
+
+       init_completion(&inst->done);
+
+       ret = call_hfi_op(hdev, session_stop, inst->session);
+       if (ret)
+               return ret;
+
+       ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+       if (!ret)
+               return -ETIMEDOUT;
+
+       vidc_inst_set_state(inst, INST_STOP);
+
+       return 0;
+}
+
+int hfi_session_abort(struct vidc_inst *inst)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       int ret;
+
+       init_completion(&inst->done);
+
+       ret = call_hfi_op(hdev, session_abort, inst->session);
+       if (ret)
+               return ret;
+
+       ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+       if (!ret)
+               return -ETIMEDOUT;
+
+       vidc_inst_set_state(inst, INST_CLOSE);
+
+       return 0;
+}
+
+int hfi_session_load_res(struct vidc_inst *inst)
+{
+       struct vidc_core *core = inst->core;
+       struct hfi_device *hdev = core->hfidev;
+       unsigned int state = vidc_inst_get_state(inst);
+       int ret;
+
+       if (state != INST_OPEN)
+               return -EINVAL;
+
+       ret = msm_comm_check_overloaded(core);
+       if (ret)
+               return ret;
+
+       init_completion(&inst->done);
+
+       ret = call_hfi_op(hdev, session_load_res, inst->session);
+       if (ret)
+               return ret;
+
+       ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+       if (!ret)
+               return -ETIMEDOUT;
+
+       vidc_inst_set_state(inst, INST_LOAD_RESOURCES);
+
+       return 0;
+}
+
+int hfi_session_release_res(struct vidc_inst *inst)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       unsigned int state = vidc_inst_get_state(inst);
+       int ret;
+
+       if (state != INST_STOP)
+               return -EINVAL;
+
+       init_completion(&inst->done);
+
+       ret = call_hfi_op(hdev, session_release_res, inst->session);
+       if (ret)
+               return ret;
+
+       ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+       if (!ret)
+               return -ETIMEDOUT;
+
+       vidc_inst_set_state(inst, INST_RELEASE_RESOURCES);
+
+       return 0;
+}
+
+int hfi_session_flush(struct vidc_inst *inst)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       int ret;
+
+       init_completion(&inst->done);
+
+       ret = call_hfi_op(hdev, session_flush, inst->session, HAL_FLUSH_ALL);
+       if (ret)
+               return ret;
+
+       ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+       if (!ret)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+void hfi_session_clean(struct vidc_inst *inst)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       int ret;
+
+       mutex_lock(&inst->lock);
+       if (hdev && inst->session) {
+               ret = call_hfi_op(hdev, session_clean, inst->session);
+               if (ret)
+                       dprintk(VIDC_ERR, "session clean failed\n");
+
+               inst->session = NULL;
+       }
+       mutex_unlock(&inst->lock);
+}
+
+int hfi_session_release_buffers(struct vidc_inst *inst,
+                               struct vidc_buffer_addr_info *bai)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       int ret;
+
+       init_completion(&inst->done);
+
+       ret = call_hfi_op(hdev, session_release_buffers, inst->session, bai);
+       if (ret)
+               return ret;
+
+       if (!bai->response_required)
+               return 0;
+
+       ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+       if (!ret)
+               return -ETIMEDOUT;
+
+       if (inst->error != VIDC_ERR_NONE)
+               return -EIO;
+
+       return 0;
+}
+
+int hfi_session_get_property(struct vidc_inst *inst, enum hal_property ptype,
+                            union hal_get_property *hprop)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       unsigned int state = vidc_inst_get_state(inst);
+       struct getprop_buf *buf;
+       int ret;
+
+       if (state == INST_INVALID)
+               return -EINVAL;
+
+       mutex_lock(&inst->sync_lock);
+       if (state < INST_OPEN || state >= INST_CLOSE) {
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       switch (ptype) {
+       case HAL_PARAM_PROFILE_LEVEL_CURRENT:
+       case HAL_PARAM_GET_BUFFER_REQUIREMENTS:
+               break;
+       default:
+               return -ENOTSUPP;
+       }
+
+       init_completion(&inst->done);
+
+       ret = call_hfi_op(hdev, session_get_property, inst->session, ptype);
+       if (ret)
+               goto exit;
+
+       ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
+       if (!ret) {
+               inst->state = INST_INVALID;
+               vidc_comm_kill_session(inst);
+               ret = -ETIMEDOUT;
+               goto exit;
+       }
+
+       mutex_lock(&inst->pending_getpropq.lock);
+       if (!list_empty(&inst->pending_getpropq.list)) {
+               buf = list_first_entry(&inst->pending_getpropq.list,
+                                      struct getprop_buf, list);
+               *hprop = *((union hal_get_property *) buf->data);
+               kfree(buf->data);
+               list_del(&buf->list);
+               kfree(buf);
+               ret = 0;
+       } else {
+               /* getprop list is empty */
+               ret = -EINVAL;
+       }
+       mutex_unlock(&inst->pending_getpropq.lock);
+exit:
+       mutex_unlock(&inst->sync_lock);
+       return ret;
+}
+
+int hfi_session_set_property(struct vidc_inst *inst, enum hal_property ptype,
+                            void *pdata)
+{
+       struct hfi_device *hdev = inst->core->hfidev;
+       unsigned int state = vidc_inst_get_state(inst);
+       int ret = 0;
+
+       mutex_lock(&inst->sync_lock);
+       if (state < INST_OPEN || state >= INST_CLOSE) {
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       ret = call_hfi_op(hdev, session_set_property, inst->session, ptype,
+                         pdata);
+exit:
+       mutex_unlock(&inst->sync_lock);
+
+       return ret;
+}
+
+/* End of interface functions */
+
+int vidc_comm_get_bufreqs(struct vidc_inst *inst)
+{
+       union hal_get_property hprop;
+       int ret, i;
+
+       ret = hfi_session_get_property(inst, HAL_PARAM_GET_BUFFER_REQUIREMENTS,
+                                      &hprop);
+       if (ret)
+               return ret;
+
+       memcpy(&inst->buff_req, &hprop.buf_req, sizeof(inst->buff_req));
+
+       for (i = 0; i < HAL_BUFFER_MAX; i++)
+               dprintk(VIDC_DBG,
+                       "buftype: %03x, actual count: %02d, size: %d, "
+                       "count min: %d, hold count: %d, region size: %d\n",
+                       inst->buff_req.buffer[i].type,
+                       inst->buff_req.buffer[i].count_actual,
+                       inst->buff_req.buffer[i].size,
+                       inst->buff_req.buffer[i].count_min,
+                       inst->buff_req.buffer[i].hold_count,
+                       inst->buff_req.buffer[i].region_size);
+
+       dprintk(VIDC_DBG, "\n");
+
+       dprintk(VIDC_PROF, "Input buffers: %d, Output buffers: %d\n",
+               inst->buff_req.buffer[0].count_actual,
+               inst->buff_req.buffer[1].count_actual);
+
+       return 0;
+}
+
+int vidc_comm_bufrequirements(struct vidc_inst *inst, enum hal_buffer type,
+                             struct hal_buffer_requirements *out)
+{
+       enum hal_property ptype = HAL_PARAM_GET_BUFFER_REQUIREMENTS;
+       union hal_get_property hprop;
+       int ret, i;
+
+       ret = hfi_session_get_property(inst, ptype, &hprop);
+       if (ret)
+               return ret;
+
+       ret = -EINVAL;
+
+       for (i = 0; i < HAL_BUFFER_MAX; i++) {
+               if (hprop.buf_req.buffer[i].type != type)
+                       continue;
+
+               if (out)
+                       memcpy(out, &hprop.buf_req.buffer[i], sizeof(*out));
+               ret = 0;
+               break;
+       }
+
+       return ret;
+}
+
+int vidc_comm_session_flush(struct vidc_inst *inst, u32 flags)
+{
+       struct vidc_core *core = inst->core;
+       struct hfi_device *hdev = core->hfidev;
+       bool ip_flush = false;
+       bool op_flush = false;
+       int ret =  0;
+
+       ip_flush = flags & V4L2_QCOM_CMD_FLUSH_OUTPUT;
+       op_flush = flags & V4L2_QCOM_CMD_FLUSH_CAPTURE;
+
+       if (ip_flush && !op_flush) {
+               dprintk(VIDC_INFO, "Input only flush not supported\n");
+               return 0;
+       }
+
+       if (inst->state == INST_INVALID || core->state == CORE_INVALID) {
+               dprintk(VIDC_ERR, "Core %p and inst %p are in bad state\n",
+                       core, inst);
+               return 0;
+       }
+
+       if (inst->in_reconfig && !ip_flush && op_flush) {
+               ret = call_hfi_op(hdev, session_flush, inst->session,
+                                 HAL_FLUSH_OUTPUT);
+       } else {
+               /*
+                * If flush is called after queueing buffers but before
+                * streamon driver should flush the pending queue
+                */
+
+               /* Do not send flush in case of session_error */
+               if (!(inst->state == INST_INVALID &&
+                     core->state != CORE_INVALID))
+                       ret = call_hfi_op(hdev, session_flush, inst->session,
+                                         HAL_FLUSH_ALL);
+       }
+
+       return ret;
+}
+
+enum hal_extradata_id
+vidc_comm_get_hal_extradata_index(enum v4l2_mpeg_vidc_extradata index)
+{
+       switch (index) {
+       case V4L2_MPEG_VIDC_EXTRADATA_NONE:
+               return HAL_EXTRADATA_NONE;
+       case V4L2_MPEG_VIDC_EXTRADATA_MB_QUANTIZATION:
+               return HAL_EXTRADATA_MB_QUANTIZATION;
+       case V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO:
+               return HAL_EXTRADATA_INTERLACE_VIDEO;
+       case V4L2_MPEG_VIDC_EXTRADATA_VC1_FRAMEDISP:
+               return HAL_EXTRADATA_VC1_FRAMEDISP;
+       case V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP:
+               return HAL_EXTRADATA_VC1_SEQDISP;
+       case V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP:
+               return HAL_EXTRADATA_TIMESTAMP;
+       case V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING:
+               return HAL_EXTRADATA_S3D_FRAME_PACKING;
+       case V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE:
+               return HAL_EXTRADATA_FRAME_RATE;
+       case V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW:
+               return HAL_EXTRADATA_PANSCAN_WINDOW;
+       case V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
+               return HAL_EXTRADATA_RECOVERY_POINT_SEI;
+       case V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO:
+               return HAL_EXTRADATA_MULTISLICE_INFO;
+       case V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB:
+               return HAL_EXTRADATA_NUM_CONCEALED_MB;
+       case V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER:
+               return HAL_EXTRADATA_METADATA_FILLER;
+       case V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO:
+               return HAL_EXTRADATA_ASPECT_RATIO;
+       case V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP:
+               return HAL_EXTRADATA_INPUT_CROP;
+       case V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM:
+               return HAL_EXTRADATA_DIGITAL_ZOOM;
+       case V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP:
+               return HAL_EXTRADATA_MPEG2_SEQDISP;
+       case V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA:
+               return HAL_EXTRADATA_STREAM_USERDATA;
+       case V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP:
+               return HAL_EXTRADATA_FRAME_QP;
+       case V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO:
+               return HAL_EXTRADATA_FRAME_BITS_INFO;
+       case V4L2_MPEG_VIDC_EXTRADATA_LTR:
+               return HAL_EXTRADATA_LTR_INFO;
+       case V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI:
+               return HAL_EXTRADATA_METADATA_MBI;
+       default:
+               return V4L2_MPEG_VIDC_EXTRADATA_NONE;
+       }
+
+       return 0;
+}
+
+enum hal_buffer_layout_type
+vidc_comm_get_hal_buffer_layout(enum v4l2_mpeg_vidc_video_mvc_layout index)
+{
+       switch (index) {
+       case V4L2_MPEG_VIDC_VIDEO_MVC_SEQUENTIAL:
+               return HAL_BUFFER_LAYOUT_SEQ;
+       case V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM:
+               return HAL_BUFFER_LAYOUT_TOP_BOTTOM;
+       default:
+               break;
+       }
+
+       return HAL_UNUSED_BUFFER_LAYOUT;
+}
+
+int vidc_trigger_ssr(struct vidc_core *core, enum hal_ssr_trigger_type type)
+{
+       struct hfi_device *hdev;
+       int ret;
+
+       if (!core || !core->hfidev)
+               return -EINVAL;
+
+       hdev = core->hfidev;
+
+       if (core->state != CORE_INIT)
+               return 0;
+
+       ret = call_hfi_op(hdev, core_trigger_ssr, hdev->hfi_device_data, type);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+int vidc_check_session_supported(struct vidc_inst *inst)
+{
+       struct vidc_core *core =inst->core;
+       struct vidc_core_capability *cap = &inst->capability;
+       int ret = 0;
+
+       if (inst->state == INST_OPEN) {
+               ret = msm_comm_check_overloaded(core);
+               if (ret)
+                       return ret;
+       }
+
+       if (!cap->capability_set)
+               return 0;
+
+       ret = -ENOTSUPP;
+
+       if (inst->width < cap->width.min || inst->height < cap->height.min)
+               goto err;
+
+       if (inst->width > cap->width.max)
+               goto err;
+
+       if (inst->height * inst->width > cap->width.max * cap->height.max)
+               goto err;
+
+       return 0;
+err:
+       dprintk(VIDC_ERR, "resolution not supported\n");
+       return ret;
+}
+
+int vidc_comm_set_color_format(struct vidc_inst *inst,
+                              enum hal_buffer buffer_type, u32 pixfmt)
+{
+       struct hal_uncompressed_format_select hal_fmt;
+       struct hfi_device *hdev = inst->core->hfidev;
+       int ret;
+
+       hal_fmt.buffer_type = buffer_type;
+
+       switch (pixfmt) {
+       case V4L2_PIX_FMT_NV12:
+               dprintk(VIDC_DBG, "set color format: nv12\n");
+               hal_fmt.format = HAL_COLOR_FORMAT_NV12;
+               break;
+       case V4L2_PIX_FMT_NV21:
+               dprintk(VIDC_DBG, "set color format: nv21\n");
+               hal_fmt.format = HAL_COLOR_FORMAT_NV21;
+               break;
+       default:
+               return -ENOTSUPP;
+       }
+
+       ret = call_hfi_op(hdev, session_set_property, inst->session,
+                         HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT, &hal_fmt);
+       if (ret) {
+               dprintk(VIDC_ERR, "set uncompressed color format failed (%d)\n",
+                       ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+int vidc_comm_kill_session(struct vidc_inst *inst)
+{
+       int ret = 0;
+
+       if (!inst || !inst->core || !inst->core->hfidev) {
+               dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
+               return -EINVAL;
+       } else if (!inst->session) {
+               /* There's no hfi session to kill */
+               return 0;
+       }
+
+       /*
+        * We're internally forcibly killing the session, if fw is aware of
+        * the session send session_abort to firmware to clean up and release
+        * the session, else just kill the session inside the driver.
+        */
+       if ((inst->state >= INST_OPEN && inst->state < INST_CLOSE) ||
+            inst->state == INST_INVALID) {
+               ret = hfi_session_abort(inst);
+               if (ret == -EBUSY) {
+                       inst->event_notify(inst, SESSION_ERROR, NULL);
+                       return 0;
+               } else if (ret) {
+                       return ret;
+               }
+               vidc_inst_set_state(inst, INST_CLOSE);
+       } else {
+               inst->event_notify(inst, SESSION_ERROR, NULL);
+       }
+
+       return ret;
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
new file mode 100644 (file)
index 0000000..52bef1b
--- /dev/null
@@ -0,0 +1,51 @@
+/* Copyright (c) 2012-2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MSM_VIDC_COMMON_H_
+#define _MSM_VIDC_COMMON_H_
+
+#include <media/msm-v4l2-controls.h>
+
+#include "msm_vidc_internal.h"
+
+struct getprop_buf {
+       struct list_head list;
+       void *data;
+};
+
+struct vidc_core *vidc_get_core(int core_id);
+
+int vidc_comm_session_flush(struct vidc_inst *inst, u32 flags);
+
+int vidc_comm_get_bufreqs(struct vidc_inst *inst);
+struct hal_buffer_requirements *get_buff_req_buffer(struct vidc_inst *inst,
+                                                   u32 buffer_type);
+/* TODO: delete above buffer requirements api's and use below one */
+int vidc_comm_bufrequirements(struct vidc_inst *inst, enum hal_buffer type,
+                             struct hal_buffer_requirements *out);
+
+int hfi_core_suspend(struct vidc_core *core);
+enum hal_extradata_id
+vidc_comm_get_hal_extradata_index(enum v4l2_mpeg_vidc_extradata index);
+enum hal_buffer_layout_type
+vidc_comm_get_hal_buffer_layout(enum v4l2_mpeg_vidc_video_mvc_layout index);
+enum multi_stream vidc_comm_get_stream_output_mode(struct vidc_inst *inst);
+enum hal_buffer vidc_comm_get_hal_output_buffer(struct vidc_inst *inst);
+enum hal_video_codec vidc_comm_hal_codec_type(u32 fourcc);
+enum hal_domain vidc_comm_get_hal_domain(int session_type);
+int vidc_comm_set_color_format(struct vidc_inst *inst,
+                              enum hal_buffer buffer_type, u32 fourcc);
+void vidc_inst_set_state(struct vidc_inst *inst, u32 state);
+int vidc_comm_kill_session(struct vidc_inst *inst);
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
new file mode 100644 (file)
index 0000000..de82944
--- /dev/null
@@ -0,0 +1,372 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define CREATE_TRACE_POINTS
+
+#include "msm_vidc_debug.h"
+#include "hfi/vidc_hfi_api.h"
+
+int vidc_debug = VIDC_ERR | VIDC_WARN;
+int vidc_debug_out = VIDC_OUT_PRINTK;
+int vidc_fw_debug = 0x18;
+int vidc_fw_debug_mode = 1;
+int vidc_fw_low_power_mode = 1;
+int vidc_hw_rsp_timeout = 1000;
+int vidc_fw_coverage = 0;
+int vidc_vpe_csc_601_to_709 = 0;
+int vidc_dec_dcvs_mode = 1;
+int vidc_enc_dcvs_mode = 1;
+int vidc_sys_idle_indicator = 0;
+int vidc_firmware_unload_delay = 15000;
+int vidc_thermal_mitigation_disabled = 0;
+
+#define MAX_DBG_BUF_SIZE 4096
+
+struct debug_buffer {
+       char ptr[MAX_DBG_BUF_SIZE];
+       char *curr;
+       u32 filled_size;
+};
+
+static struct debug_buffer dbg_buf;
+
+#define INIT_DBG_BUF(__buf) ({ \
+       __buf.curr = __buf.ptr;\
+       __buf.filled_size = 0; \
+})
+
+#define DYNAMIC_BUF_OWNER(__binfo) ({ \
+       atomic_read(&__binfo->ref_count) == 2 ? "video driver" : "firmware";\
+})
+
+static int core_info_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static u32 write_str(struct debug_buffer *buffer, const char *fmt, ...)
+{
+       va_list args;
+       u32 size;
+       va_start(args, fmt);
+       size = vscnprintf(buffer->curr, MAX_DBG_BUF_SIZE - 1, fmt, args);
+       va_end(args);
+       buffer->curr += size;
+       buffer->filled_size += size;
+       return size;
+}
+
+static ssize_t core_info_read(struct file *file, char __user *buf,
+               size_t count, loff_t *ppos)
+{
+       struct vidc_core *core = file->private_data;
+       struct hfi_device *hdev;
+       int i = 0;
+       if (!core || !core->hfidev) {
+               dprintk(VIDC_ERR, "Invalid params, core: %p\n", core);
+               return 0;
+       }
+       hdev = core->hfidev;
+       INIT_DBG_BUF(dbg_buf);
+       write_str(&dbg_buf, "===============================\n");
+       write_str(&dbg_buf, "CORE %d: %p\n", core->id, core);
+       write_str(&dbg_buf, "===============================\n");
+       write_str(&dbg_buf, "state: %d\n", core->state);
+       for (i = SYS_MSG_START; i < SYS_MSG_END; i++) {
+               write_str(&dbg_buf, "completions[%d]: %s\n", i,
+                       completion_done(&core->done) ?
+                       "pending" : "done");
+       }
+       return simple_read_from_buffer(buf, count, ppos,
+                       dbg_buf.ptr, dbg_buf.filled_size);
+}
+
+static const struct file_operations core_info_fops = {
+       .open = core_info_open,
+       .read = core_info_read,
+};
+
+static int trigger_ssr_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t trigger_ssr_write(struct file *filp, const char __user *buf,
+               size_t count, loff_t *ppos) {
+       u32 ssr_trigger_val;
+       int rc;
+       struct vidc_core *core = filp->private_data;
+       rc = sscanf(buf, "%d", &ssr_trigger_val);
+       if (rc < 0) {
+               dprintk(VIDC_WARN, "returning error err %d\n", rc);
+               rc = -EINVAL;
+       } else {
+               vidc_trigger_ssr(core, ssr_trigger_val);
+               rc = count;
+       }
+       return rc;
+}
+
+static const struct file_operations ssr_fops = {
+       .open = trigger_ssr_open,
+       .write = trigger_ssr_write,
+};
+
+struct dentry *vidc_debugfs_init_drv(void)
+{
+       bool ok = false;
+       struct dentry *dir = debugfs_create_dir("msm_vidc", NULL);
+       if (IS_ERR_OR_NULL(dir)) {
+               dir = NULL;
+               goto failed_create_dir;
+       }
+
+#define __debugfs_create(__type, __name, __value) ({                          \
+       struct dentry *f = debugfs_create_##__type(__name, S_IRUGO | S_IWUSR, \
+               dir, __value);                                                \
+       if (IS_ERR_OR_NULL(f)) {                                              \
+               dprintk(VIDC_ERR, "Failed creating debugfs file '%pd/%s'\n",  \
+                       dir, __name);                                         \
+               f = NULL;                                                     \
+       }                                                                     \
+       f;                                                                    \
+})
+
+       ok =
+       __debugfs_create(x32, "debug_level", &vidc_debug) &&
+       __debugfs_create(x32, "fw_level", &vidc_fw_debug) &&
+       __debugfs_create(u32, "fw_debug_mode", &vidc_fw_debug_mode) &&
+       __debugfs_create(bool, "fw_coverage", &vidc_fw_coverage) &&
+       __debugfs_create(bool, "dcvs_dec_mode", &vidc_dec_dcvs_mode) &&
+       __debugfs_create(bool, "dcvs_enc_mode", &vidc_enc_dcvs_mode) &&
+       __debugfs_create(u32, "fw_low_power_mode", &vidc_fw_low_power_mode) &&
+       __debugfs_create(u32, "debug_output", &vidc_debug_out) &&
+       __debugfs_create(u32, "hw_rsp_timeout", &vidc_hw_rsp_timeout) &&
+       __debugfs_create(bool, "enable_vpe_csc_601_709",
+                       &vidc_vpe_csc_601_to_709) &&
+       __debugfs_create(bool, "sys_idle_indicator",
+                       &vidc_sys_idle_indicator) &&
+       __debugfs_create(u32, "firmware_unload_delay",
+                       &vidc_firmware_unload_delay) &&
+       __debugfs_create(bool, "disable_thermal_mitigation",
+                       &vidc_thermal_mitigation_disabled);
+
+#undef __debugfs_create
+
+       if (!ok)
+               goto failed_create_dir;
+
+       return dir;
+
+failed_create_dir:
+       if (dir)
+               debugfs_remove_recursive(vidc_driver->debugfs_root);
+
+       return NULL;
+}
+
+struct dentry *vidc_debugfs_init_core(struct vidc_core *core,
+                                     struct dentry *parent)
+{
+       struct dentry *dir = NULL;
+       char debugfs_name[MAX_DEBUGFS_NAME];
+
+       if (!core) {
+               dprintk(VIDC_ERR, "Invalid params, core: %p\n", core);
+               goto failed_create_dir;
+       }
+
+       snprintf(debugfs_name, MAX_DEBUGFS_NAME, "core%d", core->id);
+       dir = debugfs_create_dir(debugfs_name, parent);
+       if (!dir) {
+               dprintk(VIDC_ERR, "Failed to create debugfs for msm_vidc\n");
+               goto failed_create_dir;
+       }
+       if (!debugfs_create_file("info", S_IRUGO, dir, core, &core_info_fops)) {
+               dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+               goto failed_create_dir;
+       }
+       if (!debugfs_create_file("trigger_ssr", S_IWUSR,
+                       dir, core, &ssr_fops)) {
+               dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+               goto failed_create_dir;
+       }
+failed_create_dir:
+       return dir;
+}
+
+static int inst_info_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t inst_info_read(struct file *file, char __user *buf,
+               size_t count, loff_t *ppos)
+{
+       struct vidc_inst *inst = file->private_data;
+       int i, j;
+       if (!inst) {
+               dprintk(VIDC_ERR, "Invalid params, core: %p\n", inst);
+               return 0;
+       }
+       INIT_DBG_BUF(dbg_buf);
+       write_str(&dbg_buf, "===============================\n");
+       write_str(&dbg_buf, "INSTANCE: %p (%s)\n", inst,
+               inst->session_type == VIDC_ENCODER ? "Encoder" : "Decoder");
+       write_str(&dbg_buf, "===============================\n");
+       write_str(&dbg_buf, "core: %p\n", inst->core);
+       write_str(&dbg_buf, "height: %d\n", inst->height);
+       write_str(&dbg_buf, "width: %d\n", inst->width);
+       write_str(&dbg_buf, "fps: %d\n", inst->fps);
+       write_str(&dbg_buf, "state: %d\n", inst->state);
+       write_str(&dbg_buf, "secure: %d\n", !!(inst->flags & VIDC_SECURE));
+       write_str(&dbg_buf, "-----------Formats-------------\n");
+       for (i = 0; i < MAX_PORT_NUM; i++) {
+               const struct vidc_format *fmt;
+
+               if (i == OUTPUT_PORT)
+                       fmt = inst->fmt_out;
+               else
+                       fmt = inst->fmt_cap;
+
+               write_str(&dbg_buf, "capability: %s\n", i == OUTPUT_PORT ?
+                       "Output" : "Capture");
+               write_str(&dbg_buf, "pixformat : %x\n", fmt->pixfmt);
+               write_str(&dbg_buf, "planes : %d\n", fmt->num_planes);
+               write_str(&dbg_buf, "type: %s\n", fmt->type == OUTPUT_PORT ?
+                       "Output" : "Capture");
+               switch (inst->buffer_mode[i]) {
+               case HAL_BUFFER_MODE_STATIC:
+                       write_str(&dbg_buf, "buffer mode : %s\n", "static");
+                       break;
+               case HAL_BUFFER_MODE_RING:
+                       write_str(&dbg_buf, "buffer mode : %s\n", "ring");
+                       break;
+               case HAL_BUFFER_MODE_DYNAMIC:
+                       write_str(&dbg_buf, "buffer mode : %s\n", "dynamic");
+                       break;
+               default:
+                       write_str(&dbg_buf, "buffer mode : unsupported\n");
+               }
+
+               if (i == OUTPUT_PORT)
+                       write_str(&dbg_buf, "count: %u\n",
+                                 inst->bufq_out.num_buffers);
+               else
+                       write_str(&dbg_buf, "count: %u\n",
+                                 inst->bufq_cap.num_buffers);
+
+               for (j = 0; j < fmt->num_planes; j++)
+                       write_str(&dbg_buf, "size for plane %d: %u\n", j,
+                               i == 0 ? inst->bufq_out.plane_sizes[j] :
+                                        inst->bufq_cap.plane_sizes[j]);
+
+               if (i < MAX_PORT_NUM - 1)
+                       write_str(&dbg_buf, "\n");
+       }
+       write_str(&dbg_buf, "-------------------------------\n");
+       for (i = SESSION_MSG_START; i < SESSION_MSG_END; i++) {
+               write_str(&dbg_buf, "completions[%d]: %s\n", i,
+               completion_done(&inst->done) ?
+               "pending" : "done");
+       }
+       write_str(&dbg_buf, "ETB Count: %d\n", inst->count.etb);
+       write_str(&dbg_buf, "EBD Count: %d\n", inst->count.ebd);
+       write_str(&dbg_buf, "FTB Count: %d\n", inst->count.ftb);
+       write_str(&dbg_buf, "FBD Count: %d\n", inst->count.fbd);
+
+       return simple_read_from_buffer(buf, count, ppos,
+               dbg_buf.ptr, dbg_buf.filled_size);
+}
+
+static const struct file_operations inst_info_fops = {
+       .open = inst_info_open,
+       .read = inst_info_read,
+};
+
+struct dentry *vidc_debugfs_init_inst(struct vidc_inst *inst,
+                                     struct dentry *parent)
+{
+       struct dentry *dir = NULL;
+       char debugfs_name[MAX_DEBUGFS_NAME];
+       if (!inst) {
+               dprintk(VIDC_ERR, "Invalid params, inst: %p\n", inst);
+               goto failed_create_dir;
+       }
+       snprintf(debugfs_name, MAX_DEBUGFS_NAME, "inst_%p", inst);
+       dir = debugfs_create_dir(debugfs_name, parent);
+       if (!dir) {
+               dprintk(VIDC_ERR, "Failed to create debugfs for msm_vidc\n");
+               goto failed_create_dir;
+       }
+       if (!debugfs_create_file("info", S_IRUGO, dir, inst, &inst_info_fops)) {
+               dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+               goto failed_create_dir;
+       }
+       inst->debug.pdata[FRAME_PROCESSING].sampling = true;
+failed_create_dir:
+       return dir;
+}
+
+void vidc_debugfs_update(struct vidc_inst *inst,
+                        enum msm_vidc_debugfs_event e)
+{
+       struct vidc_debug *d = &inst->debug;
+       char a[64] = "Frame processing";
+       switch (e) {
+       case MSM_VIDC_DEBUGFS_EVENT_ETB:
+               mutex_lock(&inst->lock);
+               inst->count.etb++;
+               mutex_unlock(&inst->lock);
+               if (inst->count.ebd && inst->count.ftb > inst->count.fbd) {
+                       d->pdata[FRAME_PROCESSING].name[0] = '\0';
+                       tic(inst, FRAME_PROCESSING, a);
+               }
+       break;
+       case MSM_VIDC_DEBUGFS_EVENT_EBD:
+               mutex_lock(&inst->lock);
+               inst->count.ebd++;
+               mutex_unlock(&inst->lock);
+               if (inst->count.ebd && inst->count.ebd == inst->count.etb) {
+                       toc(inst, FRAME_PROCESSING);
+                       dprintk(VIDC_PROF, "EBD: FW needs input buffers\n");
+               }
+               if (inst->count.ftb == inst->count.fbd)
+                       dprintk(VIDC_PROF, "EBD: FW needs output buffers\n");
+       break;
+       case MSM_VIDC_DEBUGFS_EVENT_FTB: {
+               inst->count.ftb++;
+               if (inst->count.ebd && inst->count.etb > inst->count.ebd) {
+                       d->pdata[FRAME_PROCESSING].name[0] = '\0';
+                       tic(inst, FRAME_PROCESSING, a);
+               }
+       }
+       break;
+       case MSM_VIDC_DEBUGFS_EVENT_FBD:
+               inst->debug.samples++;
+               if (inst->count.ebd && inst->count.fbd == inst->count.ftb) {
+                       toc(inst, FRAME_PROCESSING);
+                       dprintk(VIDC_PROF, "FBD: FW needs output buffers\n");
+               }
+               if (inst->count.etb == inst->count.ebd)
+                       dprintk(VIDC_PROF, "FBD: FW needs input buffers\n");
+               break;
+       default:
+               dprintk(VIDC_ERR, "Invalid state in debugfs: %d\n", e);
+               break;
+       }
+}
+
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
new file mode 100644 (file)
index 0000000..e07bb20
--- /dev/null
@@ -0,0 +1,170 @@
+/* Copyright (c) 2012-2014, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MSM_VIDC_DEBUG__
+#define __MSM_VIDC_DEBUG__
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+
+#include "msm_vidc_internal.h"
+
+#ifndef VIDC_DBG_LABEL
+#define VIDC_DBG_LABEL "msm_vidc"
+#endif
+
+#define VIDC_DBG_TAG VIDC_DBG_LABEL ": %4s: "
+
+/* To enable messages OR these values and
+ * echo the result to debugfs file.
+ *
+ * To enable all messages set debug_level = 0x101F
+ */
+
+enum vidc_msg_prio {
+       VIDC_ERR  = 0x0001,
+       VIDC_WARN = 0x0002,
+       VIDC_INFO = 0x0004,
+       VIDC_DBG  = 0x0008,
+       VIDC_PROF = 0x0010,
+       VIDC_PKT  = 0x0020,
+       VIDC_FW   = 0x1000,
+};
+
+enum vidc_msg_out {
+       VIDC_OUT_PRINTK = 0,
+       VIDC_OUT_FTRACE,
+};
+
+enum msm_vidc_debugfs_event {
+       MSM_VIDC_DEBUGFS_EVENT_ETB,
+       MSM_VIDC_DEBUGFS_EVENT_EBD,
+       MSM_VIDC_DEBUGFS_EVENT_FTB,
+       MSM_VIDC_DEBUGFS_EVENT_FBD,
+};
+
+extern int vidc_debug;
+extern int vidc_debug_out;
+extern int vidc_fw_debug;
+extern int vidc_fw_debug_mode;
+extern int vidc_fw_low_power_mode;
+extern int vidc_hw_rsp_timeout;
+extern int vidc_fw_coverage;
+extern int vidc_vpe_csc_601_to_709;
+extern int vidc_dec_dcvs_mode;
+extern int vidc_enc_dcvs_mode;
+extern int vidc_sys_idle_indicator;
+extern int vidc_firmware_unload_delay;
+extern int vidc_thermal_mitigation_disabled;
+
+#define VIDC_MSG_PRIO2STRING(__level) ({ \
+       char *__str; \
+       \
+       switch (__level) { \
+       case VIDC_ERR: \
+               __str = "err"; \
+               break; \
+       case VIDC_WARN: \
+               __str = "warn"; \
+               break; \
+       case VIDC_INFO: \
+               __str = "info"; \
+               break; \
+       case VIDC_DBG: \
+               __str = "dbg"; \
+               break; \
+       case VIDC_PROF: \
+               __str = "prof"; \
+               break; \
+       case VIDC_PKT: \
+               __str = "pkt"; \
+               break; \
+       case VIDC_FW: \
+               __str = "fw"; \
+               break; \
+       default: \
+               __str = "????"; \
+               break; \
+       } \
+       \
+       __str; \
+       })
+
+#define dprintk(__level, __fmt, arg...)        \
+       do { \
+               if (vidc_debug & __level) { \
+                       if (vidc_debug_out == VIDC_OUT_PRINTK) { \
+                               pr_info(VIDC_DBG_TAG __fmt, \
+                                               VIDC_MSG_PRIO2STRING(__level), \
+                                               ## arg); \
+                       } else if (vidc_debug_out == VIDC_OUT_FTRACE) { \
+                               trace_printk(KERN_DEBUG VIDC_DBG_TAG __fmt, \
+                                               VIDC_MSG_PRIO2STRING(__level), \
+                                               ## arg); \
+                       } \
+               } \
+       } while (0)
+
+struct dentry *vidc_debugfs_init_drv(void);
+struct dentry *vidc_debugfs_init_core(struct vidc_core *core,
+                                     struct dentry *parent);
+struct dentry *vidc_debugfs_init_inst(struct vidc_inst *inst,
+                                     struct dentry *parent);
+void vidc_debugfs_update(struct vidc_inst *inst, enum msm_vidc_debugfs_event e);
+
+static inline void tic(struct vidc_inst *i, enum profiling_points p, char *b)
+{
+       struct timeval __ddl_tv;
+       if (!i->debug.pdata[p].name[0])
+               memcpy(i->debug.pdata[p].name, b, 64);
+       if ((vidc_debug & VIDC_PROF) && i->debug.pdata[p].sampling) {
+               do_gettimeofday(&__ddl_tv);
+               i->debug.pdata[p].start =
+                       (__ddl_tv.tv_sec * 1000) + (__ddl_tv.tv_usec / 1000);
+                       i->debug.pdata[p].sampling = false;
+       }
+}
+
+static inline void toc(struct vidc_inst *i, enum profiling_points p)
+{
+       struct timeval __ddl_tv;
+       if ((vidc_debug & VIDC_PROF) && !i->debug.pdata[p].sampling) {
+               do_gettimeofday(&__ddl_tv);
+               i->debug.pdata[p].stop = (__ddl_tv.tv_sec * 1000)
+                       + (__ddl_tv.tv_usec / 1000);
+               i->debug.pdata[p].cumulative += i->debug.pdata[p].stop -
+                       i->debug.pdata[p].start;
+               i->debug.pdata[p].sampling = true;
+       }
+}
+
+static inline void show_stats(struct vidc_inst *i)
+{
+       int x;
+       for (x = 0; x < MAX_PROFILING_POINTS; x++) {
+               if (i->debug.pdata[x].name[0] && (vidc_debug & VIDC_PROF)) {
+                       if (i->debug.samples) {
+                               dprintk(VIDC_PROF, "%s averaged %d ms/sample\n",
+                                       i->debug.pdata[x].name,
+                                       i->debug.pdata[x].cumulative /
+                                       i->debug.samples);
+                       }
+
+                       dprintk(VIDC_PROF, "%s Samples: %d\n",
+                               i->debug.pdata[x].name,
+                               i->debug.samples);
+               }
+       }
+}
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
new file mode 100644 (file)
index 0000000..24241d0
--- /dev/null
@@ -0,0 +1,308 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MSM_VIDC_INTERNAL_H_
+#define _MSM_VIDC_INTERNAL_H_
+
+#include <linux/atomic.h>
+#include <linux/list.h>
+#include <linux/time.h>
+#include <linux/types.h>
+#include <linux/completion.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ctrls.h>
+#include <media/videobuf2-core.h>
+
+#include "msm_media_info.h"
+#include "hfi/vidc_hfi_api.h"
+
+#define VIDC_DRV_NAME          "vidc"
+#define VIDC_VERSION           KERNEL_VERSION(1, 0, 0);
+#define MAX_DEBUGFS_NAME       50
+#define DEFAULT_TIMEOUT                3
+#define DEFAULT_HEIGHT         1088
+#define DEFAULT_WIDTH          1920
+#define MIN_SUPPORTED_WIDTH    32
+#define MIN_SUPPORTED_HEIGHT   32
+
+/* Maintains the number of FTB's between each FBD over a window */
+#define DCVS_FTB_WINDOW 32
+
+#define V4L2_EVENT_VIDC_BASE  10
+
+#define SYS_MSG_START                  SYS_EVENT_CHANGE
+#define SYS_MSG_END                    SYS_DEBUG
+#define SESSION_MSG_START              SESSION_LOAD_RESOURCE_DONE
+#define SESSION_MSG_END                        SESSION_PROPERTY_INFO
+#define SYS_MSG_INDEX(__msg)           (__msg - SYS_MSG_START)
+#define SESSION_MSG_INDEX(__msg)       (__msg - SESSION_MSG_START)
+
+#define MAX_NAME_LENGTH                        64
+
+#define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
+
+enum vidc_ports {
+       OUTPUT_PORT,
+       CAPTURE_PORT,
+       MAX_PORT_NUM
+};
+
+/* define core states */
+#define CORE_UNINIT    0
+#define CORE_INIT      1
+#define CORE_INVALID   2
+
+/* define instance states */
+#define INST_INVALID                   1
+#define INST_UNINIT                    2
+#define INST_OPEN                      3
+#define INST_LOAD_RESOURCES            4
+#define INST_START                     5
+#define INST_STOP                      6
+#define INST_RELEASE_RESOURCES         7
+#define INST_CLOSE                     8
+
+struct vidc_list {
+       struct list_head list;
+       struct mutex lock;
+};
+
+static inline void INIT_VIDC_LIST(struct vidc_list *mlist)
+{
+       mutex_init(&mlist->lock);
+       INIT_LIST_HEAD(&mlist->list);
+}
+
+struct vidc_internal_buf {
+       struct list_head list;
+       enum hal_buffer type;
+       struct smem *smem;
+};
+
+struct vidc_format {
+       u32 pixfmt;
+       int num_planes;
+       u32 type;
+       u32 (*get_framesize)(int plane, u32 height, u32 width);
+};
+
+struct vidc_drv {
+       struct mutex lock;
+       struct list_head cores;
+       int num_cores;
+       struct dentry *debugfs_root;
+       int thermal_level;
+};
+
+enum profiling_points {
+       SYS_INIT = 0,
+       SESSION_INIT,
+       LOAD_RESOURCES,
+       FRAME_PROCESSING,
+       FW_IDLE,
+       MAX_PROFILING_POINTS,
+};
+
+struct buf_count {
+       int etb;
+       int ftb;
+       int fbd;
+       int ebd;
+};
+
+struct dcvs_stats {
+       int num_ftb[DCVS_FTB_WINDOW];
+       bool transition_turbo;
+       int ftb_index;
+       int ftb_counter;
+       bool prev_freq_lowered;
+       bool prev_freq_increased;
+       int threshold_disp_buf_high;
+       int threshold_disp_buf_low;
+       int load;
+       int load_low;
+       int load_high;
+       int min_threshold;
+       int max_threshold;
+       bool is_clock_scaled;
+       int etb_counter;
+       bool is_power_save_mode;
+       bool is_output_buff_added;
+       bool is_input_buff_added;
+       bool is_additional_buff_added;
+};
+
+struct profile_data {
+       int start;
+       int stop;
+       int cumulative;
+       char name[64];
+       int sampling;
+       int average;
+};
+
+struct vidc_debug {
+       struct profile_data pdata[MAX_PROFILING_POINTS];
+       int profile;
+       int samples;
+};
+
+enum vidc_modes {
+       VIDC_SECURE     = 1 << 0,
+       VIDC_TURBO      = 1 << 1,
+       VIDC_THUMBNAIL  = 1 << 2,
+       VIDC_NOMINAL    = 1 << 3,
+};
+
+enum core_id {
+       VIDC_CORE_VENUS = 0,
+       VIDC_CORE_Q6,
+       VIDC_CORES_MAX,
+};
+
+enum session_type {
+       VIDC_ENCODER = 0,
+       VIDC_DECODER,
+       VIDC_MAX_DEVICES,
+};
+
+struct vidc_core_capability {
+       struct hal_capability_supported width;
+       struct hal_capability_supported height;
+       struct hal_capability_supported frame_rate;
+       u32 pixelprocess_capabilities;
+       struct hal_capability_supported scale_x;
+       struct hal_capability_supported scale_y;
+       struct hal_capability_supported hier_p;
+       struct hal_capability_supported ltr_count;
+       struct hal_capability_supported mbs_per_frame;
+       struct hal_capability_supported secure_output2_threshold;
+       u32 capability_set;
+       enum hal_buffer_mode_type buffer_mode[MAX_PORT_NUM];
+};
+
+struct vidc_core {
+       struct list_head list;
+       struct mutex lock;
+       int id;
+       void *hfidev;
+       struct video_device vdev_dec;
+       struct video_device vdev_enc;
+       struct v4l2_device v4l2_dev;
+       struct list_head instances;
+       struct dentry *debugfs_root;
+       unsigned int state;
+       struct completion done;
+       unsigned int error;
+       enum vidc_hfi_type hfi_type;
+       struct vidc_resources res;
+       u32 enc_codecs;
+       u32 dec_codecs;
+       struct rproc *rproc;
+       bool rproc_booted;
+
+       int (*event_notify)(struct vidc_core *core, u32 device_id, u32 event);
+};
+
+struct vidc_inst {
+       struct list_head list;
+       struct mutex sync_lock, lock;
+       struct vidc_core *core;
+
+       struct vidc_list scratchbufs;
+       struct vidc_list persistbufs;
+       struct vidc_list pending_getpropq;
+       struct vidc_list registeredbufs;
+
+       struct list_head bufqueue;
+       struct mutex bufqueue_lock;
+
+       int streamoff;
+       struct buffer_requirements buff_req;
+       void *mem_client;
+       struct vb2_queue bufq_out;
+       struct vb2_queue bufq_cap;
+       void *vb2_ctx_cap;
+       void *vb2_ctx_out;
+
+       struct v4l2_ctrl_handler ctrl_handler;
+       struct v4l2_ctrl **ctrls;
+       struct v4l2_ctrl **cluster;
+       struct v4l2_fh fh;
+
+       int (*empty_buf_done)(struct vidc_inst *inst, u32 addr,
+                             u32 bytesused, u32 data_offset, u32 flags);
+       int (*fill_buf_done)(struct vidc_inst *inst, u32 addr,
+                            u32 bytesused, u32 data_offset, u32 flags,
+                            struct timeval *timestamp);
+       int (*event_notify)(struct vidc_inst *inst, u32 event,
+                           struct vidc_cb_event *data);
+
+       /* session fields */
+       enum session_type session_type;
+       unsigned int state;
+       void *session;
+       u32 width;
+       u32 height;
+       u64 fps;
+       struct v4l2_fract timeperframe;
+       const struct vidc_format *fmt_out;
+       const struct vidc_format *fmt_cap;
+       struct completion done;
+       unsigned int error;
+       struct vidc_core_capability capability;
+       enum hal_buffer_mode_type buffer_mode[MAX_PORT_NUM];
+       enum vidc_modes flags;
+       struct buf_count count;
+       bool in_reconfig;
+       u32 reconfig_width;
+       u32 reconfig_height;
+
+       /* encoder fields */
+       atomic_t seq_hdr_reqs;
+
+       struct dentry *debugfs_root;
+       struct vidc_debug debug;
+};
+
+extern struct vidc_drv *vidc_driver;
+
+struct vidc_ctrl {
+       u32 id;
+       char name[MAX_NAME_LENGTH];
+       enum v4l2_ctrl_type type;
+       s32 minimum;
+       s32 maximum;
+       s32 default_value;
+       u32 step;
+       u32 menu_skip_mask;
+       u32 flags;
+       const char * const *qmenu;
+};
+
+struct buffer_info {
+       struct list_head list;
+       struct vidc_buffer_addr_info bai;
+};
+
+int vidc_trigger_ssr(struct vidc_core *core, enum hal_ssr_trigger_type type);
+int vidc_check_session_supported(struct vidc_inst *inst);
+void vidc_queue_v4l2_event(struct vidc_inst *inst, int event_type);
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_load.c b/drivers/media/platform/msm/vidc/msm_vidc_load.c
new file mode 100644 (file)
index 0000000..c59f8bf
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+
+#include "msm_vidc_internal.h"
+#include "msm_vidc_common.h"
+#include "msm_vidc_debug.h"
+
+enum load_quirks {
+       LOAD_NO_QUIRKS                  = 0 << 0,
+       LOAD_IGNORE_TURBO_LOAD          = 1 << 0,
+       LOAD_IGNORE_THUMBNAIL_LOAD      = 1 << 1,
+};
+
+static inline bool is_turbo_session(struct vidc_inst *inst)
+{
+       return !!(inst->flags & VIDC_TURBO);
+}
+
+static inline bool is_thumbnail_session(struct vidc_inst *inst)
+{
+       return !!(inst->flags & VIDC_THUMBNAIL);
+}
+
+static inline bool is_nominal_session(struct vidc_inst *inst)
+{
+       return !!(inst->flags & VIDC_NOMINAL);
+}
+
+static u32 get_mbs_per_sec(struct vidc_inst *inst)
+{
+       int mbs;
+       u32 w = inst->width;
+       u32 h = inst->height;
+
+       mbs = (ALIGN(w, 16) / 16) * (ALIGN(h, 16) / 16);
+
+       return mbs * inst->fps;
+}
+
+static u32 get_inst_load(struct vidc_inst *inst, enum load_quirks quirks)
+{
+       u32 load;
+
+       if (!(inst->state >= INST_OPEN && inst->state < INST_STOP))
+               return 0;
+
+       load = get_mbs_per_sec(inst);
+
+       if (is_thumbnail_session(inst) && quirks & LOAD_IGNORE_THUMBNAIL_LOAD)
+               load = 0;
+
+       if (is_turbo_session(inst) && !(quirks & LOAD_IGNORE_TURBO_LOAD))
+               load = inst->core->res.max_load;
+
+       return load;
+}
+
+static u32 get_load(struct vidc_core *core, enum session_type type,
+                   enum load_quirks quirks)
+{
+       struct vidc_inst *inst = NULL;
+       u32 mbs_per_sec = 0;
+
+       mutex_lock(&core->lock);
+       list_for_each_entry(inst, &core->instances, list) {
+               if (inst->session_type != type)
+                       continue;
+
+               mbs_per_sec += get_inst_load(inst, quirks);
+       }
+       mutex_unlock(&core->lock);
+
+       return mbs_per_sec;
+}
+
+static int scale_clocks_load(struct vidc_core *core, u32 mbs_per_sec)
+{
+       struct clock_info *ci = &core->res.clock_set.clock_tbl[0];
+       const struct load_freq_table *table = ci->load_freq_tbl;
+       unsigned long freq = table[0].freq;
+       int num_rows = ci->count;
+       int ret, i;
+
+       if (!mbs_per_sec && num_rows > 1) {
+               freq = table[num_rows - 1].freq;
+               goto set_freq;
+       }
+
+       for (i = 0; i < num_rows; i++) {
+               if (mbs_per_sec > table[i].load)
+                       break;
+               freq = table[i].freq;
+       }
+
+set_freq:
+
+       ret = clk_set_rate(ci->clk, freq);
+       if (ret) {
+               dprintk(VIDC_ERR, "Failed to set clock rate %lu (%d)\n",
+                       freq, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static u32 scale_clocks(struct vidc_core *core)
+{
+       u32 mbs_per_sec = get_load(core, VIDC_ENCODER, LOAD_NO_QUIRKS) +
+                         get_load(core, VIDC_DECODER, LOAD_NO_QUIRKS);
+
+       return scale_clocks_load(core, mbs_per_sec);
+}
+
+void msm_comm_scale_clocks(struct vidc_core *core)
+{
+       if (scale_clocks(core)) {
+               dprintk(VIDC_WARN, "Failed to scale clocks. "
+                       "Performance might be impacted\n");
+       }
+}
+
+int msm_comm_check_overloaded(struct vidc_core *core)
+{
+       enum load_quirks quirks;
+       u32 mbs_per_sec;
+
+       quirks = LOAD_IGNORE_TURBO_LOAD | LOAD_IGNORE_THUMBNAIL_LOAD;
+
+       mbs_per_sec = get_load(core, VIDC_DECODER, quirks) +
+                     get_load(core, VIDC_ENCODER, quirks);
+
+       if (mbs_per_sec > core->res.max_load) {
+               dprintk(VIDC_ERR, "%s: HW is overloaded, needed: %d max: %d\n",
+                       __func__, mbs_per_sec, core->res.max_load);
+               return -EBUSY;
+       }
+
+       return 0;
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_load.h b/drivers/media/platform/msm/vidc/msm_vidc_load.h
new file mode 100644 (file)
index 0000000..9822f3c
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MSM_VIDC_LOAD_H__
+#define __MSM_VIDC_LOAD_H__
+
+struct vidc_core;
+
+void msm_comm_scale_clocks(struct vidc_core *core);
+int msm_comm_check_overloaded(struct vidc_core *core);
+
+#endif /* __MSM_VIDC_LOAD_H__ */
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.c b/drivers/media/platform/msm/vidc/msm_vidc_resources.c
new file mode 100644 (file)
index 0000000..50d14dc
--- /dev/null
@@ -0,0 +1,288 @@
+/* Copyright (c) 2012-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/dma-iommu.h>
+#include <linux/iommu.h>
+#include <linux/qcom_iommu.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include "msm_vidc_internal.h"
+#include "msm_vidc_resources.h"
+
+static const struct load_freq_table freq_table_8916[] = {
+       { 352800, 228570000 },  /* 1920x1088 @ 30 + 1280x720 @ 30 */
+       { 244800, 160000000 },  /* 1920x1088 @ 30 */
+       { 108000, 100000000 },  /* 1280x720 @ 30 */
+};
+
+static const struct reg_value_pair reg_preset_8916[] = {
+       { 0xe0020, 0x05555556 },
+       { 0xe0024, 0x05555556 },
+       { 0x80124, 0x00000003 },
+};
+
+static struct clock_info clks_8916[] = {
+       { .name = "core_clk",
+         .count = ARRAY_SIZE(freq_table_8916),
+         .load_freq_tbl = freq_table_8916,
+       },
+       { .name = "iface_clk", },
+       { .name = "bus_clk", },
+};
+
+static int get_clock_table(struct vidc_resources *res)
+{
+       struct device *dev = &res->pdev->dev;
+       struct clock_set *clocks = &res->clock_set;
+       unsigned int i;
+
+       clocks->clock_tbl = clks_8916;
+       clocks->count = ARRAY_SIZE(clks_8916);
+
+       for (i = 0; i < clocks->count; i++) {
+               clks_8916[i].clk = devm_clk_get(dev, clks_8916[i].name);
+               if (IS_ERR(clks_8916[i].clk))
+                       return PTR_ERR(clks_8916[i].clk);
+       }
+
+       return 0;
+}
+
+int enable_clocks(struct vidc_resources *res)
+{
+       struct clock_set *clks = &res->clock_set;
+       struct clock_info *tbl = clks->clock_tbl;
+       int ret, i;
+
+       for (i = 0; i < clks->count; i++) {
+               ret = clk_prepare_enable(tbl[i].clk);
+               if (ret)
+                       goto err;
+       }
+
+       return 0;
+err:
+       while (--i)
+               clk_disable_unprepare(tbl[i].clk);
+
+       return ret;
+}
+
+void disable_clocks(struct vidc_resources *res)
+{
+       struct clock_set *clks = &res->clock_set;
+       struct clock_info *tbl = clks->clock_tbl;
+       int i;
+
+       for (i = clks->count - 1; i >= 0; i--)
+               clk_disable_unprepare(tbl[i].clk);
+}
+
+static void iommu_ctx_banks_detach(struct vidc_resources *res)
+{
+       struct context_bank_info *cb;
+
+       list_for_each_entry(cb, &res->context_banks, list) {
+               if (cb->dev)
+                       arm_iommu_detach_device(cb->dev);
+               if (cb->mapping)
+                       arm_iommu_release_mapping(cb->mapping);
+       }
+}
+
+static int iommu_ctx_bank_attach(struct context_bank_info *cb)
+{
+       struct bus_type *bus = &platform_bus_type;
+       struct addr_range *range = &cb->addr_range;
+       int ret;
+
+       if (cb->is_secure)
+               bus = &msm_iommu_sec_bus_type;
+
+       cb->mapping = arm_iommu_create_mapping(bus, range->start,
+                                              range->size, 0);
+       if (IS_ERR_OR_NULL(cb->mapping))
+               return PTR_ERR(cb->mapping) ?: -ENODEV;
+
+       ret = arm_iommu_attach_device(cb->dev, cb->mapping);
+       if (ret)
+               goto release_mapping;
+
+       return 0;
+
+release_mapping:
+       arm_iommu_release_mapping(cb->mapping);
+       return ret;
+}
+
+struct iommu_context {
+       const char *name;
+       u32 partition_buf_type;
+       u32 virt_addr_pool_start;
+       u32 virt_addr_pool_size;
+       bool is_secure;
+};
+
+static const struct iommu_context iommu_ctxs[] = {
+       { .name                 = "venus_ns",
+         .partition_buf_type   = 0xfff,
+         /* non-secure addr pool from 1500 MB to 3548 MB */
+         .virt_addr_pool_start = 0x5dc00000,
+         .virt_addr_pool_size  = 0x8f000000,
+         .is_secure            = false,
+       },
+       { .name                 = "venus_sec_bitstream",
+         .partition_buf_type   = 0x241,
+         /* secure bitstream addr pool from 1200 MB to 1500 MB */
+         .virt_addr_pool_start = 0x4b000000,
+         .virt_addr_pool_size  = 0x12c00000,
+         .is_secure            = true,
+       },
+       { .name                 = "venus_sec_pixel",
+         .partition_buf_type   = 0x106,
+         /* secure pixel addr pool from 616 MB to 1200 MB */
+         .virt_addr_pool_start = 0x25800000,
+         .virt_addr_pool_size  = 0x25800000,
+         .is_secure            = true,
+       },
+       { .name                 = "venus_sec_non_pixel",
+         .partition_buf_type   = 0x480,
+         /* secure non-pixel addr pool from 16 MB to 616 MB */
+         .virt_addr_pool_start = 0x01000000,
+         .virt_addr_pool_size  = 0x24800000,
+         .is_secure            = true,
+       }
+};
+
+static int iommu_ctx_bank(struct vidc_resources *res, struct device_node *np,
+                         const struct iommu_context *iommu_ctx)
+{
+       struct device *dev = &res->pdev->dev;
+       struct context_bank_info *cb;
+       int ret;
+
+       cb = devm_kzalloc(dev, sizeof(*cb), GFP_KERNEL);
+       if (!cb)
+               return -ENOMEM;
+
+       cb->name = np->name;
+       cb->buffer_type = iommu_ctx->partition_buf_type;
+       cb->addr_range.start = iommu_ctx->virt_addr_pool_start;
+       cb->addr_range.size = iommu_ctx->virt_addr_pool_size;
+       cb->is_secure = iommu_ctx->is_secure;
+
+       cb->dev = msm_iommu_get_ctx(cb->name);
+       if (IS_ERR_OR_NULL(cb->dev)) {
+               dev_err(dev, "dt: failed to get context bank device for %s\n",
+                       cb->name);
+               return PTR_ERR(cb->dev) ?: -ENODEV;
+       }
+
+       ret = iommu_ctx_bank_attach(cb);
+       if (ret)
+               return ret;
+
+       INIT_LIST_HEAD(&cb->list);
+       list_add_tail(&cb->list, &res->context_banks);
+
+       return 0;
+}
+
+static int iommu_ctx_banks(struct vidc_resources *res)
+{
+       struct device_node *np = res->pdev->dev.of_node, *cb;
+       int ret = 0, i;
+
+       INIT_LIST_HEAD(&res->context_banks);
+
+       for (i = 0; i < ARRAY_SIZE(iommu_ctxs); i++) {
+               cb = of_parse_phandle(np, "qcom,iommu-cb", i);
+               if (!cb)
+                       continue;
+
+               ret = iommu_ctx_bank(res, cb, &iommu_ctxs[i]);
+               if (ret)
+                       break;
+       }
+
+       if (ret) {
+               iommu_ctx_banks_detach(res);
+               return ret;
+       }
+
+       return 0;
+}
+
+int get_platform_resources(struct vidc_core *core)
+{
+       struct vidc_resources *res = &core->res;
+       struct platform_device *pdev = res->pdev;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = pdev->dev.of_node;
+       const char *hfi_name = NULL, *propname;
+       int ret;
+
+       res->load_freq_tbl = freq_table_8916;
+       res->load_freq_tbl_size = ARRAY_SIZE(freq_table_8916);
+
+       res->reg_set.reg_tbl = reg_preset_8916;
+       res->reg_set.count = ARRAY_SIZE(reg_preset_8916);
+
+       ret = of_property_read_string(np, "qcom,hfi", &hfi_name);
+       if (ret) {
+               dev_err(dev, "reading hfi type failed\n");
+               return ret;
+       }
+
+       if (!strcasecmp(hfi_name, "venus"))
+               core->hfi_type = VIDC_HFI_VENUS;
+       else if (!strcasecmp(hfi_name, "q6"))
+               core->hfi_type = VIDC_HFI_Q6;
+       else
+               return -EINVAL;
+
+       ret = iommu_ctx_banks(&core->res);
+       if (ret)
+               return ret;
+
+       propname = "qcom,enable-idle-indicator";
+       res->sys_idle_indicator = of_property_read_bool(np, propname);
+
+       propname = "qcom,hfi-version";
+       ret = of_property_read_string(np, propname, &res->hfi_version);
+       if (ret)
+               dev_dbg(&pdev->dev, "legacy HFI packetization\n");
+
+       ret = get_clock_table(res);
+       if (ret) {
+               dev_err(dev, "load clock table failed (%d)\n", ret);
+               return ret;
+       }
+
+       ret = of_property_read_u32(np, "qcom,max-hw-load", &res->max_load);
+       if (ret) {
+               dev_err(dev, "determine max load supported failed (%d)\n", ret);
+               return ret;
+       }
+
+       propname = "qcom,sw-power-collapse";
+       res->sw_power_collapsible = of_property_read_bool(np, propname);
+
+       return 0;
+}
+
+void put_platform_resources(struct vidc_core *core)
+{
+       iommu_ctx_banks_detach(&core->res);
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
new file mode 100644 (file)
index 0000000..a460bc2
--- /dev/null
@@ -0,0 +1,85 @@
+/* Copyright (c) 2013-2015, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MSM_VIDC_RESOURCES_H__
+#define __MSM_VIDC_RESOURCES_H__
+
+#include <linux/platform_device.h>
+
+struct load_freq_table {
+       u32 load;
+       unsigned long freq;
+};
+
+struct reg_value_pair {
+       u32 reg;
+       u32 value;
+};
+
+struct reg_set {
+       const struct reg_value_pair *reg_tbl;
+       int count;
+};
+
+struct addr_range {
+       u32 start;
+       u32 size;
+};
+
+struct context_bank_info {
+       struct list_head list;
+       const char *name;
+       u32 buffer_type;
+       bool is_secure;
+       struct addr_range addr_range;
+       struct device *dev;
+       struct dma_iommu_mapping *mapping;
+};
+
+struct clock_info {
+       const char *name;
+       struct clk *clk;
+       const struct load_freq_table *load_freq_tbl;
+       u32 count; /* == has_scaling iff count != 0 */
+};
+
+struct clock_set {
+       struct clock_info *clock_tbl;
+       u32 count;
+};
+
+struct vidc_resources {
+       void __iomem *base;
+       unsigned int irq;
+       const struct load_freq_table *load_freq_tbl;
+       u32 load_freq_tbl_size;
+       struct reg_set reg_set;
+       u32 max_load;
+       struct platform_device *pdev;
+       struct clock_set clock_set;
+       bool sw_power_collapsible;
+       bool sys_idle_indicator;
+       struct list_head context_banks;
+       const char *hfi_version;
+};
+
+extern unsigned int vidc_pwr_collapse_delay;
+struct vidc_core;
+
+int get_platform_resources(struct vidc_core *);
+void put_platform_resources(struct vidc_core *);
+
+int enable_clocks(struct vidc_resources *);
+void disable_clocks(struct vidc_resources *);
+
+#endif
index 99807f4bd39d959bbf88520a8dcfe21e6398555a..d0abe4a5cc47df7e4ee62f39b022cab4c3b6156f 100644 (file)
@@ -369,7 +369,7 @@ enum v4l2_mpeg_video_bitrate_mode {
 enum v4l2_mpeg_video_header_mode {
        V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE                    = 0,
        V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME       = 1,
-
+       V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME         = 2,
 };
 #define V4L2_CID_MPEG_VIDEO_MAX_REF_PIC                        (V4L2_CID_MPEG_BASE+217)
 #define V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE               (V4L2_CID_MPEG_BASE+218)
@@ -380,6 +380,7 @@ enum v4l2_mpeg_video_multi_slice_mode {
        V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE         = 0,
        V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB          = 1,
        V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES       = 2,
+       V4L2_MPEG_VIDEO_MULTI_SLICE_GOB                 = 3,
 };
 #define V4L2_CID_MPEG_VIDEO_VBV_SIZE                   (V4L2_CID_MPEG_BASE+222)
 #define V4L2_CID_MPEG_VIDEO_DEC_PTS                    (V4L2_CID_MPEG_BASE+223)
diff --git a/include/uapi/media/Kbuild b/include/uapi/media/Kbuild
new file mode 100644 (file)
index 0000000..684a730
--- /dev/null
@@ -0,0 +1,2 @@
+header-y += msm_vidc.h
+header-y += msm-v4l2-controls.h
diff --git a/include/uapi/media/msm-v4l2-controls.h b/include/uapi/media/msm-v4l2-controls.h
new file mode 100644 (file)
index 0000000..aa5dde6
--- /dev/null
@@ -0,0 +1,446 @@
+#ifndef __MSM_V4L2_CONTROLS_H__
+#define __MSM_V4L2_CONTROLS_H__
+
+#include <linux/v4l2-controls.h>
+
+/*  MPEG-class control IDs specific to the msm_vidc driver */
+#define V4L2_CID_MPEG_MSM_VIDC_BASE            (V4L2_CTRL_CLASS_MPEG | 0x2000)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_PICTURE_TYPE \
+                       (V4L2_CID_MPEG_MSM_VIDC_BASE+0)
+#define V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO \
+                       (V4L2_CID_MPEG_MSM_VIDC_BASE+1)
+#define V4L2_CID_MPEG_VIDC_VIDEO_POST_LOOP_DEBLOCKER_MODE \
+                       (V4L2_CID_MPEG_MSM_VIDC_BASE+2)
+#define V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT \
+                       (V4L2_CID_MPEG_MSM_VIDC_BASE+3)
+enum v4l2_mpeg_vidc_video_divx_format_type {
+       V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4              = 0,
+       V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5              = 1,
+       V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6          = 2,
+};
+#define V4L2_CID_MPEG_VIDC_VIDEO_MB_ERROR_MAP_REPORTING        \
+                       (V4L2_CID_MPEG_MSM_VIDC_BASE+4)
+#define V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER \
+                       (V4L2_CID_MPEG_MSM_VIDC_BASE+5)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT   (V4L2_CID_MPEG_MSM_VIDC_BASE+6)
+enum v4l2_mpeg_vidc_video_stream_format {
+       V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES         = 0,
+       V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_ONE_NAL_PER_BUFFER = 1,
+       V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_ONE_BYTE_LENGTH    = 2,
+       V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH    = 3,
+       V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH   = 4,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER   (V4L2_CID_MPEG_MSM_VIDC_BASE+7)
+enum v4l2_mpeg_vidc_video_output_order {
+       V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY         = 0,
+       V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE          = 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE   (V4L2_CID_MPEG_MSM_VIDC_BASE+8)
+#define V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD   (V4L2_CID_MPEG_MSM_VIDC_BASE+9)
+#define V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES (V4L2_CID_MPEG_MSM_VIDC_BASE+10)
+#define V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES (V4L2_CID_MPEG_MSM_VIDC_BASE+11)
+#define V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME (V4L2_CID_MPEG_MSM_VIDC_BASE+12)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL (V4L2_CID_MPEG_MSM_VIDC_BASE+13)
+enum v4l2_mpeg_vidc_video_rate_control {
+       V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF = 0,
+       V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR = 1,
+       V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR = 2,
+       V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR = 3,
+       V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR = 4,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_ROTATION (V4L2_CID_MPEG_MSM_VIDC_BASE+14)
+enum v4l2_mpeg_vidc_video_rotation {
+       V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_NONE = 0,
+       V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90 = 1,
+       V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_180 = 2,
+       V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270 = 3,
+};
+#define MSM_VIDC_BASE V4L2_CID_MPEG_MSM_VIDC_BASE
+#define V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL (MSM_VIDC_BASE+15)
+enum v4l2_mpeg_vidc_h264_cabac_model {
+       V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0 = 0,
+       V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_1 = 1,
+       V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_2 = 2,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE (MSM_VIDC_BASE+16)
+enum v4l2_mpeg_vidc_video_intra_refresh_mode {
+       V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_NONE = 0,
+       V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_CYCLIC = 1,
+       V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_ADAPTIVE = 2,
+       V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_CYCLIC_ADAPTIVE = 3,
+       V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM = 4,
+};
+#define V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS (V4L2_CID_MPEG_MSM_VIDC_BASE+17)
+#define V4L2_CID_MPEG_VIDC_VIDEO_AIR_REF (V4L2_CID_MPEG_MSM_VIDC_BASE+18)
+#define V4L2_CID_MPEG_VIDC_VIDEO_CIR_MBS (V4L2_CID_MPEG_MSM_VIDC_BASE+19)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE (V4L2_CID_MPEG_MSM_VIDC_BASE+20)
+enum v4l2_mpeg_vidc_video_h263_profile {
+       V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE = 0,
+       V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_H320CODING    = 1,
+       V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BACKWARDCOMPATIBLE = 2,
+       V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV2 = 3,
+       V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV3 = 4,
+       V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHCOMPRESSION = 5,
+       V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERNET = 6,
+       V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERLACE = 7,
+       V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY = 8,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL (V4L2_CID_MPEG_MSM_VIDC_BASE+21)
+enum v4l2_mpeg_vidc_video_h263_level {
+       V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0 = 0,
+       V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_2_0 = 1,
+       V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_3_0 = 2,
+       V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_0 = 3,
+       V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_5 = 4,
+       V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_5_0 = 5,
+       V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_6_0 = 6,
+       V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0 = 7,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_H264_AU_DELIMITER \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 22)
+enum v4l2_mpeg_vidc_video_h264_au_delimiter {
+       V4L2_MPEG_VIDC_VIDEO_H264_AU_DELIMITER_DISABLED = 0,
+       V4L2_MPEG_VIDC_VIDEO_H264_AU_DELIMITER_ENABLED = 1
+};
+#define V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 23)
+enum v4l2_mpeg_vidc_video_sync_frame_decode {
+       V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_DISABLE = 0,
+       V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE = 1
+};
+#define V4L2_CID_MPEG_VIDC_VIDEO_SECURE (V4L2_CID_MPEG_MSM_VIDC_BASE+24)
+#define V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 25)
+enum v4l2_mpeg_vidc_extradata {
+       V4L2_MPEG_VIDC_EXTRADATA_NONE = 0,
+       V4L2_MPEG_VIDC_EXTRADATA_MB_QUANTIZATION = 1,
+       V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO = 2,
+       V4L2_MPEG_VIDC_EXTRADATA_VC1_FRAMEDISP = 3,
+       V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP = 4,
+       V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP = 5,
+       V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING = 6,
+       V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE = 7,
+       V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW = 8,
+       V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI = 9,
+       V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO = 10,
+       V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB = 11,
+       V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER = 12,
+       V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP = 13,
+       V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM = 14,
+       V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO = 15,
+       V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP = 16,
+       V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA = 17,
+       V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP = 18,
+       V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO = 19,
+       V4L2_MPEG_VIDC_EXTRADATA_LTR = 20,
+       V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI = 21,
+};
+
+#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_GOB            \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 27)
+
+#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE  \
+       (V4L2_CID_MPEG_MSM_VIDC_BASE + 28)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 29)
+enum v4l2_mpeg_vidc_video_h264_vui_timing_info {
+       V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED = 0,
+       V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED = 1
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_INPUT      \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 30)
+#define V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT       \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 31)
+enum v4l2_mpeg_vidc_video_alloc_mode_type {
+       V4L2_MPEG_VIDC_VIDEO_STATIC     = 0,
+       V4L2_MPEG_VIDC_VIDEO_RING       = 1,
+       V4L2_MPEG_VIDC_VIDEO_DYNAMIC    = 2,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY        \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 32)
+enum v4l2_mpeg_vidc_video_assembly {
+       V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE   = 0,
+       V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE    = 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 33)
+enum v4l2_mpeg_vidc_video_vp8_profile_level {
+       V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED,
+       V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0,
+       V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1,
+       V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_2,
+       V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_BITSTREAM_RESTRICT \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 34)
+enum v4l2_mpeg_vidc_video_h264_vui_bitstream_restrict {
+       V4L2_MPEG_VIDC_VIDEO_H264_VUI_BITSTREAM_RESTRICT_DISABLED = 0,
+       V4L2_MPEG_VIDC_VIDEO_H264_VUI_BITSTREAM_RESTRICT_ENABLED = 1
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_PRESERVE_TEXT_QUALITY \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 35)
+enum v4l2_mpeg_vidc_video_preserve_text_quality {
+       V4L2_MPEG_VIDC_VIDEO_PRESERVE_TEXT_QUALITY_DISABLED = 0,
+       V4L2_MPEG_VIDC_VIDEO_PRESERVE_TEXT_QUALITY_ENABLED = 1
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 36)
+enum v4l2_mpeg_vidc_video_deinterlace {
+       V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED = 0,
+       V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_ENABLED = 1
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_MPEG4_TIME_RESOLUTION \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 37)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 38)
+enum v4l2_mpeg_vidc_video_decoder_multi_stream {
+       V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY = 0,
+       V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY = 1,
+};
+#define V4L2_CID_MPEG_VIDC_VIDEO_SCS_THRESHOLD \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 39)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL   (V4L2_CID_MPEG_MSM_VIDC_BASE+40)
+enum v4l2_mpeg_vidc_video_mpeg2_level {
+       V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_0      = 0,
+       V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_1      = 1,
+       V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_2      = 2,
+       V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_3      = 3,
+};
+#define V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE (V4L2_CID_MPEG_MSM_VIDC_BASE+41)
+enum v4l2_mpeg_vidc_video_mpeg2_profile {
+       V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_SIMPLE               = 0,
+       V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_MAIN                 = 1,
+       V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_422                  = 2,
+       V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_SNR_SCALABLE         = 3,
+       V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_SPATIAL_SCALABLE     = 4,
+       V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_HIGH                 = 5,
+};
+#define V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_SEQ_HEADER \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 42)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 43)
+enum v4l2_mpeg_vidc_video_mvc_layout {
+       V4L2_MPEG_VIDC_VIDEO_MVC_SEQUENTIAL = 0,
+       V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM = 1
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_VP8_MIN_QP (V4L2_CID_MPEG_MSM_VIDC_BASE + 44)
+#define V4L2_CID_MPEG_VIDC_VIDEO_VP8_MAX_QP (V4L2_CID_MPEG_MSM_VIDC_BASE + 45)
+#define V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 46)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 47)
+
+enum v4l2_mpeg_vidc_video_ltrmode {
+       V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE = 0,
+       V4L2_MPEG_VIDC_VIDEO_LTR_MODE_MANUAL = 1,
+       V4L2_MPEG_VIDC_VIDEO_LTR_MODE_PERIODIC = 2
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 48)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 49)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 50)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 51)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE \
+       (V4L2_CID_MPEG_MSM_VIDC_BASE + 52)
+enum v4l2_mpeg_vidc_video_rate_control_timestamp_mode {
+       V4L2_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE_HONOR = 0,
+       V4L2_MPEG_VIDC_VIDEO_RATE_CONTROL_TIMESTAMP_MODE_IGNORE = 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_INITIAL_QP \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 53)
+enum vl42_mpeg_vidc_video_enable_initial_qp {
+       V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_INITIAL_QP_IFRAME = 0x1,
+       V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_INITIAL_QP_PFRAME = 0x2,
+       V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_INITIAL_QP_BFRAME = 0x4,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 54)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 55)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 56)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_X_RANGE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 57)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_PFRAME_X_RANGE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 58)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_BFRAME_X_RANGE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 59)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_Y_RANGE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 60)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_PFRAME_Y_RANGE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 61)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_BFRAME_Y_RANGE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 62)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE \
+       (V4L2_CID_MPEG_MSM_VIDC_BASE + 63)
+
+enum vl42_mpeg_vidc_video_vpx_error_resilience {
+       V4L2_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE_DISABLED = 0,
+       V4L2_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE_ENABLED = 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE \
+       (V4L2_CID_MPEG_MSM_VIDC_BASE + 65)
+enum v4l2_mpeg_video_hevc_profile {
+       V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN                  = 0,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10                = 1,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC        = 2,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL \
+       (V4L2_CID_MPEG_MSM_VIDC_BASE + 66)
+enum v4l2_mpeg_video_hevc_level {
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1       = 0,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1       = 1,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2       = 2,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2       = 3,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1     = 4,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1     = 5,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3       = 6,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3       = 7,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1     = 8,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1     = 9,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4       = 10,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4       = 11,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1     = 12,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1     = 13,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5       = 14,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5       = 15,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1     = 16,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1     = 17,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2     = 18,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2     = 19,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6       = 20,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6       = 21,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1     = 22,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1     = 23,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2     = 24,
+       V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_2     = 25,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC \
+       (V4L2_CID_MPEG_MSM_VIDC_BASE + 67)
+
+enum vl42_mpeg_vidc_video_h264_svc_nal {
+       V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC_DISABLED = 0,
+       V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC_ENABLED = 1,
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE      \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 68)
+
+enum v4l2_mpeg_vidc_video_perf_mode {
+       V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY = 1,
+       V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE = 2
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 69)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 70)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2 \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 71)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE \
+               (V4L2_CID_MPEG_MSM_VIDC_BASE + 72)
+
+/* Vendor extensions */
+#define V4L2_QCOM_BUF_FLAG_CODECCONFIG         0x10000
+#define V4L2_QCOM_BUF_FLAG_EOSEQ               0x20000
+#define V4L2_QCOM_BUF_TIMESTAMP_INVALID                0x40000
+#define V4L2_QCOM_BUF_FLAG_IDRFRAME            0x80000 /*Image is a IDR-frame*/
+#define V4L2_QCOM_BUF_FLAG_DECODEONLY          0x100000
+#define V4L2_QCOM_BUF_DATA_CORRUPT             0x200000
+#define V4L2_QCOM_BUF_DROP_FRAME               0x400000
+#define V4L2_QCOM_BUF_INPUT_UNSUPPORTED                0x800000
+#define V4L2_QCOM_BUF_FLAG_EOS                 0x1000000
+#define V4L2_QCOM_BUF_TS_DISCONTINUITY         0x2000000
+#define V4L2_QCOM_BUF_TS_ERROR                 0x4000000
+#define V4L2_QCOM_BUF_FLAG_READONLY            0x8000000
+#define V4L2_MSM_VIDC_BUF_START_CODE_NOT_FOUND 0x10000000
+#define V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP    0x20000000
+#define V4L2_MSM_BUF_FLAG_MBAFF                        0x40000000
+
+/* Capabilities */
+#define V4L2_CAP_QCOM_FRAMESKIP        0x2000  /*  frame skipping is supported */
+
+struct v4l2_qcom_frameskip {
+       __u64              maxframeinterval;
+       __u8               fpsvariance;
+};
+
+/* Encoder commands */
+#define V4L2_ENC_QCOM_CMD_FLUSH  (4)
+
+/* Decoder commands */
+#define V4L2_DEC_QCOM_CMD_FLUSH  (4)
+
+/* Flags for V4L2_DEC_QCOM_CMD_FLUSH */
+#define V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT  (1 << 0)
+#define V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE (1 << 1)
+
+#define V4L2_QCOM_CMD_FLUSH_OUTPUT  (1 << 0)
+#define V4L2_QCOM_CMD_FLUSH_CAPTURE (1 << 1)
+
+/* Events */
+#define V4L2_EVENT_MSM_VIDC_START      (V4L2_EVENT_PRIVATE_START + 0x00001000)
+#define V4L2_EVENT_MSM_VIDC_FLUSH_DONE (V4L2_EVENT_MSM_VIDC_START + 1)
+#define V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT   \
+               (V4L2_EVENT_MSM_VIDC_START + 2)
+#define V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT \
+               (V4L2_EVENT_MSM_VIDC_START + 3)
+#define V4L2_EVENT_MSM_VIDC_CLOSE_DONE (V4L2_EVENT_MSM_VIDC_START + 4)
+#define V4L2_EVENT_MSM_VIDC_SYS_ERROR  (V4L2_EVENT_MSM_VIDC_START + 5)
+#define V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE \
+               (V4L2_EVENT_MSM_VIDC_START + 6)
+#define V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER \
+               (V4L2_EVENT_MSM_VIDC_START + 7)
+#define V4L2_EVENT_MSM_VIDC_HW_OVERLOAD (V4L2_EVENT_MSM_VIDC_START + 8)
+#define V4L2_EVENT_MSM_VIDC_MAX_CLIENTS (V4L2_EVENT_MSM_VIDC_START + 9)
+#define V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED (V4L2_EVENT_MSM_VIDC_START + 10)
+
+#endif/* __MSM_V4L2_CONTROLS_H__ */