msm: camera: jpeg: add jpeg driver implementation

Software driver implementation for JPEG hardware encoder and dma.

Change-Id: I651b0a530a9367e04ec976877f72d074b0b708c6
Signed-off-by: Rajakumar Govindaram <rajakuma@codeaurora.org>
Signed-off-by: Soundrapandian Jeyaprakash <jsoundra@codeaurora.org>
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/Makefile b/drivers/media/platform/msm/camera/cam_jpeg/Makefile
new file mode 100644
index 0000000..4d272d3
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/Makefile
@@ -0,0 +1,11 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include/
+
+obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_hw/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg_dev.o cam_jpeg_context.o
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
new file mode 100644
index 0000000..a299179
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.c
@@ -0,0 +1,138 @@
+/* Copyright (c) 2017, 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/videodev2.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "cam_mem_mgr.h"
+#include "cam_sync_api.h"
+#include "cam_jpeg_context.h"
+#include "cam_context_utils.h"
+#include "cam_debug_util.h"
+
+static int __cam_jpeg_ctx_acquire_dev_in_available(struct cam_context *ctx,
+	struct cam_acquire_dev_cmd *cmd)
+{
+	int rc;
+
+	rc = cam_context_acquire_dev_to_hw(ctx, cmd);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "Unable to Acquire device %d", rc);
+	else
+		ctx->state = CAM_CTX_ACQUIRED;
+
+	return rc;
+}
+
+static int __cam_jpeg_ctx_release_dev_in_acquired(struct cam_context *ctx,
+	struct cam_release_dev_cmd *cmd)
+{
+	int rc;
+
+	rc = cam_context_release_dev_to_hw(ctx, cmd);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "Unable to release device %d", rc);
+
+	ctx->state = CAM_CTX_AVAILABLE;
+
+	return rc;
+}
+
+static int __cam_jpeg_ctx_config_dev_in_acquired(struct cam_context *ctx,
+	struct cam_config_dev_cmd *cmd)
+{
+	return cam_context_prepare_dev_to_hw(ctx, cmd);
+}
+
+static int __cam_jpeg_ctx_handle_buf_done_in_acquired(void *ctx,
+	uint32_t evt_id, void *done)
+{
+	return cam_context_buf_done_from_hw(ctx, done, evt_id);
+}
+
+/* top state machine */
+static struct cam_ctx_ops
+	cam_jpeg_ctx_state_machine[CAM_CTX_STATE_MAX] = {
+	/* Uninit */
+	{
+		.ioctl_ops = { },
+		.crm_ops = { },
+		.irq_ops = NULL,
+	},
+	/* Available */
+	{
+		.ioctl_ops = {
+			.acquire_dev = __cam_jpeg_ctx_acquire_dev_in_available,
+		},
+		.crm_ops = { },
+		.irq_ops = NULL,
+	},
+	/* Acquired */
+	{
+		.ioctl_ops = {
+			.release_dev = __cam_jpeg_ctx_release_dev_in_acquired,
+			.config_dev = __cam_jpeg_ctx_config_dev_in_acquired,
+		},
+		.crm_ops = { },
+		.irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired,
+	},
+};
+
+int cam_jpeg_context_init(struct cam_jpeg_context *ctx,
+	struct cam_context *ctx_base,
+	struct cam_hw_mgr_intf *hw_intf)
+{
+	int rc;
+	int i;
+
+	if (!ctx || !ctx_base) {
+		CAM_ERR(CAM_JPEG, "Invalid Context");
+		rc = -EFAULT;
+		goto err;
+	}
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	ctx->base = ctx_base;
+
+	for (i = 0; i < CAM_CTX_REQ_MAX; i++)
+		ctx->req_base[i].req_priv = ctx;
+
+	rc = cam_context_init(ctx_base, NULL, hw_intf, ctx->req_base,
+		CAM_CTX_REQ_MAX);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "Camera Context Base init failed");
+		goto err;
+	}
+
+	ctx_base->state_machine = cam_jpeg_ctx_state_machine;
+	ctx_base->ctx_priv = ctx;
+
+err:
+	return rc;
+}
+
+int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx)
+{
+	if (!ctx || !ctx->base) {
+		CAM_ERR(CAM_JPEG, "Invalid params: %pK", ctx);
+		return -EINVAL;
+	}
+
+	cam_context_deinit(ctx->base);
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	return 0;
+}
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.h b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.h
new file mode 100644
index 0000000..90ac5cf
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_context.h
@@ -0,0 +1,72 @@
+/* Copyright (c) 2017, 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 _CAM_JPEG_CONTEXT_H_
+#define _CAM_JPEG_CONTEXT_H_
+
+#include <uapi/media/cam_jpeg.h>
+
+#include "cam_context.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+
+#define CAM_JPEG_HW_EVENT_MAX 20
+
+/**
+ * struct cam_jpeg_context - Jpeg context
+ * @base: Base jpeg cam context object
+ * @req_base: Common request structure
+ */
+struct cam_jpeg_context {
+	struct cam_context *base;
+	struct cam_ctx_request req_base[CAM_CTX_REQ_MAX];
+};
+
+/* cam jpeg context irq handling function type */
+typedef int (*cam_jpeg_hw_event_cb_func)(
+	struct cam_jpeg_context *ctx_jpeg,
+	void *evt_data);
+
+/**
+ * struct cam_jpeg_ctx_irq_ops - Function table for handling IRQ callbacks
+ *
+ * @irq_ops: Array of handle function pointers.
+ *
+ */
+struct cam_jpeg_ctx_irq_ops {
+	cam_jpeg_hw_event_cb_func irq_ops[CAM_JPEG_HW_EVENT_MAX];
+};
+
+/**
+ * cam_jpeg_context_init()
+ *
+ * @brief: Initialization function for the JPEG context
+ *
+ * @ctx: JPEG context obj to be initialized
+ * @ctx_base: Context base from cam_context
+ * @hw_intf: JPEG hw manager interface
+ *
+ */
+int cam_jpeg_context_init(struct cam_jpeg_context *ctx,
+	struct cam_context *ctx_base,
+	struct cam_hw_mgr_intf *hw_intf);
+
+/**
+ * cam_jpeg_context_deinit()
+ *
+ * @brief: Deinitialize function for the JPEG context
+ *
+ * @ctx: JPEG context obj to be deinitialized
+ *
+ */
+int cam_jpeg_context_deinit(struct cam_jpeg_context *ctx);
+
+#endif  /* __CAM_JPEG_CONTEXT_H__ */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c
new file mode 100644
index 0000000..fb68ddb
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c
@@ -0,0 +1,136 @@
+/* Copyright (c) 2017, 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/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/ion.h>
+#include <linux/kernel.h>
+
+#include "cam_node.h"
+#include "cam_hw_mgr_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_jpeg_dev.h"
+#include "cam_debug_util.h"
+
+#define CAM_JPEG_DEV_NAME "cam-jpeg"
+
+static struct cam_jpeg_dev g_jpeg_dev;
+
+static const struct of_device_id cam_jpeg_dt_match[] = {
+	{
+		.compatible = "qcom,cam-jpeg"
+	},
+	{ }
+};
+
+static int cam_jpeg_dev_remove(struct platform_device *pdev)
+{
+	int rc;
+	int i;
+
+	for (i = 0; i < CAM_CTX_MAX; i++) {
+		rc = cam_jpeg_context_deinit(&g_jpeg_dev.ctx_jpeg[i]);
+		if (rc)
+			CAM_ERR(CAM_JPEG, "JPEG context %d deinit failed %d",
+				i, rc);
+	}
+
+	rc = cam_subdev_remove(&g_jpeg_dev.sd);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "Unregister failed %d", rc);
+
+	return rc;
+}
+
+static int cam_jpeg_dev_probe(struct platform_device *pdev)
+{
+	int rc;
+	int i;
+	struct cam_hw_mgr_intf hw_mgr_intf;
+	struct cam_node *node;
+
+	rc = cam_subdev_probe(&g_jpeg_dev.sd, pdev, CAM_JPEG_DEV_NAME,
+		CAM_JPEG_DEVICE_TYPE);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "JPEG cam_subdev_probe failed %d", rc);
+		goto err;
+	}
+	node = (struct cam_node *)g_jpeg_dev.sd.token;
+
+	rc = cam_jpeg_hw_mgr_init(pdev->dev.of_node,
+		(uint64_t *)&hw_mgr_intf);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "Can not initialize JPEG HWmanager %d", rc);
+		goto unregister;
+	}
+
+	for (i = 0; i < CAM_CTX_MAX; i++) {
+		rc = cam_jpeg_context_init(&g_jpeg_dev.ctx_jpeg[i],
+			&g_jpeg_dev.ctx[i],
+			&node->hw_mgr_intf);
+		if (rc) {
+			CAM_ERR(CAM_JPEG, "JPEG context init failed %d %d",
+				i, rc);
+			goto ctx_init_fail;
+		}
+	}
+
+	rc = cam_node_init(node, &hw_mgr_intf, g_jpeg_dev.ctx, CAM_CTX_MAX,
+		CAM_JPEG_DEV_NAME);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "JPEG node init failed %d", rc);
+		goto ctx_init_fail;
+	}
+
+	mutex_init(&g_jpeg_dev.jpeg_mutex);
+
+	CAM_INFO(CAM_JPEG, "Camera JPEG probe complete");
+
+	return rc;
+
+ctx_init_fail:
+	for (--i; i >= 0; i--)
+		if (cam_jpeg_context_deinit(&g_jpeg_dev.ctx_jpeg[i]))
+			CAM_ERR(CAM_JPEG, "deinit fail %d %d", i, rc);
+unregister:
+	if (cam_subdev_remove(&g_jpeg_dev.sd))
+		CAM_ERR(CAM_JPEG, "remove fail %d", rc);
+err:
+	return rc;
+}
+
+static struct platform_driver jpeg_driver = {
+	.probe = cam_jpeg_dev_probe,
+	.remove = cam_jpeg_dev_remove,
+	.driver = {
+		.name = "cam_jpeg",
+		.owner = THIS_MODULE,
+		.of_match_table = cam_jpeg_dt_match,
+	},
+};
+
+static int __init cam_jpeg_dev_init_module(void)
+{
+	return platform_driver_register(&jpeg_driver);
+}
+
+static void __exit cam_jpeg_dev_exit_module(void)
+{
+	platform_driver_unregister(&jpeg_driver);
+}
+
+module_init(cam_jpeg_dev_init_module);
+module_exit(cam_jpeg_dev_exit_module);
+MODULE_DESCRIPTION("MSM JPEG driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h
new file mode 100644
index 0000000..deab2d5
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2017, 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 _CAM_JPEG_DEV_H_
+#define _CAM_JPEG_DEV_H_
+
+#include "cam_subdev.h"
+#include "cam_hw_mgr_intf.h"
+#include "cam_context.h"
+#include "cam_jpeg_context.h"
+
+/**
+ * struct cam_jpeg_dev - Camera JPEG V4l2 device node
+ *
+ * @sd: Commone camera subdevice node
+ * @node: Pointer to jpeg subdevice
+ * @ctx: JPEG base context storage
+ * @ctx_jpeg: JPEG private context storage
+ * @jpeg_mutex: Jpeg dev mutex
+ */
+struct cam_jpeg_dev {
+	struct cam_subdev sd;
+	struct cam_node *node;
+	struct cam_context ctx[CAM_CTX_MAX];
+	struct cam_jpeg_context ctx_jpeg[CAM_CTX_MAX];
+	struct mutex jpeg_mutex;
+};
+#endif /* __CAM_JPEG_DEV_H__ */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/Makefile b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/Makefile
new file mode 100644
index 0000000..08c9528
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/Makefile
@@ -0,0 +1,13 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sync/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cdm/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/
+
+obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_enc_hw/
+obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_dma_hw/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_jpeg_hw_mgr.o
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
new file mode 100644
index 0000000..b06b5c4
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -0,0 +1,1178 @@
+/* Copyright (c) 2017, 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/uaccess.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/debugfs.h>
+#include <media/cam_defs.h>
+#include <media/cam_jpeg.h>
+
+#include "cam_sync_api.h"
+#include "cam_packet_util.h"
+#include "cam_hw.h"
+#include "cam_hw_mgr_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_jpeg_hw_mgr.h"
+#include "cam_enc_hw_intf.h"
+#include "cam_dma_hw_intf.h"
+#include "cam_smmu_api.h"
+#include "cam_mem_mgr.h"
+#include "cam_req_mgr_workq.h"
+#include "cam_mem_mgr.h"
+#include "cam_cdm_intf_api.h"
+#include "cam_debug_util.h"
+
+#define CAM_JPEG_HW_ENTRIES_MAX  20
+
+static struct cam_jpeg_hw_mgr g_jpeg_hw_mgr;
+
+static int32_t cam_jpeg_hw_mgr_cb(uint32_t irq_status,
+	int32_t result_size, void *data);
+static int cam_jpeg_mgr_process_cmd(void *priv, void *data);
+
+static int cam_jpeg_mgr_process_irq(void *priv, void *data)
+{
+	int rc = 0;
+	struct cam_jpeg_process_irq_work_data_t *task_data;
+	struct cam_jpeg_hw_mgr *hw_mgr;
+	int32_t i;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	struct cam_hw_done_event_data buf_data;
+	struct cam_jpeg_set_irq_cb irq_cb;
+	uint32_t dev_type = 0;
+	uint64_t kaddr;
+	uint32_t *cmd_buf_kaddr;
+	size_t cmd_buf_len;
+	struct cam_jpeg_config_inout_param_info *p_params;
+	struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
+	struct crm_workq_task *task;
+	struct cam_jpeg_process_frame_work_data_t *wq_task_data;
+
+	if (!data || !priv) {
+		CAM_ERR(CAM_JPEG, "Invalid data");
+		return -EINVAL;
+	}
+
+	task_data = data;
+	hw_mgr = &g_jpeg_hw_mgr;
+
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)task_data->data;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		return -EINVAL;
+	}
+
+	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+
+	irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb;
+	irq_cb.data = NULL;
+	irq_cb.b_set_cb = false;
+	if (!hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) {
+		CAM_ERR(CAM_JPEG, "process_cmd null ");
+		return -EINVAL;
+	}
+	rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd(
+		hw_mgr->devices[dev_type][0]->hw_priv,
+		CAM_JPEG_ENC_CMD_SET_IRQ_CB,
+		&irq_cb, sizeof(irq_cb));
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "CMD_SET_IRQ_CB failed %d", rc);
+		return rc;
+	}
+
+	mutex_lock(&g_jpeg_hw_mgr.hw_mgr_mutex);
+	hw_mgr->device_in_use[dev_type][0] = false;
+	p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0];
+	hw_mgr->dev_hw_cfg_args[dev_type][0] = NULL;
+	mutex_unlock(&g_jpeg_hw_mgr.hw_mgr_mutex);
+
+	task = cam_req_mgr_workq_get_task(
+		g_jpeg_hw_mgr.work_process_frame);
+	if (!task) {
+		CAM_ERR(CAM_JPEG, "no empty task");
+		return -EINVAL;
+	}
+
+	wq_task_data = (struct cam_jpeg_process_frame_work_data_t *)
+		task->payload;
+	if (!task_data) {
+		CAM_ERR(CAM_JPEG, "task_data is NULL");
+		return -EINVAL;
+	}
+	wq_task_data->data = (void *)(uint64_t)dev_type;
+	wq_task_data->request_id = 0;
+	wq_task_data->type = CAM_JPEG_WORKQ_TASK_CMD_TYPE;
+	task->process_cb = cam_jpeg_mgr_process_cmd;
+	rc = cam_req_mgr_workq_enqueue_task(task, &g_jpeg_hw_mgr,
+		CRM_TASK_PRIORITY_0);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "could not enque task %d", rc);
+		return rc;
+	}
+
+	rc = cam_mem_get_cpu_buf(
+		p_cfg_req->hw_cfg_args.hw_update_entries[1].handle,
+		(uint64_t *)&kaddr, &cmd_buf_len);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "unable to get info for cmd buf: %x %d",
+			hw_mgr->iommu_hdl, rc);
+		return rc;
+	}
+
+	cmd_buf_kaddr = (uint32_t *)kaddr;
+
+	cmd_buf_kaddr =
+		(cmd_buf_kaddr +
+		(p_cfg_req->hw_cfg_args.hw_update_entries[1].offset/4));
+
+	p_params = (struct cam_jpeg_config_inout_param_info *)cmd_buf_kaddr;
+
+	p_params->output_size = task_data->result_size;
+	CAM_DBG(CAM_JPEG, "Encoded Size %d", task_data->result_size);
+
+	buf_data.num_handles = p_cfg_req->
+		hw_cfg_args.num_out_map_entries;
+	for (i = 0; i < buf_data.num_handles; i++) {
+		buf_data.resource_handle[i] =
+			p_cfg_req->hw_cfg_args.
+			out_map_entries[i].resource_handle;
+	}
+	buf_data.request_id =
+		(uint64_t)p_cfg_req->hw_cfg_args.priv;
+	ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data);
+
+	list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list);
+
+
+	return rc;
+}
+
+static int cam_jpeg_hw_mgr_cb(
+	uint32_t irq_status, int32_t result_size, void *data)
+{
+	int32_t rc;
+	unsigned long flags;
+	struct cam_jpeg_hw_mgr *hw_mgr = &g_jpeg_hw_mgr;
+	struct crm_workq_task *task;
+	struct cam_jpeg_process_irq_work_data_t *task_data;
+
+	spin_lock_irqsave(&hw_mgr->hw_mgr_lock, flags);
+	task = cam_req_mgr_workq_get_task(
+		g_jpeg_hw_mgr.work_process_irq_cb);
+	if (!task) {
+		CAM_ERR(CAM_JPEG, "no empty task");
+		spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags);
+		return -ENOMEM;
+	}
+
+	task_data = (struct cam_jpeg_process_irq_work_data_t *)task->payload;
+	task_data->data = data;
+	task_data->irq_status = irq_status;
+	task_data->result_size = result_size;
+	task_data->type = CAM_JPEG_WORKQ_TASK_MSG_TYPE;
+	task->process_cb = cam_jpeg_mgr_process_irq;
+
+	rc = cam_req_mgr_workq_enqueue_task(task, &g_jpeg_hw_mgr,
+		CRM_TASK_PRIORITY_0);
+	spin_unlock_irqrestore(&hw_mgr->hw_mgr_lock, flags);
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_get_free_ctx(struct cam_jpeg_hw_mgr *hw_mgr)
+{
+	int i = 0;
+	int num_ctx = CAM_JPEG_CTX_MAX;
+
+	for (i = 0; i < num_ctx; i++) {
+		mutex_lock(&hw_mgr->ctx_data[i].ctx_mutex);
+		if (hw_mgr->ctx_data[i].in_use == false) {
+			hw_mgr->ctx_data[i].in_use = true;
+			mutex_unlock(&hw_mgr->ctx_data[i].ctx_mutex);
+			break;
+		}
+		mutex_unlock(&hw_mgr->ctx_data[i].ctx_mutex);
+	}
+
+	return i;
+}
+
+
+static int cam_jpeg_mgr_release_ctx(
+	struct cam_jpeg_hw_mgr *hw_mgr, int ctx_id)
+{
+	if (ctx_id >= CAM_JPEG_CTX_MAX) {
+		CAM_ERR(CAM_JPEG, "ctx_id is wrong: %d", ctx_id);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
+	if (!hw_mgr->ctx_data[ctx_id].in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is already in use: %d", ctx_id);
+		mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
+		return -EINVAL;
+	}
+
+	hw_mgr->ctx_data[ctx_id].in_use = 0;
+	mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
+
+	return 0;
+}
+
+static int cam_jpeg_mgr_process_cmd(void *priv, void *data)
+{
+	int rc;
+	int i = 0;
+	struct cam_jpeg_hw_mgr *hw_mgr = priv;
+	struct cam_hw_update_entry *cmd;
+	struct cam_cdm_bl_request *cdm_cmd;
+	struct cam_hw_config_args *config_args = NULL;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	uint64_t request_id = 0;
+	struct cam_jpeg_process_frame_work_data_t *task_data =
+		(struct cam_jpeg_process_frame_work_data_t *)data;
+	uint32_t dev_type;
+	struct cam_jpeg_set_irq_cb irq_cb;
+	struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
+	uint32_t size = 0;
+	uint32_t mem_cam_base = 0;
+	struct cam_hw_done_event_data buf_data;
+
+	CAM_DBG(CAM_JPEG, "in cam_jpeg_mgr_process_cmd");
+	if (!hw_mgr || !task_data) {
+		CAM_ERR(CAM_JPEG, "Invalid arguments %pK %pK",
+			hw_mgr, task_data);
+		return -EINVAL;
+	}
+
+	if (list_empty(&hw_mgr->hw_config_req_list)) {
+		CAM_DBG(CAM_JPEG, "no available request");
+		rc = -EFAULT;
+		goto end;
+	}
+
+	p_cfg_req = list_first_entry(&hw_mgr->hw_config_req_list,
+		struct cam_jpeg_hw_cfg_req, list);
+	if (!p_cfg_req) {
+		CAM_ERR(CAM_JPEG, "no request");
+		rc = -EFAULT;
+		goto end;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	if (false == hw_mgr->device_in_use[p_cfg_req->dev_type][0]) {
+		hw_mgr->device_in_use[p_cfg_req->dev_type][0] = true;
+		hw_mgr->dev_hw_cfg_args[p_cfg_req->dev_type][0] = p_cfg_req;
+		list_del_init(&p_cfg_req->list);
+	} else {
+		CAM_ERR(CAM_JPEG, "NOT dequeing, just return");
+		rc = -EFAULT;
+		goto end;
+	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	config_args = (struct cam_hw_config_args *)&p_cfg_req->hw_cfg_args;
+	request_id = task_data->request_id;
+	if (request_id != (uint64_t)config_args->priv) {
+		CAM_WARN(CAM_JPEG, "not a recent req %d %d",
+			request_id, (uint64_t)config_args->priv);
+	}
+
+	if (!config_args->num_hw_update_entries) {
+		CAM_ERR(CAM_JPEG, "No hw update enteries are available");
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)config_args->ctxt_to_hw_map;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+
+	if (dev_type != p_cfg_req->dev_type)
+		CAM_WARN(CAM_JPEG, "dev types not same something wrong");
+
+	irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb;
+	irq_cb.data = (void *)ctx_data;
+	irq_cb.b_set_cb = true;
+	if (!hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) {
+		CAM_ERR(CAM_JPEG, "op process_cmd null ");
+		return -EINVAL;
+	}
+	rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd(
+		hw_mgr->devices[dev_type][0]->hw_priv,
+		CAM_JPEG_ENC_CMD_SET_IRQ_CB,
+		&irq_cb, sizeof(irq_cb));
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "SET_IRQ_CB failed %d", rc);
+		return -EINVAL;
+	}
+
+	if (!hw_mgr->devices[dev_type][0]->hw_ops.reset) {
+		CAM_ERR(CAM_JPEG, "op reset null ");
+		return -EINVAL;
+	}
+	rc = hw_mgr->devices[dev_type][0]->hw_ops.reset(
+		hw_mgr->devices[dev_type][0]->hw_priv,
+		NULL, 0);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "jpeg hw reset failed %d", rc);
+		return -EINVAL;
+	}
+
+	mem_cam_base = (uint64_t)hw_mgr->cdm_reg_map[dev_type][0]->
+		mem_cam_base;
+	size = hw_mgr->cdm_info[dev_type][0].cdm_ops->
+		cdm_required_size_changebase();
+	hw_mgr->cdm_info[dev_type][0].cdm_ops->
+		cdm_write_changebase(ctx_data->cmd_chbase_buf_addr,
+		(uint64_t)hw_mgr->cdm_reg_map[dev_type][0]->mem_cam_base);
+	ctx_data->cdm_cmd_chbase->cmd_arrary_count = 1;
+	ctx_data->cdm_cmd_chbase->type = CAM_CDM_BL_CMD_TYPE_KERNEL_IOVA;
+	ctx_data->cdm_cmd_chbase->flag = false;
+	ctx_data->cdm_cmd_chbase->userdata = NULL;
+	ctx_data->cdm_cmd_chbase->cookie = 0;
+	ctx_data->cdm_cmd_chbase->cmd[0].bl_addr.kernel_iova =
+		ctx_data->cmd_chbase_buf_addr;
+	ctx_data->cdm_cmd_chbase->cmd[0].offset = 0;
+	ctx_data->cdm_cmd_chbase->cmd[0].len = size;
+	rc = cam_cdm_submit_bls(hw_mgr->cdm_info[dev_type][0].cdm_handle,
+		ctx_data->cdm_cmd_chbase);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "failed cdm cmd %d", rc);
+
+	CAM_DBG(CAM_JPEG, "cfg e %pK num %d",
+		config_args->hw_update_entries,
+		config_args->num_hw_update_entries);
+
+	if (config_args->num_hw_update_entries > 0) {
+		cdm_cmd = ctx_data->cdm_cmd;
+		cdm_cmd->cmd_arrary_count =
+			config_args->num_hw_update_entries - 1;
+		cdm_cmd->type = CAM_CDM_BL_CMD_TYPE_MEM_HANDLE;
+		cdm_cmd->flag = false;
+		cdm_cmd->userdata = NULL;
+		cdm_cmd->cookie = 0;
+
+		for (i = 0; i <= cdm_cmd->cmd_arrary_count; i++) {
+			cmd = (config_args->hw_update_entries + i);
+			cdm_cmd->cmd[i].bl_addr.mem_handle = cmd->handle;
+			cdm_cmd->cmd[i].offset = cmd->offset;
+			cdm_cmd->cmd[i].len = cmd->len;
+		}
+
+		rc = cam_cdm_submit_bls(
+			hw_mgr->cdm_info[dev_type][0].cdm_handle,
+			cdm_cmd);
+		if (rc) {
+			CAM_ERR(CAM_JPEG, "Failed to apply the configs %d",
+				rc);
+			goto end_callcb;
+		}
+
+		if (!hw_mgr->devices[dev_type][0]->hw_ops.start) {
+			CAM_ERR(CAM_JPEG, "op start null ");
+			rc = -EINVAL;
+			goto end_callcb;
+		}
+		rc = hw_mgr->devices[dev_type][0]->hw_ops.start(
+			hw_mgr->devices[dev_type][0]->hw_priv,
+			NULL, 0);
+		if (rc) {
+			CAM_ERR(CAM_JPEG, "Failed to apply the configs %d",
+				rc);
+			goto end_callcb;
+		}
+	} else {
+		CAM_ERR(CAM_JPEG, "No commands to config");
+	}
+
+	return rc;
+
+end_callcb:
+	if (p_cfg_req) {
+		buf_data.num_handles = p_cfg_req->
+			hw_cfg_args.num_out_map_entries;
+		for (i = 0; i < buf_data.num_handles; i++) {
+			buf_data.resource_handle[i] =
+				p_cfg_req->hw_cfg_args.
+				out_map_entries[i].resource_handle;
+		}
+		buf_data.request_id =
+			(uint64_t)p_cfg_req->hw_cfg_args.priv;
+		ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data);
+	}
+end:
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
+{
+	int rc;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_hw_config_args *config_args = config_hw_args;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	uint64_t request_id = 0;
+	struct cam_hw_update_entry *hw_update_entries;
+	struct crm_workq_task *task;
+	struct cam_jpeg_process_frame_work_data_t *task_data;
+	struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
+
+	if (!hw_mgr || !config_args) {
+		CAM_ERR(CAM_JPEG, "Invalid arguments %pK %pK",
+			hw_mgr, config_args);
+		return -EINVAL;
+	}
+
+	if (!config_args->num_hw_update_entries) {
+		CAM_ERR(CAM_JPEG, "No hw update enteries are available");
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)config_args->ctxt_to_hw_map;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+
+	if (list_empty(&hw_mgr->free_req_list)) {
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		CAM_ERR(CAM_JPEG, "list empty");
+		return -ENOMEM;
+	}
+
+	p_cfg_req = list_first_entry(&hw_mgr->free_req_list,
+		struct cam_jpeg_hw_cfg_req, list);
+	list_del_init(&p_cfg_req->list);
+
+	/* Update Currently Processing Config Request */
+	p_cfg_req->hw_cfg_args = *config_args;
+	p_cfg_req->dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+
+	request_id = (uint64_t)config_args->priv;
+	hw_update_entries = config_args->hw_update_entries;
+	CAM_DBG(CAM_JPEG, "ctx_data = %pK req_id = %d %pK",
+		ctx_data, request_id, config_args->priv);
+	task = cam_req_mgr_workq_get_task(g_jpeg_hw_mgr.work_process_frame);
+	if (!task) {
+		CAM_ERR(CAM_JPEG, "no empty task");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		rc = -ENOMEM;
+		goto err_after_dq_free_list;
+	}
+
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	task_data = (struct cam_jpeg_process_frame_work_data_t *)
+		task->payload;
+	if (!task_data) {
+		CAM_ERR(CAM_JPEG, "task_data is NULL");
+		rc = -EINVAL;
+		goto err_after_dq_free_list;
+	}
+	CAM_DBG(CAM_JPEG, "cfge %pK num %d",
+		p_cfg_req->hw_cfg_args.hw_update_entries,
+		p_cfg_req->hw_cfg_args.num_hw_update_entries);
+
+	list_add_tail(&p_cfg_req->list, &hw_mgr->hw_config_req_list);
+
+	task_data->data = (void *)(int64_t)p_cfg_req->dev_type;
+	task_data->request_id = request_id;
+	task_data->type = CAM_JPEG_WORKQ_TASK_CMD_TYPE;
+	task->process_cb = cam_jpeg_mgr_process_cmd;
+
+	rc = cam_req_mgr_workq_enqueue_task(task, &g_jpeg_hw_mgr,
+		CRM_TASK_PRIORITY_0);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "failed to enqueue task %d", rc);
+		goto err_after_get_task;
+	}
+
+	return rc;
+
+err_after_get_task:
+	list_del_init(&p_cfg_req->list);
+err_after_dq_free_list:
+	list_add_tail(&p_cfg_req->list, &hw_mgr->free_req_list);
+
+	return rc;
+}
+
+
+static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv,
+	void *prepare_hw_update_args)
+{
+	int rc, i, j, k;
+	struct cam_hw_prepare_update_args *prepare_args =
+		prepare_hw_update_args;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	struct cam_packet *packet = NULL;
+	struct cam_cmd_buf_desc *cmd_desc = NULL;
+	struct cam_buf_io_cfg *io_cfg_ptr = NULL;
+
+	if (!prepare_args || !hw_mgr) {
+		CAM_ERR(CAM_JPEG, "Invalid args %pK %pK",
+			prepare_args, hw_mgr);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)prepare_args->ctxt_to_hw_map;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	packet = prepare_args->packet;
+	if (!packet) {
+		CAM_ERR(CAM_JPEG, "received packet is NULL");
+		return -EINVAL;
+	}
+
+	if (((packet->header.op_code & 0xff) != CAM_JPEG_OPCODE_ENC_UPDATE) &&
+		((packet->header.op_code
+		& 0xff) != CAM_JPEG_OPCODE_DMA_UPDATE)) {
+		CAM_ERR(CAM_JPEG, "Invalid Opcode in pkt: %d",
+			packet->header.op_code & 0xff);
+		return -EINVAL;
+	}
+	if ((packet->num_cmd_buf > 2) || !packet->num_patches ||
+		!packet->num_io_configs) {
+		CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u",
+			packet->num_cmd_buf,
+			packet->num_patches);
+		return -EINVAL;
+	}
+
+	cmd_desc = (struct cam_cmd_buf_desc *)
+		((uint32_t *)&packet->payload +
+		(packet->cmd_buf_offset / 4));
+	CAM_DBG(CAM_JPEG, "packet = %pK cmd_desc = %pK size = %lu",
+		(void *)packet, (void *)cmd_desc,
+		sizeof(struct cam_cmd_buf_desc));
+
+	rc = cam_packet_util_process_patches(packet, hw_mgr->iommu_hdl);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "Patch processing failed %d", rc);
+		return rc;
+	}
+
+	io_cfg_ptr = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
+		packet->io_configs_offset / 4);
+	CAM_DBG(CAM_JPEG, "packet = %pK io_cfg_ptr = %pK size = %lu",
+		(void *)packet, (void *)io_cfg_ptr,
+		sizeof(struct cam_buf_io_cfg));
+
+	prepare_args->num_out_map_entries = 0;
+
+	for (i = 0, j = 0, k = 0; i < packet->num_io_configs; i++) {
+		if (io_cfg_ptr[i].direction == CAM_BUF_INPUT) {
+			prepare_args->in_map_entries[j].resource_handle =
+				io_cfg_ptr[i].resource_type;
+			prepare_args->in_map_entries[j++].sync_id =
+				io_cfg_ptr[i].fence;
+			prepare_args->num_in_map_entries++;
+		} else {
+			prepare_args->in_map_entries[k].resource_handle =
+				io_cfg_ptr[i].resource_type;
+			prepare_args->out_map_entries[k++].sync_id =
+				io_cfg_ptr[i].fence;
+			prepare_args->num_out_map_entries++;
+		}
+		CAM_DBG(CAM_JPEG, "dir[%d]: %u, fence: %u",
+			i, io_cfg_ptr[i].direction, io_cfg_ptr[i].fence);
+	}
+
+	for (i = 0; i < packet->num_cmd_buf;  i++) {
+		prepare_args->hw_update_entries[i].len =
+			(uint32_t)cmd_desc[i].length;
+		prepare_args->hw_update_entries[i].handle =
+			(uint32_t)cmd_desc[i].mem_handle;
+		prepare_args->hw_update_entries[i].offset =
+			(uint32_t)cmd_desc[i].offset;
+		prepare_args->num_hw_update_entries++;
+	}
+
+	prepare_args->priv = (void *)packet->header.request_id;
+
+	CAM_DBG(CAM_JPEG, "will wait on input sync sync_id %d",
+		prepare_args->in_map_entries[0].sync_id);
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args)
+{
+	int rc;
+	int ctx_id = 0;
+	struct cam_hw_release_args *release_hw = release_hw_args;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	uint32_t dev_type;
+
+	if (!release_hw || !hw_mgr) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return -EINVAL;
+	}
+
+	ctx_data = (struct cam_jpeg_hw_ctx_data *)release_hw->ctxt_to_hw_map;
+	if (!ctx_data->in_use) {
+		CAM_ERR(CAM_JPEG, "ctx is not in use");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+
+	hw_mgr->cdm_info[dev_type][0].ref_cnt--;
+	if (!(hw_mgr->cdm_info[dev_type][0].ref_cnt)) {
+		if (cam_cdm_stream_off(
+			hw_mgr->cdm_info[dev_type][0].cdm_handle)) {
+			CAM_ERR(CAM_JPEG, "CDM stream off failed %d",
+				hw_mgr->cdm_info[dev_type][0].cdm_handle);
+		}
+		/* release cdm handle */
+		cam_cdm_release(hw_mgr->cdm_info[dev_type][0].cdm_handle);
+	}
+
+	if (g_jpeg_hw_mgr.devices[dev_type][0]->hw_ops.deinit) {
+		rc = g_jpeg_hw_mgr.devices[dev_type][0]->hw_ops.deinit(
+			g_jpeg_hw_mgr.devices[dev_type][0]->hw_priv, NULL, 0);
+		if (rc)
+			CAM_ERR(CAM_JPEG, "Failed to Init %d HW", dev_type);
+	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	rc = cam_jpeg_mgr_release_ctx(hw_mgr, ctx_id);
+	if (rc) {
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_JPEG, "handle %llu", ctx_data);
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
+{
+	int rc;
+	int32_t ctx_id = 0;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
+	struct cam_hw_acquire_args *args = acquire_hw_args;
+	struct cam_jpeg_acquire_dev_info jpeg_dev_acquire_info;
+	struct cam_cdm_acquire_data cdm_acquire;
+	uint32_t dev_type;
+	uint32_t size = 0;
+
+	if ((!hw_mgr_priv) || (!acquire_hw_args)) {
+		CAM_ERR(CAM_JPEG, "Invalid params: %pK %pK", hw_mgr_priv,
+			acquire_hw_args);
+		return -EINVAL;
+	}
+
+	if (args->num_acq > 1) {
+		CAM_ERR(CAM_JPEG,
+			"number of resources are wrong: %u",
+			args->num_acq);
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&jpeg_dev_acquire_info,
+			(void __user *)args->acquire_info,
+			sizeof(jpeg_dev_acquire_info))) {
+		CAM_ERR(CAM_JPEG, "copy failed");
+		return -EFAULT;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	ctx_id = cam_jpeg_mgr_get_free_ctx(hw_mgr);
+	if (ctx_id >= CAM_JPEG_CTX_MAX) {
+		CAM_ERR(CAM_JPEG, "No free ctx space in hw_mgr");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return -EFAULT;
+	}
+
+	ctx_data = &hw_mgr->ctx_data[ctx_id];
+
+	ctx_data->cdm_cmd =
+		kzalloc(((sizeof(struct cam_cdm_bl_request)) +
+			((CAM_JPEG_HW_ENTRIES_MAX - 1) *
+			sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL);
+	if (!ctx_data->cdm_cmd) {
+		rc = -ENOMEM;
+		goto acq_cdm_hdl_failed;
+	}
+
+	mutex_lock(&ctx_data->ctx_mutex);
+	ctx_data->jpeg_dev_acquire_info = jpeg_dev_acquire_info;
+	mutex_unlock(&ctx_data->ctx_mutex);
+
+	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+	if (!hw_mgr->cdm_info[dev_type][0].ref_cnt) {
+
+		if (dev_type == CAM_JPEG_RES_TYPE_ENC) {
+			memcpy(cdm_acquire.identifier,
+				"jpegenc", sizeof("jpegenc"));
+		} else {
+			memcpy(cdm_acquire.identifier,
+				"jpegdma", sizeof("jpegdma"));
+		}
+		cdm_acquire.cell_index = 0;
+		cdm_acquire.handle = 0;
+		cdm_acquire.userdata = ctx_data;
+		if (hw_mgr->cdm_reg_map[dev_type][0]) {
+			cdm_acquire.base_array[0] =
+				hw_mgr->cdm_reg_map[dev_type][0];
+		}
+		cdm_acquire.base_array_cnt = 1;
+		cdm_acquire.id = CAM_CDM_VIRTUAL;
+		cdm_acquire.cam_cdm_callback = NULL;
+
+		rc = cam_cdm_acquire(&cdm_acquire);
+		if (rc) {
+			CAM_ERR(CAM_JPEG, "Failed to acquire the CDM HW %d",
+				rc);
+			rc = -EFAULT;
+			goto acq_cdm_hdl_failed;
+		}
+		hw_mgr->cdm_info[dev_type][0].cdm_handle = cdm_acquire.handle;
+		hw_mgr->cdm_info[dev_type][0].cdm_ops = cdm_acquire.ops;
+		hw_mgr->cdm_info[dev_type][0].ref_cnt++;
+	} else {
+		hw_mgr->cdm_info[dev_type][0].ref_cnt++;
+	}
+
+	ctx_data->cdm_cmd_chbase =
+		kzalloc(((sizeof(struct cam_cdm_bl_request)) +
+			(2 * sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL);
+	if (!ctx_data->cdm_cmd_chbase) {
+		rc = -ENOMEM;
+		goto start_cdm_hdl_failed;
+	}
+	size = hw_mgr->cdm_info[dev_type][0].
+		cdm_ops->cdm_required_size_changebase();
+	ctx_data->cmd_chbase_buf_addr = kzalloc(size*4, GFP_KERNEL);
+	if (!ctx_data->cdm_cmd_chbase) {
+		rc = -ENOMEM;
+		goto start_cdm_hdl_failed;
+	}
+
+	if (!g_jpeg_hw_mgr.devices[dev_type][0]->hw_ops.init) {
+		CAM_ERR(CAM_JPEG, "hw op init null ");
+		rc = -EINVAL;
+		goto start_cdm_hdl_failed;
+	}
+	rc = g_jpeg_hw_mgr.devices[dev_type][0]->hw_ops.init(
+		g_jpeg_hw_mgr.devices[dev_type][0]->hw_priv,
+		ctx_data,
+		sizeof(ctx_data));
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "Failed to Init %d HW", dev_type);
+		goto start_cdm_hdl_failed;
+	}
+
+	if (hw_mgr->cdm_info[dev_type][0].ref_cnt == 1)
+		if (cam_cdm_stream_on(
+			hw_mgr->cdm_info[dev_type][0].cdm_handle)) {
+			CAM_ERR(CAM_JPEG, "Can not start cdm (%d)!",
+				hw_mgr->cdm_info[dev_type][0].cdm_handle);
+			rc = -EFAULT;
+			goto start_cdm_hdl_failed;
+		}
+
+	mutex_lock(&ctx_data->ctx_mutex);
+	ctx_data->context_priv = args->context_data;
+
+	args->ctxt_to_hw_map = (void *)&(hw_mgr->ctx_data[ctx_id]);
+
+	mutex_unlock(&ctx_data->ctx_mutex);
+
+	hw_mgr->ctx_data[ctx_id].ctxt_event_cb = args->event_cb;
+
+
+	if (copy_to_user((void __user *)args->acquire_info,
+		&jpeg_dev_acquire_info,
+		sizeof(jpeg_dev_acquire_info))) {
+		rc = -EFAULT;
+		goto copy_to_user_failed;
+	}
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	CAM_DBG(CAM_JPEG, "success ctx_data= %pK", ctx_data);
+
+	return rc;
+
+copy_to_user_failed:
+	cam_cdm_stream_off(hw_mgr->cdm_info[dev_type][0].cdm_handle);
+start_cdm_hdl_failed:
+	cam_cdm_release(hw_mgr->cdm_info[dev_type][0].cdm_handle);
+acq_cdm_hdl_failed:
+	kfree(ctx_data->cdm_cmd);
+	cam_jpeg_mgr_release_ctx(hw_mgr, ctx_id);
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	return rc;
+}
+
+static int cam_jpeg_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args)
+{
+	int rc;
+	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
+	struct cam_query_cap_cmd *query_cap = hw_caps_args;
+
+	if (!hw_mgr_priv || !hw_caps_args) {
+		CAM_ERR(CAM_JPEG, "Invalid params: %pK %pK",
+			hw_mgr_priv, hw_caps_args);
+		return -EINVAL;
+	}
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+
+	if (copy_to_user((void __user *)query_cap->caps_handle,
+		&g_jpeg_hw_mgr.jpeg_caps,
+		sizeof(struct cam_jpeg_query_cap_cmd))) {
+		CAM_ERR(CAM_JPEG, "copy_to_user failed");
+		rc = -EFAULT;
+		goto copy_error;
+	}
+	CAM_DBG(CAM_JPEG, "cam_jpeg_mgr_get_hw_caps success");
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	return 0;
+
+copy_error:
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+	return rc;
+}
+
+static int cam_jpeg_setup_workqs(void)
+{
+	int rc, i;
+
+	rc = cam_req_mgr_workq_create(
+		"jpeg_command_queue",
+		CAM_JPEG_WORKQ_NUM_TASK,
+		&g_jpeg_hw_mgr.work_process_frame,
+		CRM_WORKQ_USAGE_NON_IRQ);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc);
+		goto work_process_frame_failed;
+	}
+
+	rc = cam_req_mgr_workq_create(
+		"jpeg_message_queue",
+		CAM_JPEG_WORKQ_NUM_TASK,
+		&g_jpeg_hw_mgr.work_process_irq_cb,
+		CRM_WORKQ_USAGE_IRQ);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc);
+		goto work_process_irq_cb_failed;
+	}
+
+	g_jpeg_hw_mgr.process_frame_work_data =
+		(struct cam_jpeg_process_frame_work_data_t *)
+		kzalloc(sizeof(struct cam_jpeg_process_frame_work_data_t) *
+			CAM_JPEG_WORKQ_NUM_TASK, GFP_KERNEL);
+	if (!g_jpeg_hw_mgr.process_frame_work_data) {
+		rc = -ENOMEM;
+		goto work_process_frame_data_failed;
+	}
+
+	g_jpeg_hw_mgr.process_irq_cb_work_data =
+		(struct cam_jpeg_process_irq_work_data_t *)
+		kzalloc(sizeof(struct cam_jpeg_process_irq_work_data_t) *
+			CAM_JPEG_WORKQ_NUM_TASK, GFP_KERNEL);
+	if (!g_jpeg_hw_mgr.process_irq_cb_work_data) {
+		rc = -ENOMEM;
+		goto work_process_irq_cb_data_failed;
+	}
+
+	for (i = 0; i < CAM_JPEG_WORKQ_NUM_TASK; i++)
+		g_jpeg_hw_mgr.work_process_irq_cb->task.pool[i].payload =
+			&g_jpeg_hw_mgr.process_irq_cb_work_data[i];
+
+	for (i = 0; i < CAM_JPEG_WORKQ_NUM_TASK; i++)
+		g_jpeg_hw_mgr.work_process_frame->task.pool[i].payload =
+			&g_jpeg_hw_mgr.process_frame_work_data[i];
+
+	INIT_LIST_HEAD(&g_jpeg_hw_mgr.hw_config_req_list);
+	INIT_LIST_HEAD(&g_jpeg_hw_mgr.free_req_list);
+	for (i = 0; i < CAM_JPEG_HW_CFG_Q_MAX; i++) {
+		INIT_LIST_HEAD(&(g_jpeg_hw_mgr.req_list[i].list));
+		list_add_tail(&(g_jpeg_hw_mgr.req_list[i].list),
+			&(g_jpeg_hw_mgr.free_req_list));
+	}
+
+	return rc;
+
+work_process_irq_cb_data_failed:
+	kfree(g_jpeg_hw_mgr.process_frame_work_data);
+work_process_frame_data_failed:
+	cam_req_mgr_workq_destroy(&g_jpeg_hw_mgr.work_process_irq_cb);
+work_process_irq_cb_failed:
+	cam_req_mgr_workq_destroy(&g_jpeg_hw_mgr.work_process_frame);
+work_process_frame_failed:
+
+	return rc;
+}
+
+static int cam_jpeg_init_devices(struct device_node *of_node,
+	uint32_t *p_num_enc_dev,
+	uint32_t *p_num_dma_dev)
+{
+	int count, i, rc;
+	uint32_t num_dev;
+	uint32_t num_dma_dev;
+	const char *name = NULL;
+	struct device_node *child_node = NULL;
+	struct platform_device *child_pdev = NULL;
+	struct cam_hw_intf *child_dev_intf = NULL;
+	struct cam_hw_info *enc_hw = NULL;
+	struct cam_hw_info *dma_hw = NULL;
+	struct cam_hw_soc_info *enc_soc_info = NULL;
+	struct cam_hw_soc_info *dma_soc_info = NULL;
+
+	if (!p_num_enc_dev || !p_num_dma_dev) {
+		rc = -EINVAL;
+		goto num_dev_failed;
+	}
+	count = of_property_count_strings(of_node, "compat-hw-name");
+	if (!count) {
+		CAM_ERR(CAM_JPEG,
+			"no compat hw found in dev tree, count = %d",
+			count);
+		rc = -EINVAL;
+		goto num_dev_failed;
+	}
+
+	rc = of_property_read_u32(of_node, "num-jpeg-enc", &num_dev);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "read num enc devices failed %d", rc);
+		goto num_enc_failed;
+	}
+	g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC] = kzalloc(
+		sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL);
+	if (!g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC]) {
+		rc = -ENOMEM;
+		CAM_ERR(CAM_JPEG, "getting number of dma dev nodes failed");
+		goto num_enc_failed;
+	}
+
+	rc = of_property_read_u32(of_node, "num-jpeg-dma", &num_dma_dev);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "get num dma dev nodes failed %d", rc);
+		goto num_dma_failed;
+	}
+
+	g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA] = kzalloc(
+		sizeof(struct cam_hw_intf *) * num_dma_dev, GFP_KERNEL);
+	if (!g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA]) {
+		rc = -ENOMEM;
+		goto num_dma_failed;
+	}
+
+	for (i = 0; i < count; i++) {
+		rc = of_property_read_string_index(of_node, "compat-hw-name",
+			i, &name);
+		if (rc) {
+			CAM_ERR(CAM_JPEG, "getting dev object name failed");
+			goto compat_hw_name_failed;
+		}
+
+		child_node = of_find_node_by_name(NULL, name);
+		if (!child_node) {
+			CAM_ERR(CAM_JPEG,
+				"error! Cannot find node in dtsi %s", name);
+			rc = -ENODEV;
+			goto compat_hw_name_failed;
+		}
+
+		child_pdev = of_find_device_by_node(child_node);
+		if (!child_pdev) {
+			CAM_ERR(CAM_JPEG, "failed to find device on bus %s",
+				child_node->name);
+			rc = -ENODEV;
+			of_node_put(child_node);
+			goto compat_hw_name_failed;
+		}
+
+		child_dev_intf = (struct cam_hw_intf *)platform_get_drvdata(
+			child_pdev);
+		if (!child_dev_intf) {
+			CAM_ERR(CAM_JPEG, "no child device");
+			of_node_put(child_node);
+			rc = -ENODEV;
+			goto compat_hw_name_failed;
+		}
+		CAM_DBG(CAM_JPEG, "child_intf %pK type %d id %d",
+			child_dev_intf,
+			child_dev_intf->hw_type,
+			child_dev_intf->hw_idx);
+
+		if ((child_dev_intf->hw_type == CAM_JPEG_DEV_ENC &&
+			child_dev_intf->hw_idx >= num_dev) ||
+			(child_dev_intf->hw_type == CAM_JPEG_DEV_DMA &&
+			child_dev_intf->hw_idx >= num_dma_dev)) {
+			CAM_ERR(CAM_JPEG, "index out of range");
+			rc = -ENODEV;
+			goto compat_hw_name_failed;
+		}
+		g_jpeg_hw_mgr.devices[child_dev_intf->hw_type]
+			[child_dev_intf->hw_idx] = child_dev_intf;
+
+		of_node_put(child_node);
+	}
+
+	enc_hw = (struct cam_hw_info *)
+		g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC][0]->hw_priv;
+	enc_soc_info = &enc_hw->soc_info;
+	g_jpeg_hw_mgr.cdm_reg_map[CAM_JPEG_DEV_ENC][0] =
+		&enc_soc_info->reg_map[0];
+	dma_hw = (struct cam_hw_info *)
+		g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA][0]->hw_priv;
+	dma_soc_info = &dma_hw->soc_info;
+	g_jpeg_hw_mgr.cdm_reg_map[CAM_JPEG_DEV_DMA][0] =
+		&dma_soc_info->reg_map[0];
+
+	*p_num_enc_dev = num_dev;
+	*p_num_dma_dev = num_dma_dev;
+
+	return rc;
+
+compat_hw_name_failed:
+	kfree(g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA]);
+num_dma_failed:
+	kfree(g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC]);
+num_enc_failed:
+num_dev_failed:
+
+	return rc;
+}
+
+int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl)
+{
+	int i, rc;
+	uint32_t num_dev;
+	uint32_t num_dma_dev;
+	struct cam_hw_mgr_intf *hw_mgr_intf;
+	struct cam_iommu_handle cdm_handles;
+
+	hw_mgr_intf = (struct cam_hw_mgr_intf *)hw_mgr_hdl;
+	if (!of_node || !hw_mgr_intf) {
+		CAM_ERR(CAM_JPEG, "Invalid args of_node %pK hw_mgr %pK",
+			of_node, hw_mgr_intf);
+		return -EINVAL;
+	}
+
+	memset(hw_mgr_hdl, 0x0, sizeof(struct cam_hw_mgr_intf));
+	hw_mgr_intf->hw_mgr_priv = &g_jpeg_hw_mgr;
+	hw_mgr_intf->hw_get_caps = cam_jpeg_mgr_get_hw_caps;
+	hw_mgr_intf->hw_acquire = cam_jpeg_mgr_acquire_hw;
+	hw_mgr_intf->hw_release = cam_jpeg_mgr_release_hw;
+	hw_mgr_intf->hw_prepare_update = cam_jpeg_mgr_prepare_hw_update;
+	hw_mgr_intf->hw_config = cam_jpeg_mgr_config_hw;
+
+	mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex);
+	spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock);
+
+	for (i = 0; i < CAM_JPEG_CTX_MAX; i++)
+		mutex_init(&g_jpeg_hw_mgr.ctx_data[i].ctx_mutex);
+
+	rc = cam_jpeg_init_devices(of_node, &num_dev, &num_dma_dev);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "jpeg init devices %d", rc);
+		goto smmu_get_failed;
+	}
+
+	rc = cam_smmu_get_handle("jpeg", &g_jpeg_hw_mgr.iommu_hdl);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "jpeg get iommu handle failed %d", rc);
+		goto smmu_get_failed;
+	}
+
+	CAM_DBG(CAM_JPEG, "mmu handle :%d", g_jpeg_hw_mgr.iommu_hdl);
+	rc = cam_smmu_ops(g_jpeg_hw_mgr.iommu_hdl, CAM_SMMU_ATTACH);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "jpeg attach failed: %d", rc);
+		goto jpeg_attach_failed;
+	}
+
+	rc = cam_cdm_get_iommu_handle("jpegenc", &cdm_handles);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "acquire cdm iommu handle Fail  %d", rc);
+		g_jpeg_hw_mgr.cdm_iommu_hdl = -1;
+		g_jpeg_hw_mgr.cdm_iommu_hdl_secure = -1;
+		goto cdm_iommu_failed;
+	}
+	g_jpeg_hw_mgr.cdm_iommu_hdl = cdm_handles.non_secure;
+	g_jpeg_hw_mgr.cdm_iommu_hdl_secure = cdm_handles.secure;
+
+	g_jpeg_hw_mgr.jpeg_caps.dev_iommu_handle.non_secure =
+		g_jpeg_hw_mgr.iommu_hdl;
+	g_jpeg_hw_mgr.jpeg_caps.dev_iommu_handle.secure =
+		g_jpeg_hw_mgr.iommu_sec_hdl;
+	g_jpeg_hw_mgr.jpeg_caps.cdm_iommu_handle.non_secure =
+		g_jpeg_hw_mgr.cdm_iommu_hdl;
+	g_jpeg_hw_mgr.jpeg_caps.cdm_iommu_handle.secure =
+		g_jpeg_hw_mgr.cdm_iommu_hdl_secure;
+	g_jpeg_hw_mgr.jpeg_caps.num_enc = num_dev;
+	g_jpeg_hw_mgr.jpeg_caps.num_dma = num_dma_dev;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.major = 4;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.minor = 2;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.incr  = 0;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_ENC].hw_ver.reserved = 0;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.major = 4;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.minor = 2;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.incr  = 0;
+	g_jpeg_hw_mgr.jpeg_caps.dev_ver[CAM_JPEG_DEV_DMA].hw_ver.reserved = 0;
+
+	rc = cam_jpeg_setup_workqs();
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "setup work qs failed  %d", rc);
+		goto cdm_iommu_failed;
+	}
+
+	return rc;
+
+cdm_iommu_failed:
+	cam_smmu_ops(g_jpeg_hw_mgr.iommu_hdl, CAM_SMMU_DETACH);
+	cam_smmu_destroy_handle(g_jpeg_hw_mgr.iommu_hdl);
+jpeg_attach_failed:
+	g_jpeg_hw_mgr.iommu_hdl = 0;
+smmu_get_failed:
+	mutex_destroy(&g_jpeg_hw_mgr.hw_mgr_mutex);
+	for (i = 0; i < CAM_JPEG_CTX_MAX; i++)
+		mutex_destroy(&g_jpeg_hw_mgr.ctx_data[i].ctx_mutex);
+
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
new file mode 100644
index 0000000..9e3418d
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
@@ -0,0 +1,164 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_HW_MGR_H
+#define CAM_JPEG_HW_MGR_H
+
+#include <linux/types.h>
+#include <linux/completion.h>
+#include <media/cam_jpeg.h>
+
+#include "cam_jpeg_hw_intf.h"
+#include "cam_hw_mgr_intf.h"
+#include "cam_hw_intf.h"
+#include "cam_req_mgr_workq.h"
+#include "cam_mem_mgr.h"
+
+#define CAM_JPEG_WORKQ_NUM_TASK      30
+#define CAM_JPEG_WORKQ_TASK_CMD_TYPE 1
+#define CAM_JPEG_WORKQ_TASK_MSG_TYPE 2
+#define CAM_JPEG_HW_CFG_Q_MAX        50
+
+/**
+ * struct cam_jpeg_process_frame_work_data_t
+ *
+ * @type: Task type
+ * @data: Pointer to command data
+ * @request_id: Request id
+ */
+struct cam_jpeg_process_frame_work_data_t {
+	uint32_t type;
+	void *data;
+	uint64_t request_id;
+};
+
+/**
+ * struct cam_jpeg_process_irq_work_data_t
+ *
+ * @type: Task type
+ * @data: Pointer to message data
+ * @result_size: Result size of enc/dma
+ * @irq_status: IRQ status
+ */
+struct cam_jpeg_process_irq_work_data_t {
+	uint32_t type;
+	void *data;
+	int32_t result_size;
+	uint32_t irq_status;
+};
+
+/**
+ * struct cam_jpeg_hw_cdm_info_t
+ *
+ * @ref_cnt: Ref count of how many times device type is acquired
+ * @cdm_handle: Cdm handle
+ * @cdm_ops: Cdm ops struct
+ */
+struct cam_jpeg_hw_cdm_info_t {
+	int ref_cnt;
+	uint32_t cdm_handle;
+	struct cam_cdm_utils_ops *cdm_ops;
+};
+
+/**
+ * struct cam_jpeg_hw_cfg_req_t
+ *
+ * @list_head: List head
+ * @hw_cfg_args: Hw config args
+ * @dev_type: Dev type for cfg request
+ */
+struct cam_jpeg_hw_cfg_req {
+	struct list_head list;
+	struct cam_hw_config_args hw_cfg_args;
+	uint32_t dev_type;
+};
+
+/**
+ * struct cam_jpeg_hw_ctx_data
+ *
+ * @context_priv: Context private data, cam_context from
+ *     acquire.
+ * @ctx_mutex: Mutex for context
+ * @jpeg_dev_acquire_info: Acquire device info
+ * @ctxt_event_cb: Context callback function
+ * @in_use: Flag for context usage
+ * @wait_complete: Completion info
+ * @cdm_cmd: Cdm cmd submitted for that context.
+ * @cdm_cmd_chbase: Change base cdm command from context
+ * @cmd_chbase_buf_addr : Change base cmd buf address
+ */
+struct cam_jpeg_hw_ctx_data {
+	void *context_priv;
+	struct mutex ctx_mutex;
+	struct cam_jpeg_acquire_dev_info jpeg_dev_acquire_info;
+	cam_hw_event_cb_func ctxt_event_cb;
+	bool in_use;
+	struct completion wait_complete;
+	struct cam_cdm_bl_request *cdm_cmd;
+	struct cam_cdm_bl_request *cdm_cmd_chbase;
+	uint32_t *cmd_chbase_buf_addr;
+};
+
+/**
+ * struct cam_jpeg_hw_mgr
+ * @hw_mgr_mutex: Mutex for JPEG hardware manager
+ * @hw_mgr_lock: Spinlock for JPEG hardware manager
+ * @ctx_data: Context data
+ * @jpeg_caps: JPEG capabilities
+ * @iommu_hdl: Non secure IOMMU handle
+ * @iommu_sec_hdl: Secure IOMMU handle
+ * @work_process_frame: Work queue for hw config requests
+ * @work_process_irq_cb: Work queue for processing IRQs.
+ * @process_frame_work_data: Work data pool for hw config
+ *     requests
+ * @process_irq_cb_work_data: Work data pool for irq requests
+ * @cdm_iommu_hdl: Iommu handle received from cdm
+ * @cdm_iommu_hdl_secure: Secure iommu handle received from cdm
+ * @devices: Core hw Devices of JPEG hardware manager
+ * @cdm_info: Cdm info for each core device.
+ * @cdm_reg_map: Regmap of each device for cdm.
+ * @device_in_use: Flag device being used for an active request
+ * @dev_hw_cfg_args: Current cfg request per core dev
+ * @hw_config_req_list: Pending hw update requests list
+ * @free_req_list: Free nodes for above list
+ * @req_list: Nodes of hw update list
+ */
+struct cam_jpeg_hw_mgr {
+	struct mutex hw_mgr_mutex;
+	spinlock_t hw_mgr_lock;
+	struct cam_jpeg_hw_ctx_data ctx_data[CAM_JPEG_CTX_MAX];
+	struct cam_jpeg_query_cap_cmd jpeg_caps;
+	int32_t iommu_hdl;
+	int32_t iommu_sec_hdl;
+	struct cam_req_mgr_core_workq *work_process_frame;
+	struct cam_req_mgr_core_workq *work_process_irq_cb;
+	struct cam_jpeg_process_frame_work_data_t *process_frame_work_data;
+	struct cam_jpeg_process_irq_work_data_t *process_irq_cb_work_data;
+	int cdm_iommu_hdl;
+	int cdm_iommu_hdl_secure;
+
+	struct cam_hw_intf **devices[CAM_JPEG_DEV_TYPE_MAX];
+	struct cam_jpeg_hw_cdm_info_t cdm_info[CAM_JPEG_DEV_TYPE_MAX]
+		[CAM_JPEG_NUM_DEV_PER_RES_MAX];
+	struct cam_soc_reg_map *cdm_reg_map[CAM_JPEG_DEV_TYPE_MAX]
+		[CAM_JPEG_NUM_DEV_PER_RES_MAX];
+	uint32_t device_in_use[CAM_JPEG_DEV_TYPE_MAX]
+		[CAM_JPEG_NUM_DEV_PER_RES_MAX];
+	struct cam_jpeg_hw_cfg_req *dev_hw_cfg_args[CAM_JPEG_DEV_TYPE_MAX]
+		[CAM_JPEG_NUM_DEV_PER_RES_MAX];
+
+	struct list_head hw_config_req_list;
+	struct list_head free_req_list;
+	struct cam_jpeg_hw_cfg_req req_list[CAM_JPEG_HW_CFG_Q_MAX];
+};
+
+#endif /* CAM_JPEG_HW_MGR_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_dma_hw_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_dma_hw_intf.h
new file mode 100644
index 0000000..71b21b9
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_dma_hw_intf.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_DMA_HW_INTF_H
+#define CAM_JPEG_DMA_HW_INTF_H
+
+#include <uapi/media/cam_defs.h>
+#include <media/cam_jpeg.h>
+
+#include "cam_hw_mgr_intf.h"
+#include "cam_jpeg_hw_intf.h"
+
+enum cam_jpeg_dma_cmd_type {
+	CAM_JPEG_DMA_CMD_CDM_CFG,
+	CAM_JPEG_DMA_CMD_SET_IRQ_CB,
+	CAM_JPEG_DMA_CMD_MAX,
+};
+
+#endif /* CAM_JPEG_DMA_HW_INTF_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_enc_hw_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_enc_hw_intf.h
new file mode 100644
index 0000000..f0b4e00
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_enc_hw_intf.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_ENC_HW_INTF_H
+#define CAM_JPEG_ENC_HW_INTF_H
+
+#include <uapi/media/cam_defs.h>
+#include <media/cam_jpeg.h>
+
+#include "cam_hw_mgr_intf.h"
+#include "cam_jpeg_hw_intf.h"
+
+enum cam_jpeg_enc_cmd_type {
+	CAM_JPEG_ENC_CMD_CDM_CFG,
+	CAM_JPEG_ENC_CMD_SET_IRQ_CB,
+	CAM_JPEG_ENC_CMD_MAX,
+};
+
+#endif /* CAM_JPEG_ENC_HW_INTF_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h
new file mode 100644
index 0000000..3204388
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h
@@ -0,0 +1,26 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_HW_INTF_H
+#define CAM_JPEG_HW_INTF_H
+
+#define CAM_JPEG_CTX_MAX              8
+#define CAM_JPEG_DEV_PER_TYPE_MAX     1
+
+#define CAM_JPEG_CMD_BUF_MAX_SIZE     128
+#define CAM_JPEG_MSG_BUF_MAX_SIZE     CAM_JPEG_CMD_BUF_MAX_SIZE
+
+enum cam_jpeg_hw_type {
+	CAM_JPEG_DEV_ENC,
+	CAM_JPEG_DEV_DMA,
+};
+#endif
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h
new file mode 100644
index 0000000..d5c8c9d
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_mgr_intf.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_HW_MGR_INTF_H
+#define CAM_JPEG_HW_MGR_INTF_H
+
+#include <uapi/media/cam_jpeg.h>
+#include <uapi/media/cam_defs.h>
+#include <linux/of.h>
+
+#include "cam_cpas_api.h"
+
+#define JPEG_TURBO_VOTE           640000000
+
+int cam_jpeg_hw_mgr_init(struct device_node *of_node,
+	uint64_t *hw_mgr_hdl);
+
+/**
+ * struct cam_jpeg_cpas_vote
+ * @ahb_vote: AHB vote info
+ * @axi_vote: AXI vote info
+ * @ahb_vote_valid: Flag for ahb vote data
+ * @axi_vote_valid: Flag for axi vote data
+ */
+struct cam_jpeg_cpas_vote {
+	struct cam_ahb_vote ahb_vote;
+	struct cam_axi_vote axi_vote;
+	uint32_t ahb_vote_valid;
+	uint32_t axi_vote_valid;
+};
+
+struct cam_jpeg_set_irq_cb {
+	int32_t (*jpeg_hw_mgr_cb)(
+		uint32_t irq_status,
+		int32_t result_size,
+		void *data);
+	void *data;
+	uint32_t b_set_cb;
+};
+
+#endif /* CAM_JPEG_HW_MGR_INTF_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile
new file mode 100644
index 0000000..23b27bf
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/Makefile
@@ -0,0 +1,11 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_hw_mgr/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw
+
+obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_dma_dev.o jpeg_dma_core.o jpeg_dma_soc.o
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c
new file mode 100644
index 0000000..05c1a95
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c
@@ -0,0 +1,165 @@
+/* Copyright (c) 2017, 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/of.h>
+#include <linux/debugfs.h>
+#include <linux/videodev2.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+
+#include "cam_io_util.h"
+#include "cam_hw.h"
+#include "cam_hw_intf.h"
+#include "jpeg_dma_core.h"
+#include "jpeg_dma_soc.h"
+#include "cam_soc_util.h"
+#include "cam_io_util.h"
+#include "cam_dma_hw_intf.h"
+#include "cam_jpeg_hw_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_cpas_api.h"
+#include "cam_debug_util.h"
+
+int cam_jpeg_dma_init_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_dma_dev = device_priv;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_dma_device_core_info *core_info = NULL;
+	struct cam_jpeg_cpas_vote cpas_vote;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid cam_dev_info");
+		return -EINVAL;
+	}
+
+	soc_info = &jpeg_dma_dev->soc_info;
+	core_info =
+		(struct cam_jpeg_dma_device_core_info *)jpeg_dma_dev->
+		core_info;
+
+	if (!soc_info || !core_info) {
+		CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
+		return -EINVAL;
+	}
+
+	cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE;
+	cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE;
+	cpas_vote.axi_vote.compressed_bw = JPEG_TURBO_VOTE;
+	cpas_vote.axi_vote.uncompressed_bw = JPEG_TURBO_VOTE;
+
+	rc = cam_cpas_start(core_info->cpas_handle,
+		&cpas_vote.ahb_vote, &cpas_vote.axi_vote);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpass start failed: %d", rc);
+
+	rc = cam_jpeg_dma_enable_soc_resources(soc_info);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "soc enable is failed %d", rc);
+		cam_cpas_stop(core_info->cpas_handle);
+	}
+
+	return rc;
+}
+
+int cam_jpeg_dma_deinit_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_dma_dev = device_priv;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_dma_device_core_info *core_info = NULL;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid cam_dev_info");
+		return -EINVAL;
+	}
+
+	soc_info = &jpeg_dma_dev->soc_info;
+	core_info = (struct cam_jpeg_dma_device_core_info *)
+		jpeg_dma_dev->core_info;
+	if (!soc_info || !core_info) {
+		CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
+		return -EINVAL;
+	}
+
+	rc = cam_jpeg_dma_disable_soc_resources(soc_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "soc enable failed %d", rc);
+
+	rc = cam_cpas_stop(core_info->cpas_handle);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpas stop failed: %d", rc);
+
+	return 0;
+}
+
+int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type,
+	void *cmd_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_dma_dev = device_priv;
+	struct cam_jpeg_dma_device_core_info *core_info = NULL;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid arguments");
+		return -EINVAL;
+	}
+
+	if (cmd_type >= CAM_JPEG_DMA_CMD_MAX) {
+		CAM_ERR(CAM_JPEG, "Invalid command : %x", cmd_type);
+		return -EINVAL;
+	}
+
+	core_info =
+		(struct cam_jpeg_dma_device_core_info *)jpeg_dma_dev->
+		core_info;
+
+	switch (cmd_type) {
+	case CAM_JPEG_DMA_CMD_SET_IRQ_CB:
+	{
+		struct cam_jpeg_set_irq_cb *irq_cb = cmd_args;
+
+		if (!cmd_args) {
+			CAM_ERR(CAM_JPEG, "cmd args NULL");
+			return -EINVAL;
+		}
+		if (irq_cb->b_set_cb) {
+			core_info->irq_cb.jpeg_hw_mgr_cb =
+				irq_cb->jpeg_hw_mgr_cb;
+			core_info->irq_cb.data = irq_cb->data;
+		} else {
+			core_info->irq_cb.jpeg_hw_mgr_cb = NULL;
+			core_info->irq_cb.data = NULL;
+		}
+		rc = 0;
+		break;
+	}
+	default:
+		rc = -EINVAL;
+		break;
+	}
+
+	return rc;
+}
+
+irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data)
+{
+	return IRQ_HANDLED;
+}
+
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h
new file mode 100644
index 0000000..bb4e34a
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_DMA_CORE_H
+#define CAM_JPEG_DMA_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/dma-buf.h>
+
+struct cam_jpeg_dma_device_hw_info {
+	uint32_t reserved;
+};
+
+struct cam_jpeg_dma_set_irq_cb {
+	int32_t (*jpeg_hw_mgr_cb)(uint32_t irq_status,
+		int32_t result_size, void *data);
+	void *data;
+};
+
+enum cam_jpeg_dma_core_state {
+	CAM_JPEG_DMA_CORE_NOT_READY,
+	CAM_JPEG_DMA_CORE_READY,
+	CAM_JPEG_DMA_CORE_RESETTING,
+	CAM_JPEG_DMA_CORE_STATE_MAX,
+};
+
+struct cam_jpeg_dma_device_core_info {
+	enum cam_jpeg_dma_core_state core_state;
+	struct cam_jpeg_dma_device_hw_info *jpeg_dma_hw_info;
+	uint32_t cpas_handle;
+	struct cam_jpeg_dma_set_irq_cb irq_cb;
+};
+
+int cam_jpeg_dma_init_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size);
+int cam_jpeg_dma_deinit_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size);
+int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type,
+	void *cmd_args, uint32_t arg_size);
+irqreturn_t cam_jpeg_dma_irq(int irq_num, void *data);
+
+#endif /* CAM_JPEG_DMA_CORE_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c
new file mode 100644
index 0000000..829bb51
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2017, 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/module.h>
+#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/timer.h>
+
+#include "jpeg_dma_core.h"
+#include "jpeg_dma_soc.h"
+#include "cam_hw.h"
+#include "cam_hw_intf.h"
+#include "cam_io_util.h"
+#include "cam_jpeg_hw_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_cpas_api.h"
+#include "cam_debug_util.h"
+
+static struct cam_jpeg_dma_device_hw_info cam_jpeg_dma_hw_info = {
+	.reserved = 0,
+};
+EXPORT_SYMBOL(cam_jpeg_dma_hw_info);
+
+static int cam_jpeg_dma_register_cpas(struct cam_hw_soc_info *soc_info,
+	struct cam_jpeg_dma_device_core_info *core_info,
+	uint32_t hw_idx)
+{
+	struct cam_cpas_register_params cpas_register_params;
+	int rc;
+
+	cpas_register_params.dev = &soc_info->pdev->dev;
+	memcpy(cpas_register_params.identifier, "jpeg-dma",
+		sizeof("jpeg-dma"));
+	cpas_register_params.cam_cpas_client_cb = NULL;
+	cpas_register_params.cell_index = hw_idx;
+	cpas_register_params.userdata = NULL;
+
+	rc = cam_cpas_register_client(&cpas_register_params);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "cpas_register failed: %d", rc);
+		return rc;
+	}
+	core_info->cpas_handle = cpas_register_params.client_handle;
+
+	return rc;
+}
+
+static int cam_jpeg_dma_unregister_cpas(
+	struct cam_jpeg_dma_device_core_info *core_info)
+{
+	int rc;
+
+	rc = cam_cpas_unregister_client(core_info->cpas_handle);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpas unregister failed: %d", rc);
+	core_info->cpas_handle = 0;
+
+	return rc;
+}
+
+static int cam_jpeg_dma_remove(struct platform_device *pdev)
+{
+	struct cam_hw_info *jpeg_dma_dev = NULL;
+	struct cam_hw_intf *jpeg_dma_dev_intf = NULL;
+	struct cam_jpeg_dma_device_core_info *core_info = NULL;
+	int rc;
+
+	jpeg_dma_dev_intf = platform_get_drvdata(pdev);
+	if (!jpeg_dma_dev_intf) {
+		CAM_ERR(CAM_JPEG, "error No data in pdev");
+		return -EINVAL;
+	}
+
+	jpeg_dma_dev = jpeg_dma_dev_intf->hw_priv;
+	if (!jpeg_dma_dev) {
+		CAM_ERR(CAM_JPEG, "error HW data is NULL");
+		rc = -ENODEV;
+		goto free_jpeg_hw_intf;
+	}
+
+	core_info = (struct cam_jpeg_dma_device_core_info *)
+		jpeg_dma_dev->core_info;
+	if (!core_info) {
+		CAM_ERR(CAM_JPEG, "error core data NULL");
+		goto deinit_soc;
+	}
+
+	rc = cam_jpeg_dma_unregister_cpas(core_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc);
+
+	kfree(core_info);
+
+deinit_soc:
+	rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc);
+
+	mutex_destroy(&jpeg_dma_dev->hw_mutex);
+	kfree(jpeg_dma_dev);
+
+free_jpeg_hw_intf:
+	kfree(jpeg_dma_dev_intf);
+	return rc;
+}
+
+static int cam_jpeg_dma_probe(struct platform_device *pdev)
+{
+	struct cam_hw_info *jpeg_dma_dev = NULL;
+	struct cam_hw_intf *jpeg_dma_dev_intf = NULL;
+	const struct of_device_id *match_dev = NULL;
+	struct cam_jpeg_dma_device_core_info *core_info = NULL;
+	struct cam_jpeg_dma_device_hw_info *hw_info = NULL;
+	int rc;
+
+	jpeg_dma_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
+	if (!jpeg_dma_dev_intf)
+		return -ENOMEM;
+
+	of_property_read_u32(pdev->dev.of_node,
+		"cell-index", &jpeg_dma_dev_intf->hw_idx);
+
+	jpeg_dma_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
+	if (!jpeg_dma_dev) {
+		rc = -ENOMEM;
+		goto error_alloc_dev;
+	}
+	jpeg_dma_dev->soc_info.pdev = pdev;
+	jpeg_dma_dev_intf->hw_priv = jpeg_dma_dev;
+	jpeg_dma_dev_intf->hw_ops.init = cam_jpeg_dma_init_hw;
+	jpeg_dma_dev_intf->hw_ops.deinit = cam_jpeg_dma_deinit_hw;
+	jpeg_dma_dev_intf->hw_ops.process_cmd = cam_jpeg_dma_process_cmd;
+	jpeg_dma_dev_intf->hw_type = CAM_JPEG_DEV_DMA;
+
+	platform_set_drvdata(pdev, jpeg_dma_dev_intf);
+	jpeg_dma_dev->core_info =
+		kzalloc(sizeof(struct cam_jpeg_dma_device_core_info),
+			GFP_KERNEL);
+	if (!jpeg_dma_dev->core_info) {
+		rc = -ENOMEM;
+		goto error_alloc_core;
+	}
+	core_info = (struct cam_jpeg_dma_device_core_info *)jpeg_dma_dev->
+		core_info;
+
+	match_dev = of_match_device(pdev->dev.driver->of_match_table,
+		&pdev->dev);
+	if (!match_dev) {
+		CAM_ERR(CAM_JPEG, " No jpeg_dma hardware info");
+		rc = -EINVAL;
+		goto error_match_dev;
+	}
+	hw_info = (struct cam_jpeg_dma_device_hw_info *)match_dev->data;
+	core_info->jpeg_dma_hw_info = hw_info;
+	core_info->core_state = CAM_JPEG_DMA_CORE_NOT_READY;
+
+	rc = cam_jpeg_dma_init_soc_resources(&jpeg_dma_dev->soc_info,
+		cam_jpeg_dma_irq,
+		jpeg_dma_dev);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "%failed to init_soc %d", rc);
+		goto error_match_dev;
+	}
+
+	rc = cam_jpeg_dma_register_cpas(&jpeg_dma_dev->soc_info,
+		core_info, jpeg_dma_dev_intf->hw_idx);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, " failed to reg cpas %d", rc);
+		goto error_reg_cpas;
+	}
+	jpeg_dma_dev->hw_state = CAM_HW_STATE_POWER_DOWN;
+	mutex_init(&jpeg_dma_dev->hw_mutex);
+	spin_lock_init(&jpeg_dma_dev->hw_lock);
+	init_completion(&jpeg_dma_dev->hw_complete);
+
+	CAM_DBG(CAM_JPEG, " hwidx %d", jpeg_dma_dev_intf->hw_idx);
+
+	return rc;
+
+error_reg_cpas:
+	rc = cam_soc_util_release_platform_resource(&jpeg_dma_dev->soc_info);
+error_match_dev:
+	kfree(jpeg_dma_dev->core_info);
+error_alloc_core:
+	kfree(jpeg_dma_dev);
+error_alloc_dev:
+	kfree(jpeg_dma_dev_intf);
+	return rc;
+}
+
+static const struct of_device_id cam_jpeg_dma_dt_match[] = {
+	{
+		.compatible = "qcom,cam_jpeg_dma",
+		.data = &cam_jpeg_dma_hw_info,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, cam_jpeg_dma_dt_match);
+
+static struct platform_driver cam_jpeg_dma_driver = {
+	.probe = cam_jpeg_dma_probe,
+	.remove = cam_jpeg_dma_remove,
+	.driver = {
+		.name = "cam-jpeg-dma",
+		.owner = THIS_MODULE,
+		.of_match_table = cam_jpeg_dma_dt_match,
+	},
+};
+
+static int __init cam_jpeg_dma_init_module(void)
+{
+	return platform_driver_register(&cam_jpeg_dma_driver);
+}
+
+static void __exit cam_jpeg_dma_exit_module(void)
+{
+	platform_driver_unregister(&cam_jpeg_dma_driver);
+}
+
+module_init(cam_jpeg_dma_init_module);
+module_exit(cam_jpeg_dma_exit_module);
+MODULE_DESCRIPTION("CAM JPEG_DMA driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c
new file mode 100644
index 0000000..efc161b
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.c
@@ -0,0 +1,63 @@
+/* Copyright (c) 2017, 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/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/dma-buf.h>
+#include <media/cam_defs.h>
+#include <media/cam_jpeg.h>
+
+#include "jpeg_dma_soc.h"
+#include "cam_soc_util.h"
+#include "cam_debug_util.h"
+
+int cam_jpeg_dma_init_soc_resources(struct cam_hw_soc_info *soc_info,
+	irq_handler_t jpeg_dma_irq_handler, void *irq_data)
+{
+	int rc;
+
+	rc = cam_soc_util_get_dt_properties(soc_info);
+	if (rc)
+		return rc;
+
+	rc = cam_soc_util_request_platform_resource(soc_info,
+		jpeg_dma_irq_handler,
+		irq_data);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "init soc failed %d", rc);
+
+	return rc;
+}
+
+int cam_jpeg_dma_enable_soc_resources(struct cam_hw_soc_info *soc_info)
+{
+	int rc;
+
+	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+		CAM_SVS_VOTE, true);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "enable platform failed %d", rc);
+
+	return rc;
+}
+
+int cam_jpeg_dma_disable_soc_resources(struct cam_hw_soc_info *soc_info)
+{
+	int rc;
+
+	rc = cam_soc_util_disable_platform_resource(soc_info, true, false);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "disable platform failed %d", rc);
+
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h
new file mode 100644
index 0000000..bc9bed8
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_soc.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2017, 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 _CAM_JPEG_DMA_SOC_H_
+#define _CAM_JPEG_DMA_SOC_H_
+
+#include "cam_soc_util.h"
+
+int cam_jpeg_dma_init_soc_resources(struct cam_hw_soc_info *soc_info,
+	irq_handler_t jpeg_dma_irq_handler, void *irq_data);
+
+int cam_jpeg_dma_enable_soc_resources(struct cam_hw_soc_info *soc_info);
+
+int cam_jpeg_dma_disable_soc_resources(struct cam_hw_soc_info *soc_info);
+
+#endif /* _CAM_JPEG_DMA_SOC_H_*/
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile
new file mode 100644
index 0000000..b046a7f
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/Makefile
@@ -0,0 +1,11 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_core
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_hw_mgr/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw
+
+obj-$(CONFIG_SPECTRA_CAMERA) += jpeg_enc_dev.o jpeg_enc_core.o jpeg_enc_soc.o
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
new file mode 100644
index 0000000..25405cf
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
@@ -0,0 +1,348 @@
+/* Copyright (c) 2017, 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/of.h>
+#include <linux/debugfs.h>
+#include <linux/videodev2.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+
+#include "cam_io_util.h"
+#include "cam_hw.h"
+#include "cam_hw_intf.h"
+#include "jpeg_enc_core.h"
+#include "jpeg_enc_soc.h"
+#include "cam_soc_util.h"
+#include "cam_io_util.h"
+#include "cam_enc_hw_intf.h"
+#include "cam_jpeg_hw_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_cpas_api.h"
+#include "cam_debug_util.h"
+
+#define CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK 0x00000001
+#define CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_SHIFT 0x00000000
+
+#define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK 0x10000000
+#define CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_SHIFT 0x0000000a
+
+#define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_MASK 0x00000800
+#define CAM_JPEG_HW_IRQ_STATUS_BUS_ERROR_SHIFT 0x0000000b
+
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF      (0x1<<19)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR     (0x1<<20)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR   (0x1<<21)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF (0x1<<22)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW    (0x1<<23)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM       (0x1<<24)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ   (0x1<<25)
+#define CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM       (0x1<<26)
+#define CAM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK        (0x1<<29)
+
+#define CAM_JPEG_HW_MASK_COMP_FRAMEDONE \
+		CAM_JPEG_HW_IRQ_STATUS_FRAMEDONE_MASK
+#define CAM_JPEG_HW_MASK_COMP_RESET_ACK \
+		CAM_JPEG_HW_IRQ_STATUS_RESET_ACK_MASK
+#define CAM_JPEG_HW_MASK_COMP_ERR \
+		(CAM_JPEG_HW_IRQ_STATUS_DCD_UNESCAPED_FF | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_HUFFMAN_ERROR | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_COEFFICIENT_ERR | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_BIT_STUFF | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_SCAN_UNDERFLOW | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_INVALID_RSM_SEQ | \
+		CAM_JPEG_HW_IRQ_STATUS_DCD_MISSING_RSM | \
+		CAM_JPEG_HW_IRQ_STATUS_VIOLATION_MASK)
+
+#define CAM_JPEG_HW_IRQ_IS_FRAME_DONE(jpeg_irq_status) \
+	(jpeg_irq_status & CAM_JPEG_HW_MASK_COMP_FRAMEDONE)
+#define CAM_JPEG_HW_IRQ_IS_RESET_ACK(jpeg_irq_status) \
+	(jpeg_irq_status & CAM_JPEG_HW_MASK_COMP_RESET_ACK)
+#define CAM_JPEG_HW_IRQ_IS_ERR(jpeg_irq_status) \
+	(jpeg_irq_status & CAM_JPEG_HW_MASK_COMP_ERR)
+
+#define CAM_JPEG_ENC_RESET_TIMEOUT msecs_to_jiffies(500)
+
+int cam_jpeg_enc_init_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = device_priv;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	struct cam_jpeg_cpas_vote cpas_vote;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid cam_dev_info");
+		return -EINVAL;
+	}
+
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info =
+		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+
+	if (!soc_info || !core_info) {
+		CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
+		return -EINVAL;
+	}
+
+	cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE;
+	cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE;
+	cpas_vote.axi_vote.compressed_bw = JPEG_TURBO_VOTE;
+	cpas_vote.axi_vote.uncompressed_bw = JPEG_TURBO_VOTE;
+
+	rc = cam_cpas_start(core_info->cpas_handle,
+		&cpas_vote.ahb_vote, &cpas_vote.axi_vote);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpass start failed: %d", rc);
+
+	rc = cam_jpeg_enc_enable_soc_resources(soc_info);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "soc enable is failed %d", rc);
+		cam_cpas_stop(core_info->cpas_handle);
+	}
+
+	return rc;
+}
+
+int cam_jpeg_enc_deinit_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = device_priv;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid cam_dev_info");
+		return -EINVAL;
+	}
+
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
+	if (!soc_info || !core_info) {
+		CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK",
+			soc_info, core_info);
+		return -EINVAL;
+	}
+
+	rc = cam_jpeg_enc_disable_soc_resources(soc_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "soc enable failed %d", rc);
+
+	rc = cam_cpas_stop(core_info->cpas_handle);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpas stop failed: %d", rc);
+
+	return 0;
+}
+
+irqreturn_t cam_jpeg_enc_irq(int irq_num, void *data)
+{
+	struct cam_hw_info *jpeg_enc_dev = data;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	uint32_t irq_status = 0;
+	uint32_t encoded_size = 0;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
+	void __iomem *mem_base;
+
+	if (!jpeg_enc_dev) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return IRQ_HANDLED;
+	}
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info =
+		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+	hw_info = core_info->jpeg_enc_hw_info;
+	mem_base = soc_info->reg_map[0].mem_base;
+
+	irq_status = cam_io_r_mb(mem_base +
+		core_info->jpeg_enc_hw_info->int_status);
+
+	cam_io_w_mb(irq_status,
+		soc_info->reg_map[0].mem_base +
+		core_info->jpeg_enc_hw_info->int_clr);
+
+	CAM_DBG(CAM_JPEG, "irq_num %d  irq_status = %x , core_state %d",
+		irq_num, irq_status, core_info->core_state);
+	if (CAM_JPEG_HW_IRQ_IS_FRAME_DONE(irq_status)) {
+		if (core_info->core_state == CAM_JPEG_ENC_CORE_READY) {
+			encoded_size = cam_io_r_mb(mem_base + 0x180);
+			if (core_info->irq_cb.jpeg_hw_mgr_cb) {
+				core_info->irq_cb.jpeg_hw_mgr_cb(irq_status,
+					encoded_size,
+					core_info->irq_cb.data);
+			} else {
+				CAM_ERR(CAM_JPEG, "unexpected done");
+			}
+		}
+
+		core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+	}
+	if (CAM_JPEG_HW_IRQ_IS_RESET_ACK(irq_status)) {
+		if (core_info->core_state == CAM_JPEG_ENC_CORE_RESETTING) {
+			core_info->core_state = CAM_JPEG_ENC_CORE_READY;
+			complete(&jpeg_enc_dev->hw_complete);
+		} else {
+			CAM_ERR(CAM_JPEG, "unexpected reset irq");
+		}
+	}
+	/* Unexpected/unintended HW interrupt */
+	if (CAM_JPEG_HW_IRQ_IS_ERR(irq_status)) {
+		core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+		CAM_ERR_RATE_LIMIT(CAM_JPEG,
+			"error irq_num %d  irq_status = %x , core_state %d",
+			irq_num, irq_status, core_info->core_state);
+
+		if (core_info->irq_cb.jpeg_hw_mgr_cb) {
+			core_info->irq_cb.jpeg_hw_mgr_cb(irq_status,
+				-1,
+				core_info->irq_cb.data);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+int cam_jpeg_enc_reset_hw(void *data,
+	void *start_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = data;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
+	void __iomem *mem_base;
+	unsigned long rem_jiffies;
+
+	if (!jpeg_enc_dev) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return -EINVAL;
+	}
+	/* maskdisable.clrirq.maskenable.resetcmd */
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info =
+		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+	hw_info = core_info->jpeg_enc_hw_info;
+	mem_base = soc_info->reg_map[0].mem_base;
+
+	if (core_info->core_state == CAM_JPEG_ENC_CORE_RESETTING) {
+		CAM_ERR(CAM_JPEG, "alrady resetting");
+		return 0;
+	}
+
+	reinit_completion(&jpeg_enc_dev->hw_complete);
+
+	core_info->core_state = CAM_JPEG_ENC_CORE_RESETTING;
+
+	cam_io_w_mb(0x00000000, mem_base + hw_info->int_mask);
+	cam_io_w_mb(0xFFFFFFFF, mem_base + hw_info->int_clr);
+	cam_io_w_mb(0xFFFFFFFF, mem_base + hw_info->int_mask);
+	cam_io_w_mb(0x00032093, mem_base + hw_info->reset_cmd);
+
+	rem_jiffies = wait_for_completion_timeout(&jpeg_enc_dev->hw_complete,
+		CAM_JPEG_ENC_RESET_TIMEOUT);
+	if (!rem_jiffies) {
+		CAM_ERR(CAM_JPEG, "error Reset Timeout");
+		core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+	}
+
+	return 0;
+}
+
+int cam_jpeg_enc_start_hw(void *data,
+	void *start_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = data;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	struct cam_hw_soc_info *soc_info = NULL;
+	struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
+	void __iomem *mem_base;
+
+	if (!jpeg_enc_dev) {
+		CAM_ERR(CAM_JPEG, "Invalid args");
+		return -EINVAL;
+	}
+
+	soc_info = &jpeg_enc_dev->soc_info;
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
+	hw_info = core_info->jpeg_enc_hw_info;
+	mem_base = soc_info->reg_map[0].mem_base;
+
+	if (core_info->core_state != CAM_JPEG_ENC_CORE_READY) {
+		CAM_ERR(CAM_JPEG, "Error not ready");
+		return -EINVAL;
+	}
+
+	cam_io_w_mb(0x00000001, mem_base + 0x00000010);
+
+	return 0;
+}
+
+int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
+	void *cmd_args, uint32_t arg_size)
+{
+	struct cam_hw_info *jpeg_enc_dev = device_priv;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	int rc;
+
+	if (!device_priv) {
+		CAM_ERR(CAM_JPEG, "Invalid arguments");
+		return -EINVAL;
+	}
+
+	if (cmd_type >= CAM_JPEG_ENC_CMD_MAX) {
+		CAM_ERR(CAM_JPEG, "Invalid command : %x", cmd_type);
+		return -EINVAL;
+	}
+
+	core_info =
+		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+
+	switch (cmd_type) {
+	case CAM_JPEG_ENC_CMD_SET_IRQ_CB:
+	{
+		struct cam_jpeg_set_irq_cb *irq_cb = cmd_args;
+
+		if (!cmd_args) {
+			CAM_ERR(CAM_JPEG, "cmd args NULL");
+			return -EINVAL;
+		}
+		if (irq_cb->b_set_cb) {
+			core_info->irq_cb.jpeg_hw_mgr_cb =
+				irq_cb->jpeg_hw_mgr_cb;
+			core_info->irq_cb.data = irq_cb->data;
+		} else {
+			core_info->irq_cb.jpeg_hw_mgr_cb = NULL;
+			core_info->irq_cb.data = NULL;
+		}
+		rc = 0;
+		break;
+	}
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	if (rc)
+		CAM_ERR(CAM_JPEG, "error cmdtype %d rc = %d", cmd_type, rc);
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h
new file mode 100644
index 0000000..6ae4cdc
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.h
@@ -0,0 +1,62 @@
+/* Copyright (c) 2017, 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 CAM_JPEG_ENC_CORE_H
+#define CAM_JPEG_ENC_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/dma-buf.h>
+
+struct cam_jpeg_enc_device_hw_info {
+	uint32_t hw_version;
+	uint32_t int_status;
+	uint32_t int_clr;
+	uint32_t int_mask;
+	uint32_t reset_cmd;
+};
+
+struct cam_jpeg_enc_set_irq_cb {
+	int32_t (*jpeg_hw_mgr_cb)(uint32_t irq_status,
+		int32_t result_size, void *data);
+	void *data;
+};
+
+enum cam_jpeg_enc_core_state {
+	CAM_JPEG_ENC_CORE_NOT_READY,
+	CAM_JPEG_ENC_CORE_READY,
+	CAM_JPEG_ENC_CORE_RESETTING,
+	CAM_JPEG_ENC_CORE_STATE_MAX,
+};
+
+struct cam_jpeg_enc_device_core_info {
+	enum cam_jpeg_enc_core_state core_state;
+	struct cam_jpeg_enc_device_hw_info *jpeg_enc_hw_info;
+	uint32_t cpas_handle;
+	struct cam_jpeg_enc_set_irq_cb irq_cb;
+};
+
+int cam_jpeg_enc_init_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size);
+int cam_jpeg_enc_deinit_hw(void *device_priv,
+	void *init_hw_args, uint32_t arg_size);
+int cam_jpeg_enc_start_hw(void *device_priv,
+	void *start_hw_args, uint32_t arg_size);
+int cam_jpeg_enc_reset_hw(void *device_priv,
+	void *reset_hw_args, uint32_t arg_size);
+int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
+	void *cmd_args, uint32_t arg_size);
+irqreturn_t cam_jpeg_enc_irq(int irq_num, void *data);
+
+#endif /* CAM_JPEG_ENC_CORE_H */
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c
new file mode 100644
index 0000000..5dd1e1f
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2017, 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/module.h>
+#include <linux/slab.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/timer.h>
+
+#include "jpeg_enc_core.h"
+#include "jpeg_enc_soc.h"
+#include "cam_hw.h"
+#include "cam_hw_intf.h"
+#include "cam_io_util.h"
+#include "cam_jpeg_hw_intf.h"
+#include "cam_jpeg_hw_mgr_intf.h"
+#include "cam_cpas_api.h"
+#include "cam_debug_util.h"
+
+static struct cam_jpeg_enc_device_hw_info cam_jpeg_enc_hw_info = {
+	.int_clr = 0x1c,
+	.int_status = 0x20,
+	.int_mask = 0x18,
+	.reset_cmd = 0x8,
+	.hw_version = 0x0,
+};
+EXPORT_SYMBOL(cam_jpeg_enc_hw_info);
+
+static int cam_jpeg_enc_register_cpas(struct cam_hw_soc_info *soc_info,
+	struct cam_jpeg_enc_device_core_info *core_info,
+	uint32_t hw_idx)
+{
+	struct cam_cpas_register_params cpas_register_params;
+	int rc;
+
+	cpas_register_params.dev = &soc_info->pdev->dev;
+	memcpy(cpas_register_params.identifier, "jpeg-enc",
+		sizeof("jpeg-enc"));
+	cpas_register_params.cam_cpas_client_cb = NULL;
+	cpas_register_params.cell_index = hw_idx;
+	cpas_register_params.userdata = NULL;
+
+	rc = cam_cpas_register_client(&cpas_register_params);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, "cpas_register failed: %d", rc);
+		return rc;
+	}
+	core_info->cpas_handle = cpas_register_params.client_handle;
+
+	return rc;
+}
+
+static int cam_jpeg_enc_unregister_cpas(
+	struct cam_jpeg_enc_device_core_info *core_info)
+{
+	int rc;
+
+	rc = cam_cpas_unregister_client(core_info->cpas_handle);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "cpas unregister failed: %d", rc);
+	core_info->cpas_handle = 0;
+
+	return rc;
+}
+
+static int cam_jpeg_enc_remove(struct platform_device *pdev)
+{
+	struct cam_hw_info *jpeg_enc_dev = NULL;
+	struct cam_hw_intf *jpeg_enc_dev_intf = NULL;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	int rc;
+
+	jpeg_enc_dev_intf = platform_get_drvdata(pdev);
+	if (!jpeg_enc_dev_intf) {
+		CAM_ERR(CAM_JPEG, "error No data in pdev");
+		return -EINVAL;
+	}
+
+	jpeg_enc_dev = jpeg_enc_dev_intf->hw_priv;
+	if (!jpeg_enc_dev) {
+		CAM_ERR(CAM_JPEG, "error HW data is NULL");
+		rc = -ENODEV;
+		goto free_jpeg_hw_intf;
+	}
+
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
+	if (!core_info) {
+		CAM_ERR(CAM_JPEG, "error core data NULL");
+		goto deinit_soc;
+	}
+
+	rc = cam_jpeg_enc_unregister_cpas(core_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, " unreg failed to reg cpas %d", rc);
+
+	kfree(core_info);
+
+deinit_soc:
+	rc = cam_soc_util_release_platform_resource(&jpeg_enc_dev->soc_info);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "Failed to deinit soc rc=%d", rc);
+
+	mutex_destroy(&jpeg_enc_dev->hw_mutex);
+	kfree(jpeg_enc_dev);
+
+free_jpeg_hw_intf:
+	kfree(jpeg_enc_dev_intf);
+	return rc;
+}
+
+static int cam_jpeg_enc_probe(struct platform_device *pdev)
+{
+	struct cam_hw_info *jpeg_enc_dev = NULL;
+	struct cam_hw_intf *jpeg_enc_dev_intf = NULL;
+	const struct of_device_id *match_dev = NULL;
+	struct cam_jpeg_enc_device_core_info *core_info = NULL;
+	struct cam_jpeg_enc_device_hw_info *hw_info = NULL;
+	int rc;
+
+	jpeg_enc_dev_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
+	if (!jpeg_enc_dev_intf)
+		return -ENOMEM;
+
+	of_property_read_u32(pdev->dev.of_node,
+		"cell-index", &jpeg_enc_dev_intf->hw_idx);
+
+	jpeg_enc_dev = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
+	if (!jpeg_enc_dev) {
+		rc = -ENOMEM;
+		goto error_alloc_dev;
+	}
+	jpeg_enc_dev->soc_info.pdev = pdev;
+	jpeg_enc_dev_intf->hw_priv = jpeg_enc_dev;
+	jpeg_enc_dev_intf->hw_ops.init = cam_jpeg_enc_init_hw;
+	jpeg_enc_dev_intf->hw_ops.deinit = cam_jpeg_enc_deinit_hw;
+	jpeg_enc_dev_intf->hw_ops.start = cam_jpeg_enc_start_hw;
+	jpeg_enc_dev_intf->hw_ops.reset = cam_jpeg_enc_reset_hw;
+	jpeg_enc_dev_intf->hw_ops.process_cmd = cam_jpeg_enc_process_cmd;
+	jpeg_enc_dev_intf->hw_type = CAM_JPEG_DEV_ENC;
+
+	platform_set_drvdata(pdev, jpeg_enc_dev_intf);
+	jpeg_enc_dev->core_info =
+		kzalloc(sizeof(struct cam_jpeg_enc_device_core_info),
+			GFP_KERNEL);
+	if (!jpeg_enc_dev->core_info) {
+		rc = -ENOMEM;
+		goto error_alloc_core;
+	}
+	core_info = (struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
+		core_info;
+
+	match_dev = of_match_device(pdev->dev.driver->of_match_table,
+		&pdev->dev);
+	if (!match_dev) {
+		CAM_ERR(CAM_JPEG, " No jpeg_enc hardware info");
+		rc = -EINVAL;
+		goto error_match_dev;
+	}
+	hw_info = (struct cam_jpeg_enc_device_hw_info *)match_dev->data;
+	core_info->jpeg_enc_hw_info = hw_info;
+	core_info->core_state = CAM_JPEG_ENC_CORE_NOT_READY;
+
+	rc = cam_jpeg_enc_init_soc_resources(&jpeg_enc_dev->soc_info,
+		cam_jpeg_enc_irq,
+		jpeg_enc_dev);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, " failed to init_soc %d", rc);
+		goto error_match_dev;
+	}
+
+	rc = cam_jpeg_enc_register_cpas(&jpeg_enc_dev->soc_info,
+		core_info, jpeg_enc_dev_intf->hw_idx);
+	if (rc) {
+		CAM_ERR(CAM_JPEG, " failed to reg cpas %d", rc);
+		goto error_reg_cpas;
+	}
+	jpeg_enc_dev->hw_state = CAM_HW_STATE_POWER_DOWN;
+	mutex_init(&jpeg_enc_dev->hw_mutex);
+	spin_lock_init(&jpeg_enc_dev->hw_lock);
+	init_completion(&jpeg_enc_dev->hw_complete);
+
+	return rc;
+
+error_reg_cpas:
+	cam_soc_util_release_platform_resource(&jpeg_enc_dev->soc_info);
+error_match_dev:
+	kfree(jpeg_enc_dev->core_info);
+error_alloc_core:
+	kfree(jpeg_enc_dev);
+error_alloc_dev:
+	kfree(jpeg_enc_dev_intf);
+
+	return rc;
+}
+
+static const struct of_device_id cam_jpeg_enc_dt_match[] = {
+	{
+		.compatible = "qcom,cam_jpeg_enc",
+		.data = &cam_jpeg_enc_hw_info,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, cam_jpeg_enc_dt_match);
+
+static struct platform_driver cam_jpeg_enc_driver = {
+	.probe = cam_jpeg_enc_probe,
+	.remove = cam_jpeg_enc_remove,
+	.driver = {
+		.name = "cam-jpeg-enc",
+		.owner = THIS_MODULE,
+		.of_match_table = cam_jpeg_enc_dt_match,
+	},
+};
+
+static int __init cam_jpeg_enc_init_module(void)
+{
+	return platform_driver_register(&cam_jpeg_enc_driver);
+}
+
+static void __exit cam_jpeg_enc_exit_module(void)
+{
+	platform_driver_unregister(&cam_jpeg_enc_driver);
+}
+
+module_init(cam_jpeg_enc_init_module);
+module_exit(cam_jpeg_enc_exit_module);
+MODULE_DESCRIPTION("CAM JPEG_ENC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c
new file mode 100644
index 0000000..3f450cd
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.c
@@ -0,0 +1,63 @@
+/* Copyright (c) 2017, 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/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/dma-buf.h>
+#include <media/cam_defs.h>
+#include <media/cam_jpeg.h>
+
+#include "jpeg_enc_soc.h"
+#include "cam_soc_util.h"
+#include "cam_debug_util.h"
+
+int cam_jpeg_enc_init_soc_resources(struct cam_hw_soc_info *soc_info,
+	irq_handler_t jpeg_enc_irq_handler, void *irq_data)
+{
+	int rc;
+
+	rc = cam_soc_util_get_dt_properties(soc_info);
+	if (rc)
+		return rc;
+
+	rc = cam_soc_util_request_platform_resource(soc_info,
+		jpeg_enc_irq_handler,
+		irq_data);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "init soc failed %d", rc);
+
+	return rc;
+}
+
+int cam_jpeg_enc_enable_soc_resources(struct cam_hw_soc_info *soc_info)
+{
+	int rc;
+
+	rc = cam_soc_util_enable_platform_resource(soc_info, true,
+		CAM_SVS_VOTE, true);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "enable platform failed %d", rc);
+
+	return rc;
+}
+
+int cam_jpeg_enc_disable_soc_resources(struct cam_hw_soc_info *soc_info)
+{
+	int rc;
+
+	rc = cam_soc_util_disable_platform_resource(soc_info, true, false);
+	if (rc)
+		CAM_ERR(CAM_JPEG, "disable platform failed %d", rc);
+
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h
new file mode 100644
index 0000000..a0485a2
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_soc.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2017, 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 _CAM_JPEG_ENC_SOC_H_
+#define _CAM_JPEG_ENC_SOC_H_
+
+#include "cam_soc_util.h"
+
+int cam_jpeg_enc_init_soc_resources(struct cam_hw_soc_info *soc_info,
+	irq_handler_t jpeg_enc_irq_handler, void *irq_data);
+
+int cam_jpeg_enc_enable_soc_resources(struct cam_hw_soc_info *soc_info);
+
+int cam_jpeg_enc_disable_soc_resources(struct cam_hw_soc_info *soc_info);
+
+#endif /* _CAM_JPEG_ENC_SOC_H_*/