[PATCH 11/30] v4l: vxd-dec: Add TALMMU module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Sidraya <sidraya.bj@xxxxxxxxxxxxxxxxxxx>

It contains the implementation of Address allocation management
APIs, list processing primitives, generic resource allocations,
self scaling has tables and object pool memory allocator which
are needed for TALMMU functionality

Signed-off-by: Lakshmi Sankar <lakshmisankar-t@xxxxxx>
Signed-off-by: Sidraya <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
---
 MAINTAINERS                                   |  10 +
 drivers/staging/media/vxd/common/addr_alloc.c | 499 +++++++++
 drivers/staging/media/vxd/common/addr_alloc.h | 238 +++++
 drivers/staging/media/vxd/common/hash.c       | 481 +++++++++
 drivers/staging/media/vxd/common/hash.h       |  86 ++
 drivers/staging/media/vxd/common/pool.c       | 228 ++++
 drivers/staging/media/vxd/common/pool.h       |  66 ++
 drivers/staging/media/vxd/common/ra.c         | 972 ++++++++++++++++++
 drivers/staging/media/vxd/common/ra.h         | 200 ++++
 drivers/staging/media/vxd/common/talmmu_api.c | 753 ++++++++++++++
 drivers/staging/media/vxd/common/talmmu_api.h | 246 +++++
 11 files changed, 3779 insertions(+)
 create mode 100644 drivers/staging/media/vxd/common/addr_alloc.c
 create mode 100644 drivers/staging/media/vxd/common/addr_alloc.h
 create mode 100644 drivers/staging/media/vxd/common/hash.c
 create mode 100644 drivers/staging/media/vxd/common/hash.h
 create mode 100644 drivers/staging/media/vxd/common/pool.c
 create mode 100644 drivers/staging/media/vxd/common/pool.h
 create mode 100644 drivers/staging/media/vxd/common/ra.c
 create mode 100644 drivers/staging/media/vxd/common/ra.h
 create mode 100644 drivers/staging/media/vxd/common/talmmu_api.c
 create mode 100644 drivers/staging/media/vxd/common/talmmu_api.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 2668eeb89a34..2b0d0708d852 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19537,8 +19537,12 @@ M:	Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
 L:	linux-media@xxxxxxxxxxxxxxx
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/img,d5520-vxd.yaml
+F:	drivers/staging/media/vxd/common/addr_alloc.c
+F:	drivers/staging/media/vxd/common/addr_alloc.h
 F:	drivers/staging/media/vxd/common/dq.c
 F:	drivers/staging/media/vxd/common/dq.h
+F:	drivers/staging/media/vxd/common/hash.c
+F:	drivers/staging/media/vxd/common/hash.h
 F:	drivers/staging/media/vxd/common/idgen_api.c
 F:	drivers/staging/media/vxd/common/idgen_api.h
 F:	drivers/staging/media/vxd/common/img_mem_man.c
@@ -19548,6 +19552,12 @@ F:	drivers/staging/media/vxd/common/imgmmu.c
 F:	drivers/staging/media/vxd/common/imgmmu.h
 F:	drivers/staging/media/vxd/common/lst.c
 F:	drivers/staging/media/vxd/common/lst.h
+F:	drivers/staging/media/vxd/common/pool.c
+F:	drivers/staging/media/vxd/common/pool.h
+F:	drivers/staging/media/vxd/common/ra.c
+F:	drivers/staging/media/vxd/common/ra.h
+F:	drivers/staging/media/vxd/common/talmmu_api.c
+F:	drivers/staging/media/vxd/common/talmmu_api.h
 F:	drivers/staging/media/vxd/common/work_queue.c
 F:	drivers/staging/media/vxd/common/work_queue.h
 F:	drivers/staging/media/vxd/decoder/hw_control.c
diff --git a/drivers/staging/media/vxd/common/addr_alloc.c b/drivers/staging/media/vxd/common/addr_alloc.c
new file mode 100644
index 000000000000..393d309b2c0c
--- /dev/null
+++ b/drivers/staging/media/vxd/common/addr_alloc.c
@@ -0,0 +1,499 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Address allocation APIs - used to manage address allocation
+ * with a number of predefined regions.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@xxxxxx>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
+ */
+
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "addr_alloc.h"
+#include "hash.h"
+#include "img_errors.h"
+
+/* Global context. */
+static struct addr_context global_ctx = {0};
+/* Sub-system initialized. */
+static int global_initialized;
+/* Count of contexts. */
+static unsigned int num_ctx;
+/* Global mutex */
+static struct mutex *global_lock;
+
+/**
+ * addr_initialise - addr_initialise
+ */
+
+int addr_initialise(void)
+{
+	unsigned int result = IMG_ERROR_ALREADY_INITIALISED;
+
+	/* If we are not initialized */
+	if (!global_initialized)
+		result = addr_cx_initialise(&global_ctx);
+	return result;
+}
+
+int addr_cx_initialise(struct addr_context * const context)
+{
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!context)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (!global_initialized) {
+		/* Initialise context */
+		memset(context, 0x00, sizeof(struct addr_context));
+
+		/* If no mutex associated with this resource */
+		if (!global_lock) {
+			/* Create one */
+
+			global_lock = kzalloc(sizeof(*global_lock), GFP_KERNEL);
+			if (!global_lock)
+				return -ENOMEM;
+
+			mutex_init(global_lock);
+		}
+
+		mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+		/* Initialise the hash functions. */
+		result = vid_hash_initialise();
+		if (result != IMG_SUCCESS) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		/* Initialise the arena functions */
+		result = vid_ra_initialise();
+		if (result != IMG_SUCCESS) {
+			mutex_unlock(global_lock);
+			result = vid_hash_finalise();
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		/* We are now initialized */
+		global_initialized = TRUE;
+		result = IMG_SUCCESS;
+	} else {
+		mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+	}
+
+	num_ctx++;
+	mutex_unlock(global_lock);
+
+	return result;
+}
+
+int addr_deinitialise(void)
+{
+	return addr_cx_deinitialise(&global_ctx);
+}
+
+int addr_cx_deinitialise(struct addr_context * const context)
+{
+	struct addr_region *tmp_region = NULL;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!context)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (global_initialized) {
+		mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+		tmp_region = context->regions;
+
+		/* Delete all arena structure */
+		if (context->default_region)
+			result = vid_ra_delete(context->default_region->arena);
+
+		while (tmp_region) {
+			result = vid_ra_delete(tmp_region->arena);
+			tmp_region = tmp_region->nxt_region;
+		}
+
+		if (num_ctx != 0)
+			num_ctx--;
+
+		result = IMG_SUCCESS;
+		if (num_ctx == 0) {
+			/* Free off resources */
+			result = vid_hash_finalise();
+			result = vid_ra_deinit();
+			global_initialized = FALSE;
+
+			mutex_unlock(global_lock);
+			mutex_destroy(global_lock);
+			kfree(global_lock);
+			global_lock = NULL;
+		} else {
+			mutex_unlock(global_lock);
+		}
+	}
+
+	return result;
+}
+
+int addr_define_mem_region(struct addr_region * const region)
+{
+	return addr_cx_define_mem_region(&global_ctx, region);
+}
+
+int addr_cx_define_mem_region(struct addr_context * const context,
+			      struct addr_region * const region)
+{
+	struct addr_region *tmp_region = NULL;
+	unsigned int result = IMG_SUCCESS;
+
+	if (!context || !region)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+	tmp_region = context->regions;
+
+	/* Ensure the link to the next is NULL */
+	region->nxt_region = NULL;
+
+	/* If this is the default memory region */
+	if (!region->name) {
+		/* Should not previously have been defined */
+		if (context->default_region) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		context->default_region = region;
+		context->no_regions++;
+
+		/*
+		 * Create an arena for memory allocation
+		 * name of resource arena for debug
+		 * start of resource
+		 * size of resource
+		 * allocation quantum
+		 * import allocator
+		 * import deallocator
+		 * import handle
+		 */
+		result = vid_ra_create("memory",
+				       region->base_addr,
+				       region->size,
+				       1,
+				       NULL,
+				       NULL,
+				       NULL,
+				       &region->arena);
+
+		if (result != IMG_SUCCESS) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+	} else {
+		/*
+		 * Run down the list of existing named regions
+		 * to check if there is a region with this name
+		 */
+		while (tmp_region &&
+		       (strcmp(region->name, tmp_region->name) != 0) &&
+		       tmp_region->nxt_region) {
+			tmp_region = tmp_region->nxt_region;
+		}
+
+		/* If we have items in the list */
+		if (tmp_region) {
+			/*
+			 * Check we didn't stop because the name
+			 * clashes with one already defined.
+			 */
+
+			if (strcmp(region->name, tmp_region->name) == 0 ||
+			    tmp_region->nxt_region) {
+				mutex_unlock(global_lock);
+				return IMG_ERROR_UNEXPECTED_STATE;
+			}
+
+			/* Add to end of list */
+			tmp_region->nxt_region = region;
+		} else {
+			/* Add to head of list */
+			context->regions = region;
+		}
+
+		context->no_regions++;
+
+		/*
+		 * Create an arena for memory allocation
+		 * name of resource arena for debug
+		 * start of resource
+		 * size of resource
+		 * allocation quantum
+		 * import allocator
+		 * import deallocator
+		 * import handle
+		 */
+		result = vid_ra_create(region->name,
+				       region->base_addr,
+				       region->size,
+				       1,
+				       NULL,
+				       NULL,
+				       NULL,
+				       &region->arena);
+
+		if (result != IMG_SUCCESS) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+	}
+
+	mutex_unlock(global_lock);
+
+	/* Check the arean was created OK */
+	if (!region->arena)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	return result;
+}
+
+int addr_malloc(const unsigned char * const name,
+		unsigned long long size,
+		unsigned long long * const base_adr)
+{
+	return addr_cx_malloc(&global_ctx, name, size, base_adr);
+}
+
+int addr_cx_malloc(struct addr_context * const context,
+		   const unsigned char * const name,
+		   unsigned long long size,
+		   unsigned long long * const base_adr)
+{
+	unsigned int result = IMG_ERROR_FATAL;
+	struct addr_region *tmp_region = NULL;
+
+	if (!context || !base_adr || !name)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	*(base_adr) = (unsigned long long)-1LL;
+
+	mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+	tmp_region = context->regions;
+
+	/*
+	 * Run down the list of existing named
+	 * regions to locate this
+	 */
+	while (tmp_region && (strcmp(name, tmp_region->name) != 0) && (tmp_region->nxt_region))
+		tmp_region = tmp_region->nxt_region;
+
+	/* If there was no match. */
+	if (!tmp_region || (strcmp(name, tmp_region->name) != 0)) {
+		/* Use the default */
+		if (!context->default_region) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		tmp_region = context->default_region;
+	}
+
+	if (!tmp_region) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_UNEXPECTED_STATE;
+	}
+
+	/* Allocate size + guard band */
+	result = vid_ra_alloc(tmp_region->arena,
+			      size + tmp_region->guard_band,
+			      NULL,
+			      NULL,
+			      SEQUENTIAL_ALLOCATION,
+			      1,
+			      base_adr);
+	if (result != IMG_SUCCESS) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	mutex_unlock(global_lock);
+
+	return result;
+}
+
+int addr_cx_malloc_res(struct addr_context * const context,
+		       const unsigned char * const name,
+		       unsigned long long size,
+		       unsigned long long * const base_adr)
+{
+	unsigned int result = IMG_ERROR_FATAL;
+	struct addr_region *tmp_region = NULL;
+
+	if (!context || !base_adr || !name)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+	tmp_region = context->regions;
+	/* If the allocation is for the default region */
+	/*
+	 * Run down the list of existing named
+	 * regions to locate this
+	 */
+	while (tmp_region && (strcmp(name, tmp_region->name) != 0) && (tmp_region->nxt_region))
+		tmp_region = tmp_region->nxt_region;
+
+	/* If there was no match. */
+	if (!tmp_region || (strcmp(name, tmp_region->name) != 0)) {
+		/* Use the default */
+		if (!context->default_region) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+		tmp_region = context->default_region;
+	}
+	if (!tmp_region) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_UNEXPECTED_STATE;
+	}
+	/* Allocate size + guard band */
+	result = vid_ra_alloc(tmp_region->arena, size + tmp_region->guard_band,
+			      NULL, NULL, SEQUENTIAL_ALLOCATION, 1, base_adr);
+	if (result != IMG_SUCCESS) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+	mutex_unlock(global_lock);
+
+	return result;
+}
+
+int addr_cx_malloc_align_res(struct addr_context * const context,
+			     const unsigned char * const name,
+			     unsigned long long size,
+			     unsigned long long alignment,
+			     unsigned long long * const base_adr)
+{
+	unsigned int result;
+	struct addr_region *tmp_region = NULL;
+
+	if (!context || !base_adr || !name)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+	tmp_region = context->regions;
+
+	/*
+	 * Run down the list of existing named
+	 * regions to locate this
+	 */
+	while (tmp_region &&
+	       (strcmp(name, tmp_region->name) != 0) &&
+	       (tmp_region->nxt_region)) {
+		tmp_region = tmp_region->nxt_region;
+	}
+	/* If there was no match. */
+	if (!tmp_region ||
+	    (strcmp(name, tmp_region->name) != 0)) {
+		/* Use the default */
+		if (!context->default_region) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		tmp_region = context->default_region;
+	}
+
+	if (!tmp_region) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_UNEXPECTED_STATE;
+	}
+	/* Allocate size + guard band */
+	result = vid_ra_alloc(tmp_region->arena,
+			      size + tmp_region->guard_band,
+			      NULL,
+			      NULL,
+			      SEQUENTIAL_ALLOCATION,
+			      alignment,
+			      base_adr);
+	if (result != IMG_SUCCESS) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	mutex_unlock(global_lock);
+
+	return result;
+}
+
+int addr_free(const unsigned char * const name, unsigned long long addr)
+{
+	return addr_cx_free(&global_ctx, name, addr);
+}
+
+int addr_cx_free(struct addr_context * const context,
+		 const unsigned char * const name,
+		 unsigned long long addr)
+{
+	struct addr_region *tmp_region;
+	unsigned int result;
+
+	if (!context)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	tmp_region = context->regions;
+
+	mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+	/* If the allocation is for the default region */
+	if (!name) {
+		if (!context->default_region) {
+			result = IMG_ERROR_INVALID_PARAMETERS;
+			goto error;
+		}
+		tmp_region = context->default_region;
+	} else {
+		/*
+		 * Run down the list of existing named
+		 * regions to locate this
+		 */
+		while (tmp_region &&
+		       (strcmp(name, tmp_region->name) != 0) &&
+		       tmp_region->nxt_region) {
+			tmp_region = tmp_region->nxt_region;
+		}
+
+		/* If there was no match */
+		if (!tmp_region || (strcmp(name, tmp_region->name) != 0)) {
+			/* Use the default */
+			if (!context->default_region) {
+				result = IMG_ERROR_INVALID_PARAMETERS;
+				goto error;
+			}
+			tmp_region = context->default_region;
+		}
+	}
+
+	/* Free the address */
+	result = vid_ra_free(tmp_region->arena, addr);
+
+error:
+	mutex_unlock(global_lock);
+	return result;
+}
diff --git a/drivers/staging/media/vxd/common/addr_alloc.h b/drivers/staging/media/vxd/common/addr_alloc.h
new file mode 100644
index 000000000000..387418b124e4
--- /dev/null
+++ b/drivers/staging/media/vxd/common/addr_alloc.h
@@ -0,0 +1,238 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Address allocation management API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@xxxxxx>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
+ */
+#ifndef __ADDR_ALLOC_H__
+#define __ADDR_ALLOC_H__
+
+#include <linux/types.h>
+#include "ra.h"
+
+/* Defines whether sequential or random allocation is used */
+enum {
+	SEQUENTIAL_ALLOCATION,
+	RANDOM_ALLOCATION,
+	RANDOM_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/**
+ * struct addr_region - Memory region structure
+ *@name: A pointer to a sring containing the name of the region.
+ *		NULL for the default memory region.
+ *@base_addr: The base address of the memory region.
+ *@size: The size of the memory region.
+ *@guard_band: The size of any guard band to be used.
+ *		Guard bands can be useful in separating block allocations
+ *		and allows the caller to detect erroneous accesses
+ *		into these areas.
+ *@nxt_region:Used internally by the ADDR API.A pointer used to point
+ *		to the next memory region.
+ *@arena: Used internally by the ADDR API. A to a structure used to
+ *		maintain and perform address allocation.
+ *
+ * This structure contains information about the memory region.
+ */
+struct addr_region {
+	unsigned char *name;
+	unsigned long long base_addr;
+	unsigned long long size;
+	unsigned int guard_band;
+	struct addr_region *nxt_region;
+	void *arena;
+};
+
+/*
+ * This structure contains the context for allocation.
+ *@regions: Pointer the first region in the list.
+ *@default_region: Pointer the default region.
+ *@no_regions: Number of regions currently available (including default)
+ */
+struct addr_context {
+	struct addr_region *regions;
+	struct addr_region *default_region;
+	unsigned int no_regions;
+};
+
+/*
+ * @Function	ADDR_Initialise
+ * @Description
+ * This function is used to initialise the address alocation sub-system.
+ * NOTE: This function may be called multiple times. The initialisation only
+ * happens the first time it is called.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_initialise(void);
+
+/*
+ * @Function	addr_deinitialise
+ * @Description
+ * This function is used to de-initialise the address alocation sub-system.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_deinitialise(void);
+
+/*
+ * @Function	addr_define_mem_region
+ * @Description
+ * This function is used define a memory region.
+ * NOTE: The region structure MUST be defined in static memory as this
+ * is retained and used by the ADDR sub-system.
+ * NOTE: Invalid parameters are trapped by asserts.
+ * @Input	region: A pointer to a region structure.
+ * @Return	IMG_RESULT  : IMG_SUCCESS or an error code.
+ */
+int addr_define_mem_region(struct addr_region * const region);
+
+/*
+ * @Function	addr_malloc
+ * @Description
+ * This function is used allocate space within a memory region.
+ * NOTE: Allocation failures or invalid parameters are trapped by asserts.
+ * @Input	name: Is a pointer the name of the memory region.
+ *		NULL can be used to allocate space from the
+ *		default memory region.
+ * @Input	size: The size (in bytes) of the allocation.
+ * @Output	base_adr : The address of the allocated space.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_malloc(const unsigned char *const name,
+		unsigned long long size,
+		unsigned long long *const base_adr);
+
+/*
+ * @Function	addr_free
+ * @Description
+ * This function is used free a previously allocate space within
+ * a memory region.
+ * NOTE: Invalid parameters are trapped by asserts.
+ * @Input	name: Is a pointer to the name of the memory region.
+ *		NULL is used to free space from the default memory region.
+ *@Input	addr: The address allocated.
+ *@Return	IMG_SUCCESS or an error code.
+ */
+int addr_free(const unsigned char * const name, unsigned long long addr);
+
+/*
+ * @Function	addr_cx_initialise
+ * @Description
+ * This function is used to initialise the address allocation sub-system with
+ * an external context structure.
+ * NOTE: This function should be call only once for the context.
+ * @Input	context : Pointer to context structure.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_initialise(struct addr_context * const context);
+
+/*
+ * @Function	addr_cx_deinitialise
+ * @Description
+ * This function is used to de-initialise the address allocation
+ * sub-system with an external context structure.
+ * @Input	context : Pointer to context structure.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_deinitialise(struct addr_context * const context);
+
+/*
+ * @Function	addr_cx_define_mem_region
+ * @Description
+ * This function is used define a memory region with an external
+ * context structure.
+ * NOTE: The region structure MUST be defined in static memory as this
+ * is retained and used by the ADDR sub-system.
+ * NOTE: Invalid parameters are trapped by asserts.
+ * @Input	context : Pointer to context structure.
+ * @Input	region : A pointer to a region structure.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_define_mem_region(struct addr_context *const context,
+			      struct addr_region *const region);
+
+/*
+ * @Function	addr_cx_malloc
+ * @Description
+ * This function is used allocate space within a memory region with
+ * an external context structure.
+ * NOTE: Allocation failures or invalid parameters are trapped by asserts.
+ * @Input	context : Pointer to context structure.
+ * @Input	name : Is a pointer the name of the memory region.
+ *		NULL can be used to allocate space from the
+ *		default memory region.
+ * @Input	size : The size (in bytes) of the allocation.
+ * @Output	base_adr : The address of the allocated space.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_malloc(struct addr_context * const context,
+		   const unsigned char *const name,
+		   unsigned long long size,
+		   unsigned long long *const base_adr);
+
+/*
+ * @Function	addr_cx_malloc_res
+ * @Description
+ * This function is used allocate space within a memory region with
+ * an external context structure.
+ * NOTE: Allocation failures are returned in IMG_RESULT, however invalid
+ * parameters are trapped by asserts.
+ * @Input	context : Pointer to context structure.
+ * @Input	name : Is a pointer the name of the memory region.
+ *		NULL can be used to allocate space from the
+ *		default memory region.
+ * @Input	size : The size (in bytes) of the allocation.
+ * @Input	base_adr : Pointer to the address of the allocated space.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_malloc_res(struct addr_context *const context,
+		       const unsigned char *const name,
+		       unsigned long long size,
+		       unsigned long long * const base_adr);
+
+/*
+ * @Function	addr_cx_malloc1_res
+ * @Description
+ * This function is used allocate space within a memory region with
+ * an external context structure.
+ * NOTE: Allocation failures are returned in IMG_RESULT, however invalid
+ * parameters are trapped by asserts.
+ * @Input	context : Pointer to context structure.
+ * @Input	name : Is a pointer the name of the memory region.
+ *		NULL can be used to allocate space from the
+ *		default memory region.
+ * @Input	size	: The size (in bytes) of the allocation.
+ * @Input	alignment : The required byte alignment (1, 2, 4, 8, 16 etc).
+ * @Input	base_adr : Pointer to the address of the allocated space.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_malloc_align_res(struct addr_context *const context,
+			     const unsigned char *const name,
+			     unsigned long long size,
+			     unsigned long long alignment,
+			     unsigned long long *const base_adr);
+
+/*
+ * @Function	addr_cx_free
+ * @Description
+ * This function is used free a previously allocate space within a memory region
+ * with an external context structure.
+ * NOTE: Invalid parameters are trapped by asserts.
+ * @Input	context : Pointer to context structure.
+ * @Input	name : Is a pointer the name of the memory region.
+ *		NULL is used to free space from the
+ *		default memory region.
+ * @Input	addr : The address allocated.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_free(struct addr_context *const context,
+		 const unsigned char *const name,
+		 unsigned long long addr);
+
+#endif /* __ADDR_ALLOC_H__	*/
diff --git a/drivers/staging/media/vxd/common/hash.c b/drivers/staging/media/vxd/common/hash.c
new file mode 100644
index 000000000000..1a03aecc34ef
--- /dev/null
+++ b/drivers/staging/media/vxd/common/hash.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Self scaling hash tables.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@xxxxxx>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "hash.h"
+#include "img_errors.h"
+#include "pool.h"
+
+/* pool of struct hash objects */
+static struct pool *global_hashpool;
+
+/* pool of struct bucket objects */
+static struct pool *global_bucketpool;
+
+static int global_initialized;
+
+/* Each entry in a hash table is placed into a bucket */
+struct bucket {
+	struct bucket *next;
+	unsigned long long key;
+	unsigned long long value;
+};
+
+struct hash {
+	struct bucket **table;
+	unsigned int size;
+	unsigned int count;
+	unsigned int minimum_size;
+};
+
+/**
+ * hash_func - Hash function intended for hashing addresses.
+ * @vale : The key to hash.
+ * @size : The size of the hash table
+ */
+static unsigned int hash_func(unsigned long long vale,
+			      unsigned int size)
+{
+	unsigned int hash = (unsigned int)(vale);
+
+	hash += (hash << 12);
+	hash ^= (hash >> 22);
+	hash += (hash << 4);
+	hash ^= (hash >> 9);
+	hash += (hash << 10);
+	hash ^= (hash >> 2);
+	hash += (hash << 7);
+	hash ^= (hash >> 12);
+	hash &= (size - 1);
+	return hash;
+}
+
+/*
+ * @Function	hash_chain_insert
+ * @Description
+ * Hash function intended for hashing addresses.
+ * @Input	bucket : The bucket
+ * @Input	table : The hash table
+ * @Input	size : The size of the hash table
+ * @Return	IMG_SUCCESS or an error code.
+ */
+static int hash_chain_insert(struct bucket *bucket,
+			     struct bucket **table,
+			     unsigned int size)
+{
+	unsigned int idx;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!bucket || !table || !size) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	idx = hash_func(bucket->key, size);
+
+	if (idx < size) {
+		result = IMG_SUCCESS;
+		bucket->next = table[idx];
+		table[idx] = bucket;
+	}
+
+	return result;
+}
+
+/*
+ * @Function	hash_rehash
+ * @Description
+ * Iterate over every entry in an old hash table and rehash into the new table.
+ * @Input	old_table : The old hash table
+ * @Input	old_size : The size of the old hash table
+ * @Input	new_table : The new hash table
+ * @Input	new_sz : The size of the new hash table
+ * @Return	IMG_SUCCESS or an error code.
+ */
+static int hash_rehash(struct bucket **old_table,
+		       unsigned int old_size,
+		       struct bucket **new_table,
+		       unsigned int new_sz)
+{
+	unsigned int idx;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!old_table || !new_table) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	for (idx = 0; idx < old_size; idx++) {
+		struct bucket *bucket;
+		struct bucket *nex_bucket;
+
+		bucket = old_table[idx];
+		while (bucket) {
+			nex_bucket = bucket->next;
+			result = hash_chain_insert(bucket, new_table, new_sz);
+			if (result != IMG_SUCCESS) {
+				result = IMG_ERROR_UNEXPECTED_STATE;
+				return result;
+			}
+			bucket = nex_bucket;
+		}
+	}
+	result = IMG_SUCCESS;
+
+	return result;
+}
+
+/*
+ * @Function	hash_resize
+ * @Description
+ * Attempt to resize a hash table, failure to allocate a new larger hash table
+ * is not considered a hard failure. We simply continue and allow the table to
+ * fill up, the effect is to allow hash chains to become longer.
+ * @Input	hash_arg : Pointer to the hash table
+ * @Input	new_sz : The size of the new hash table
+ * @Return	IMG_SUCCESS or an error code.
+ */
+static int hash_resize(struct hash *hash_arg,
+		       unsigned int new_sz)
+{
+	unsigned int malloc_sz = 0;
+	unsigned int result = IMG_ERROR_FATAL;
+	unsigned int idx;
+
+	if (!hash_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	if (new_sz != hash_arg->size) {
+		struct bucket **new_bkt_table;
+
+		malloc_sz = (sizeof(struct bucket *) * new_sz);
+		new_bkt_table = kmalloc(malloc_sz, GFP_KERNEL);
+
+		if (!new_bkt_table) {
+			result = IMG_ERROR_MALLOC_FAILED;
+			return result;
+		}
+
+		for (idx = 0; idx < new_sz; idx++)
+			new_bkt_table[idx] = NULL;
+
+		result = hash_rehash(hash_arg->table,
+				     hash_arg->size,
+				     new_bkt_table,
+				     new_sz);
+
+		if (result != IMG_SUCCESS) {
+			kfree(new_bkt_table);
+			new_bkt_table = NULL;
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+
+		kfree(hash_arg->table);
+		hash_arg->table = new_bkt_table;
+		hash_arg->size = new_sz;
+	}
+	result = IMG_SUCCESS;
+
+	return result;
+}
+
+static unsigned int private_max(unsigned int a, unsigned int b)
+{
+	unsigned int ret = (a > b) ? a : b;
+	return ret;
+}
+
+/*
+ * @Function	vid_hash_initialise
+ * @Description
+ * To initialise the hash module.
+ * @Input	None
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_initialise(void)
+{
+	unsigned int result = IMG_ERROR_ALREADY_COMPLETE;
+
+	if (!global_initialized) {
+		if (global_hashpool || global_bucketpool) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+
+		result = pool_create("img-hash",
+				     sizeof(struct hash),
+				     &global_hashpool);
+
+		if (result != IMG_SUCCESS) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+
+		result = pool_create("img-sBucket",
+				     sizeof(struct bucket),
+				     &global_bucketpool);
+		if (result != IMG_SUCCESS) {
+			if (global_bucketpool) {
+				result = pool_delete(global_bucketpool);
+				global_bucketpool = NULL;
+			}
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+		global_initialized = true;
+		result = IMG_SUCCESS;
+	}
+	return result;
+}
+
+/*
+ * @Function	vid_hash_finalise
+ * @Description
+ * To finalise the hash module. All allocated hash tables should
+ * be deleted before calling this function.
+ * @Input	None
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_finalise(void)
+{
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (global_initialized) {
+		if (global_hashpool) {
+			result = pool_delete(global_hashpool);
+			if (result != IMG_SUCCESS)
+				return result;
+
+			global_hashpool = NULL;
+		}
+
+		if (global_bucketpool) {
+			result = pool_delete(global_bucketpool);
+			if (result != IMG_SUCCESS)
+				return result;
+
+			global_bucketpool = NULL;
+		}
+		global_initialized = false;
+		result = IMG_SUCCESS;
+	}
+
+	return result;
+}
+
+/*
+ * @Function	vid_hash_create
+ * @Description
+ * Create a self scaling hash table.
+ * @Input	initial_size : Initial and minimum size of the hash table.
+ * @Output	hash_arg : Will countin the hash table handle or NULL.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_create(unsigned int initial_size,
+		    struct hash ** const hash_arg)
+{
+	unsigned int idx;
+	unsigned int tbl_sz = 0;
+	unsigned int result = IMG_ERROR_FATAL;
+	struct hash *local_hash = NULL;
+
+	if (!hash_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	if (global_initialized) {
+		pool_alloc(global_hashpool, ((void **)&local_hash));
+		if (!local_hash) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			*hash_arg = NULL;
+			return result;
+		}
+
+		local_hash->count = 0;
+		local_hash->size = initial_size;
+		local_hash->minimum_size = initial_size;
+
+		tbl_sz = (sizeof(struct bucket *) * local_hash->size);
+		local_hash->table = kmalloc(tbl_sz, GFP_KERNEL);
+		if (!local_hash->table) {
+			result = pool_free(global_hashpool, local_hash);
+			if (result != IMG_SUCCESS)
+				result = IMG_ERROR_UNEXPECTED_STATE;
+			result |= IMG_ERROR_MALLOC_FAILED;
+			*hash_arg = NULL;
+			return result;
+		}
+
+		for (idx = 0; idx < local_hash->size; idx++)
+			local_hash->table[idx] = NULL;
+
+		*hash_arg = local_hash;
+		result = IMG_SUCCESS;
+	}
+	return result;
+}
+
+/*
+ * @Function	vid_hash_delete
+ * @Description
+ * To delete a hash table, all entries in the table should be
+ * removed before calling this function.
+ * @Input	hash_arg : Hash table pointer
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_delete(struct hash * const hash_arg)
+{
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!hash_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	if (global_initialized) {
+		if (hash_arg->count != 0) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+
+		kfree(hash_arg->table);
+		hash_arg->table = NULL;
+
+		result = pool_free(global_hashpool, hash_arg);
+		if (result != IMG_SUCCESS) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+	}
+	return result;
+}
+
+/*
+ * @Function	vid_hash_insert
+ * @Description
+ * To insert a key value pair into a hash table.
+ * @Input	hash_arg : Hash table pointer
+ * @Input	key : Key value
+ * @Input	value : The value associated with the key.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_insert(struct hash * const hash_arg,
+		    unsigned long long key,
+		    unsigned long long value)
+{
+	struct bucket *ps_bucket = NULL;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!hash_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	if (global_initialized) {
+		result = pool_alloc(global_bucketpool, ((void **)&ps_bucket));
+		if (result != IMG_SUCCESS || !ps_bucket) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+		ps_bucket->next = NULL;
+		ps_bucket->key = key;
+		ps_bucket->value = value;
+
+		result = hash_chain_insert(ps_bucket,
+					   hash_arg->table,
+					   hash_arg->size);
+
+		if (result != IMG_SUCCESS) {
+			pool_free(global_bucketpool, ((void **)&ps_bucket));
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+
+		hash_arg->count++;
+
+		/* check if we need to think about re-balancing */
+		if ((hash_arg->count << 1) > hash_arg->size) {
+			result = hash_resize(hash_arg, (hash_arg->size << 1));
+			if (result != IMG_SUCCESS) {
+				result = IMG_ERROR_UNEXPECTED_STATE;
+				return result;
+			}
+		}
+		result = IMG_SUCCESS;
+	}
+	return result;
+}
+
+/*
+ * @Function	vid_hash_remove
+ * @Description
+ * To remove a key value pair from a hash table
+ * @Input	hash_arg : Hash table pointer
+ * @Input	key : Key value
+ * @Input	ret_result : 0 if the key is missing or the value
+ *		associated with the key.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_remove(struct hash * const hash_arg,
+		    unsigned long long key,
+		    unsigned long * const ret_result)
+{
+	unsigned int idx;
+	unsigned int tmp1 = 0;
+	unsigned int tmp2 = 0;
+	unsigned int result = IMG_ERROR_FATAL;
+	struct bucket **bucket = NULL;
+
+	if (!hash_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	idx = hash_func(key, hash_arg->size);
+
+	for (bucket = &hash_arg->table[idx]; (*bucket) != NULL;
+		bucket = &((*bucket)->next)) {
+		if ((*bucket)->key == key) {
+			struct bucket *ps_bucket = (*bucket);
+
+			unsigned long long value = ps_bucket->value;
+
+			*bucket = ps_bucket->next;
+			result = pool_free(global_bucketpool, ps_bucket);
+
+			hash_arg->count--;
+
+			/* check if we need to think about re-balencing */
+			if (hash_arg->size > (hash_arg->count << 2) &&
+			    hash_arg->size > hash_arg->minimum_size) {
+				tmp1 = (hash_arg->size >> 1);
+				tmp2 = hash_arg->minimum_size;
+				result = hash_resize(hash_arg,
+						     private_max(tmp1, tmp2));
+			}
+			*ret_result = value;
+			result = IMG_SUCCESS;
+			break;
+		}
+	}
+	return result;
+}
diff --git a/drivers/staging/media/vxd/common/hash.h b/drivers/staging/media/vxd/common/hash.h
new file mode 100644
index 000000000000..91034d1ba441
--- /dev/null
+++ b/drivers/staging/media/vxd/common/hash.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Self scaling hash tables.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@xxxxxx>
+ *
+ * Re-written for upstream
+ *      Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
+ */
+#ifndef _HASH_H_
+#define _HASH_H_
+
+#include <linux/types.h>
+struct hash;
+
+/**
+ * vid_hash_initialise - VID_HASH_Initialise
+ * @Input	 None
+ *
+ * To initialise the hash module.
+ */
+int vid_hash_initialise(void);
+
+/*
+ * @Function	VID_HASH_Finalise
+ * @Description
+ * To finalise the hash module. All allocated hash tables should
+ * be deleted before calling this function.
+ * @Input	None
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_finalise(void);
+
+/*
+ * @Function	VID_HASH_Create
+ * @Description
+ * Create a self scaling hash table.
+ * @Input	initial_size : Initial and minimum size of the hash table.
+ * @Output	hash : Hash table handle or NULL.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_create(unsigned int initial_size,
+		    struct hash ** const hash_hndl);
+
+/*
+ * @Function	VID_HASH_Delete
+ * @Description
+ * To delete a hash table, all entries in the table should be
+ * removed before calling this function.
+ * @Input	hash : Hash table pointer
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_delete(struct hash * const ps_hash);
+
+/*
+ * @Function	VID_HASH_Insert
+ * @Description
+ * To insert a key value pair into a hash table.
+ * @Input	ps_hash : Hash table pointer
+ * @Input	key : Key value
+ * @Input	value : The value associated with the key.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_insert(struct hash * const ps_hash,
+		    unsigned long long key,
+		    unsigned long long value);
+
+/*
+ * @Function	VID_HASH_Remove
+ * @Description
+ * To remove a key value pair from a hash table
+ * @Input	ps_hash : Hash table pointer
+ * @Input	key : Key value
+ * @Input	result : 0 if the key is missing or the value
+ *		associated with the key.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_remove(struct hash * const ps_hash,
+		    unsigned long long key,
+		    unsigned long * const result);
+
+#endif /* _HASH_H_ */
diff --git a/drivers/staging/media/vxd/common/pool.c b/drivers/staging/media/vxd/common/pool.c
new file mode 100644
index 000000000000..c0cb1e465c50
--- /dev/null
+++ b/drivers/staging/media/vxd/common/pool.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Object Pool Memory Allocator
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@xxxxxx>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_errors.h"
+#include "pool.h"
+
+#define BUFF_MAX_SIZE 4096
+#define BUFF_MAX_GROW 32
+
+/* 64 bits */
+#define ALIGN_SIZE (sizeof(long long) - 1)
+
+struct pool {
+	unsigned char *name;
+	unsigned int size;
+	unsigned int grow;
+	struct buffer *buffers;
+	struct object *objects;
+};
+
+struct buffer {
+	struct buffer *next;
+};
+
+struct object {
+	struct object *next;
+};
+
+static inline unsigned char *strdup_cust(const unsigned char *str)
+{
+	unsigned char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
+
+	if (r)
+		strcpy(r, str);
+	return r;
+}
+
+/*
+ * pool_create - Create an sObject pool
+ * @name: Name of sObject pool for diagnostic purposes
+ * @obj_size: size of each sObject in the pool in bytes
+ * @pool_hdnl: Will contain NULL or sObject pool handle
+ *
+ * This function Create an sObject pool
+ */
+
+int pool_create(const unsigned char * const name,
+		unsigned int obj_size,
+		struct pool ** const pool_hdnl)
+{
+	struct pool *local_pool = NULL;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!name || !pool_hdnl) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	local_pool = kmalloc((sizeof(*local_pool)), GFP_KERNEL);
+	if (!local_pool) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	local_pool->name = strdup_cust((unsigned char *)name);
+	local_pool->size = obj_size;
+	local_pool->buffers = NULL;
+	local_pool->objects = NULL;
+	local_pool->grow =
+		(BUFF_MAX_SIZE - sizeof(struct buffer)) /
+		(obj_size + ALIGN_SIZE);
+
+	if (local_pool->grow == 0)
+		local_pool->grow = 1;
+	else if (local_pool->grow > BUFF_MAX_GROW)
+		local_pool->grow = BUFF_MAX_GROW;
+
+	*pool_hdnl = local_pool;
+	result = IMG_SUCCESS;
+
+	return result;
+}
+
+/*
+ * @Function	pool_delete
+ * @Description
+ * Delete an sObject pool. All psObjects allocated from the pool must
+ * be free'd with pool_free() before deleting the sObject pool.
+ * @Input	pool : Object Pool pointer
+ * @Return IMG_SUCCESS or an error code.
+ */
+int pool_delete(struct pool * const pool_arg)
+{
+	struct buffer *local_buf = NULL;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!pool_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	local_buf = pool_arg->buffers;
+	while (local_buf) {
+		local_buf = local_buf->next;
+		kfree(pool_arg->buffers);
+		pool_arg->buffers = local_buf;
+	}
+
+	kfree(pool_arg->name);
+	pool_arg->name = NULL;
+
+	kfree(pool_arg);
+	result = IMG_SUCCESS;
+
+	return result;
+}
+
+/*
+ * @Function	pool_alloc
+ * @Description
+ * Allocate an sObject from an sObject pool.
+ * @Input	pool_arg : Object Pool
+ * @Output	obj_hndl : Pointer containing the handle to the
+ * object created or IMG_NULL
+ * @Return    IMG_SUCCESS or an error code.
+ */
+int pool_alloc(struct pool * const pool_arg,
+	       void ** const obj_hndl)
+{
+	struct object *local_obj1 = NULL;
+	struct buffer *local_buf = NULL;
+	unsigned int idx = 0;
+	unsigned int sz = 0;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!pool_arg || !obj_hndl) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	if (!pool_arg->objects) {
+		sz = (pool_arg->size + ALIGN_SIZE);
+		sz *= (pool_arg->grow + sizeof(struct buffer));
+		local_buf = kmalloc(sz, GFP_KERNEL);
+		if (!local_buf) {
+			result = IMG_ERROR_MALLOC_FAILED;
+			return result;
+		}
+
+		local_buf->next = pool_arg->buffers;
+		pool_arg->buffers = local_buf;
+
+		for (idx = 0; idx < pool_arg->grow; idx++) {
+			struct object *local_obj2;
+			unsigned char *temp_ptr = NULL;
+
+			local_obj2 = (struct object *)(((unsigned char *)(local_buf + 1))
+				+ (idx * (pool_arg->size + ALIGN_SIZE)));
+
+			temp_ptr = (unsigned char *)local_obj2;
+			if ((unsigned long)temp_ptr & ALIGN_SIZE) {
+				temp_ptr += ((ALIGN_SIZE + 1)
+					- ((unsigned long)temp_ptr & ALIGN_SIZE));
+				local_obj2 = (struct object *)temp_ptr;
+			}
+
+			local_obj2->next = pool_arg->objects;
+			pool_arg->objects = local_obj2;
+		}
+	}
+
+	if (!pool_arg->objects) {
+		result = IMG_ERROR_UNEXPECTED_STATE;
+		return result;
+	}
+
+	local_obj1 = pool_arg->objects;
+	pool_arg->objects = local_obj1->next;
+
+	*obj_hndl = (void *)(local_obj1);
+	result = IMG_SUCCESS;
+
+	return result;
+}
+
+/*
+ * @Function	pool_free
+ * @Description
+ * Free an sObject previously allocated from an sObject pool.
+ * @Input	pool_arg : Object Pool pointer.
+ * @Output	h_object : Handle to the object to be freed.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int pool_free(struct pool * const pool_arg,
+	      void * const obj_hndl)
+{
+	struct object *object = NULL;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!pool_arg || !obj_hndl) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	object = (struct object *)obj_hndl;
+	object->next = pool_arg->objects;
+	pool_arg->objects = object;
+
+	result = IMG_SUCCESS;
+
+	return result;
+}
diff --git a/drivers/staging/media/vxd/common/pool.h b/drivers/staging/media/vxd/common/pool.h
new file mode 100644
index 000000000000..d22d15a2af54
--- /dev/null
+++ b/drivers/staging/media/vxd/common/pool.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Object Pool Memory Allocator header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@xxxxxx>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
+ */
+#ifndef _pool_h_
+#define _pool_h_
+
+#include <linux/types.h>
+
+struct pool;
+
+/**
+ * pool_create - Create an sObject pool
+ * @name: Name of sObject pool for diagnostic purposes
+ * @obj_size: size of each sObject in the pool in bytes
+ * @pool: Will contain NULL or sObject pool handle
+ *
+ * Return	IMG_SUCCESS or an error code.
+ */
+int pool_create(const unsigned char * const name,
+		unsigned int obj_size,
+		struct pool ** const pool);
+
+/*
+ * @Function	pool_delete
+ * @Description
+ * Delete an sObject pool. All psObjects allocated from the pool must
+ * be free'd with pool_free() before deleting the sObject pool.
+ * @Input	pool : Object Pool pointer
+ * @Return IMG_SUCCESS or an error code.
+ */
+int pool_delete(struct pool * const pool);
+
+/*
+ * @Function	pool_alloc
+ * @Description
+ * Allocate an Object from an Object pool.
+ * @Input	pool : Object Pool
+ * @Output	obj_hdnl : Pointer containing the handle to the
+ * object created or IMG_NULL
+ * @Return    IMG_SUCCESS or an error code.
+ */
+int pool_alloc(struct pool * const pool,
+	       void ** const obj_hdnl);
+
+/*
+ * @Function	pool_free
+ * @Description
+ * Free an sObject previously allocated from an sObject pool.
+ * @Input	pool : Object Pool pointer.
+ * @Output	obj_hdnl : Handle to the object to be freed.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int pool_free(struct pool * const pool,
+	      void * const obj_hdnl);
+
+#endif /* _pool_h_ */
diff --git a/drivers/staging/media/vxd/common/ra.c b/drivers/staging/media/vxd/common/ra.c
new file mode 100644
index 000000000000..ac07737f351b
--- /dev/null
+++ b/drivers/staging/media/vxd/common/ra.c
@@ -0,0 +1,972 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Implements generic resource allocation.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@xxxxxx>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "hash.h"
+#include "img_errors.h"
+#include "pool.h"
+#include "ra.h"
+
+static unsigned char	global_init;
+
+/* pool of struct arena's */
+static struct pool *global_pool_arena;
+
+/* pool of struct boundary tag */
+static struct pool *global_pool_bt;
+
+/**
+ * ra_request_alloc_fail - ra_request_alloc_fail
+ * @import_hdnl : Callback handle.
+ * @requested_size : Requested allocation size.
+ * @ref : Pointer to user reference data.
+ * @alloc_flags : Allocation flags.
+ * @actual_size : Pointer to contain the actual allocated size.
+ * @base_addr : Allocation base(always 0,it is failing).
+ *
+ * Default callback allocator used if no callback is specified, always fails
+ * to allocate further resources to the arena.
+ */
+static int ra_request_alloc_fail(void *import_hdnl,
+				 unsigned long long requested_size,
+				 unsigned long long *actual_size,
+				 void **ref,
+				 unsigned int alloc_flags,
+				 unsigned long long *base_addr)
+{
+	if (base_addr)
+		*base_addr = 0;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	ra_log2
+ * @Description
+ * Calculates the Log2(n) with n being a 64-bit value.
+ *
+ * @Input	value : Input value.
+ * @Output	None
+ * @Return	result : Log2(ui64Value).
+ */
+
+static unsigned int ra_log2(unsigned long long value)
+{
+	int res = 0;
+
+	value >>= 1;
+	while (value > 0) {
+		value >>= 1;
+		res++;
+	}
+	return res;
+}
+
+/*
+ * @Function	ra_segment_list_insert_after
+ * @Description	Insert a boundary tag into an arena segment list after a
+ *		specified boundary tag.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_here_arg : The boundary tag before which psBTToInsert
+ *		will be added .
+ * @Input	bt_to_insert_arg : The boundary tag to insert.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_segment_list_insert_after(struct arena *arena_arg,
+					 struct btag *bt_here_arg,
+					 struct btag *bt_to_insert_arg)
+{
+	bt_to_insert_arg->nxt_seg = bt_here_arg->nxt_seg;
+	bt_to_insert_arg->prv_seg = bt_here_arg;
+
+	if (!bt_here_arg->nxt_seg)
+		arena_arg->tail_seg = bt_to_insert_arg;
+	else
+		bt_here_arg->nxt_seg->prv_seg = bt_to_insert_arg;
+
+	bt_here_arg->nxt_seg = bt_to_insert_arg;
+}
+
+/*
+ * @Function	ra_segment_list_insert
+ * @Description
+ * Insert a boundary tag into an arena segment list at the appropriate point.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_to_insert_arg : The boundary tag to insert.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_segment_list_insert(struct arena *arena_arg,
+				   struct btag *bt_to_insert_arg)
+{
+	/* insert into the segment chain */
+	if (!arena_arg->head_seg) {
+		arena_arg->head_seg = bt_to_insert_arg;
+		arena_arg->tail_seg = bt_to_insert_arg;
+		bt_to_insert_arg->nxt_seg = NULL;
+		bt_to_insert_arg->prv_seg = NULL;
+	} else {
+		struct btag *bt_scan = arena_arg->head_seg;
+
+		while (bt_scan->nxt_seg &&
+		       bt_to_insert_arg->base >=
+		       bt_scan->nxt_seg->base) {
+			bt_scan = bt_scan->nxt_seg;
+		}
+		ra_segment_list_insert_after(arena_arg,
+					     bt_scan,
+					     bt_to_insert_arg);
+	}
+}
+
+/*
+ * @Function	ra_SegmentListRemove
+ * @Description
+ * Insert a boundary tag into an arena segment list at the appropriate point.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_to_remove_arg : The boundary tag to insert.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_segment_list_remove(struct arena *arena_arg,
+				   struct btag *bt_to_remove_arg)
+{
+	if (!bt_to_remove_arg->prv_seg)
+		arena_arg->head_seg = bt_to_remove_arg->nxt_seg;
+	else
+		bt_to_remove_arg->prv_seg->nxt_seg = bt_to_remove_arg->nxt_seg;
+
+	if (!bt_to_remove_arg->nxt_seg)
+		arena_arg->tail_seg = bt_to_remove_arg->prv_seg;
+	else
+		bt_to_remove_arg->nxt_seg->prv_seg = bt_to_remove_arg->prv_seg;
+}
+
+/*
+ * @Function	ra_segment_split
+ * @Description
+ * Split a segment into two, maintain the arena segment list.
+ * The boundary tag should not be in the free table. Neither the original or
+ * the new psBTNeighbour bounary tag will be in the free table.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_to_split_arg : The boundary tag to split.
+ *		The required segment size of boundary tag after the split.
+ * @Output	None
+ * @Return	btag *: New boundary tag.
+ */
+static struct btag *ra_segment_split(struct arena *arena_arg,
+				     struct btag *bt_to_split_arg,
+				     unsigned long long size)
+{
+	struct btag *local_bt_neighbour = NULL;
+	int res = IMG_ERROR_FATAL;
+
+	res = pool_alloc(global_pool_bt, ((void **)&local_bt_neighbour));
+	if (res != IMG_SUCCESS)
+		return NULL;
+
+	local_bt_neighbour->prv_seg = bt_to_split_arg;
+	local_bt_neighbour->nxt_seg = bt_to_split_arg->nxt_seg;
+	local_bt_neighbour->bt_type = RA_BOUNDARY_TAG_TYPE_FREE;
+	local_bt_neighbour->size = (bt_to_split_arg->size - size);
+	local_bt_neighbour->base = (bt_to_split_arg->base + size);
+	local_bt_neighbour->nxt_free = NULL;
+	local_bt_neighbour->prv_free = NULL;
+	local_bt_neighbour->ref = bt_to_split_arg->ref;
+
+	if (!bt_to_split_arg->nxt_seg)
+		arena_arg->tail_seg = local_bt_neighbour;
+	else
+		bt_to_split_arg->nxt_seg->prv_seg = local_bt_neighbour;
+
+	bt_to_split_arg->nxt_seg = local_bt_neighbour;
+	bt_to_split_arg->size = size;
+
+	return local_bt_neighbour;
+}
+
+/*
+ * @Function	ra_free_list_insert
+ * @Description
+ * Insert a boundary tag into an arena free table.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_arg : The boundary tag to insert into an arena
+ *		free table.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_free_list_insert(struct arena *arena_arg,
+				struct btag *bt_arg)
+{
+	unsigned int index = ra_log2(bt_arg->size);
+
+	bt_arg->bt_type = RA_BOUNDARY_TAG_TYPE_FREE;
+	if (index < FREE_TABLE_LIMIT)
+		bt_arg->nxt_free = arena_arg->head_free[index];
+	else
+		bt_arg->nxt_free = NULL;
+
+	bt_arg->prv_free = NULL;
+
+	if (index < FREE_TABLE_LIMIT) {
+		if (arena_arg->head_free[index])
+			arena_arg->head_free[index]->prv_free = bt_arg;
+	}
+
+	if (index < FREE_TABLE_LIMIT)
+		arena_arg->head_free[index] = bt_arg;
+}
+
+/*
+ * @Function	ra_free_list_remove
+ * @Description
+ * Remove a boundary tag from an arena free table.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_arg    : The boundary tag to remove from
+ *		an arena free table.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_free_list_remove(struct arena *arena_arg,
+				struct btag *bt_arg)
+{
+	unsigned int index = ra_log2(bt_arg->size);
+
+	if (bt_arg->nxt_free)
+		bt_arg->nxt_free->prv_free = bt_arg->prv_free;
+
+	if (!bt_arg->prv_free && index < FREE_TABLE_LIMIT)
+		arena_arg->head_free[index] = bt_arg->nxt_free;
+	else if (bt_arg->prv_free)
+		bt_arg->prv_free->nxt_free = bt_arg->nxt_free;
+}
+
+/*
+ * @Function	ra_build_span_marker
+ * @Description
+ * Construct a span marker boundary tag.
+ * @Input	base : The base of the boundary tag.
+ * @Output	None
+ * @Return    btag * : New span marker boundary tag
+ */
+static struct btag *ra_build_span_marker(unsigned long long base)
+{
+	struct btag *local_bt = NULL;
+	int res = IMG_ERROR_FATAL;
+
+	res = pool_alloc(global_pool_bt, ((void **)&local_bt));
+	if (res != IMG_SUCCESS)
+		return NULL;
+
+	local_bt->bt_type = RA_BOUNDARY_TAG_TYPE_SPAN;
+	local_bt->base = base;
+	local_bt->size = 0;
+	local_bt->nxt_seg = NULL;
+	local_bt->prv_seg = NULL;
+	local_bt->nxt_free = NULL;
+	local_bt->prv_free = NULL;
+	local_bt->ref = NULL;
+
+	return local_bt;
+}
+
+/*
+ * @Function	ra_build_bt
+ * @Description
+ * Construct a boundary tag for a free segment.
+ * @Input	    ui64Base    : The base of the resource segment.
+ * @Input	    ui64Size    : The extent of the resource segment.
+ * @Output	None
+ * @Return    btag *       : New boundary tag
+ */
+static struct btag *ra_build_bt(unsigned long long base, unsigned long long size)
+{
+	struct btag *local_bt = NULL;
+	int res = IMG_ERROR_FATAL;
+
+	res = pool_alloc(global_pool_bt, ((void **)&local_bt));
+
+	if (res != IMG_SUCCESS)
+		return local_bt;
+
+	local_bt->bt_type = RA_BOUNDARY_TAG_TYPE_FREE;
+	local_bt->base = base;
+	local_bt->size = size;
+	local_bt->nxt_seg = NULL;
+	local_bt->prv_seg = NULL;
+	local_bt->nxt_free = NULL;
+	local_bt->prv_free = NULL;
+	local_bt->ref = NULL;
+
+	return local_bt;
+}
+
+/*
+ * @Function	ra_insert_resource
+ * @Description
+ * Add a free resource segment to an arena.
+ * @Input	base : The base of the resource segment.
+ * @Input	size : The size of the resource segment.
+ * @Output	None
+ * @Return	IMG_SUCCESS or an error code.
+ */
+static int ra_insert_resource(struct arena *arena_arg,
+			      unsigned long long base,
+			      unsigned long long size)
+{
+	struct btag *local_bt = NULL;
+
+	local_bt = ra_build_bt(base, size);
+	if (!local_bt)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	ra_segment_list_insert(arena_arg, local_bt);
+	ra_free_list_insert(arena_arg, local_bt);
+	arena_arg->max_idx = ra_log2(size);
+	if (1ULL << arena_arg->max_idx < size)
+		arena_arg->max_idx++;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	ra_insert_resource_span
+ * @Description
+ * Add a free resource span to an arena, complete with span markers.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	base : The base of the resource segment.
+ * @Input	size : The size of the resource segment.
+ * @Output	None
+ * @Return	btag * : The boundary tag representing
+ *		the free resource segment.
+ */
+static struct btag *ra_insert_resource_span(struct arena *arena_arg,
+					    unsigned long long base,
+					    unsigned long long size)
+{
+	struct btag *local_bt = NULL;
+	struct btag *local_bt_span_start = NULL;
+	struct btag *local_bt_span_end = NULL;
+
+	local_bt_span_start = ra_build_span_marker(base);
+	if (!local_bt_span_start)
+		return NULL;
+
+	local_bt_span_end = ra_build_span_marker(base + size);
+	if (!local_bt_span_end) {
+		pool_free(global_pool_bt, local_bt_span_start);
+		return NULL;
+	}
+
+	local_bt = ra_build_bt(base, size);
+	if (!local_bt) {
+		pool_free(global_pool_bt, local_bt_span_end);
+		pool_free(global_pool_bt, local_bt_span_start);
+		return NULL;
+	}
+
+	ra_segment_list_insert(arena_arg, local_bt_span_start);
+	ra_segment_list_insert_after(arena_arg,
+				     local_bt_span_start,
+				     local_bt);
+	ra_free_list_insert(arena_arg, local_bt);
+	ra_segment_list_insert_after(arena_arg,
+				     local_bt,
+				     local_bt_span_end);
+
+	return local_bt;
+}
+
+/*
+ * @Function	ra_free_bt
+ * @Description
+ * Free a boundary tag taking care of the segment list and the
+ *		boundary tag free table.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_arg : The boundary tag to free.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_free_bt(struct arena *arena_arg,
+		       struct btag *bt_arg)
+{
+	struct btag *bt_neibr;
+
+	/* try and coalesce with left bt_neibr */
+	bt_neibr = bt_arg->prv_seg;
+	if (bt_neibr &&
+	    bt_neibr->bt_type == RA_BOUNDARY_TAG_TYPE_FREE &&
+	    bt_neibr->base + bt_neibr->size == bt_arg->base) {
+		ra_free_list_remove(arena_arg, bt_neibr);
+		ra_segment_list_remove(arena_arg, bt_neibr);
+		bt_arg->base = bt_neibr->base;
+		bt_arg->size += bt_neibr->size;
+		pool_free(global_pool_bt, bt_neibr);
+	}
+
+	/* try to coalesce with right psBTNeighbour */
+	bt_neibr = bt_arg->nxt_seg;
+	if (bt_neibr &&
+	    bt_neibr->bt_type == RA_BOUNDARY_TAG_TYPE_FREE &&
+	    bt_arg->base + bt_arg->size == bt_neibr->base) {
+		ra_free_list_remove(arena_arg, bt_neibr);
+		ra_segment_list_remove(arena_arg, bt_neibr);
+		bt_arg->size += bt_neibr->size;
+		pool_free(global_pool_bt, bt_neibr);
+	}
+
+	if (bt_arg->nxt_seg &&
+	    bt_arg->nxt_seg->bt_type == RA_BOUNDARY_TAG_TYPE_SPAN &&
+	    bt_arg->prv_seg && bt_arg->prv_seg->bt_type ==
+	    RA_BOUNDARY_TAG_TYPE_SPAN) {
+		struct btag *ps_bt_nxt = bt_arg->nxt_seg;
+		struct btag *ps_bt_prev = bt_arg->prv_seg;
+
+		ra_segment_list_remove(arena_arg, ps_bt_nxt);
+		ra_segment_list_remove(arena_arg, ps_bt_prev);
+		ra_segment_list_remove(arena_arg, bt_arg);
+		arena_arg->import_free_fxn(arena_arg->import_hdnl,
+					   bt_arg->base,
+					   bt_arg->ref);
+		pool_free(global_pool_bt, ps_bt_nxt);
+		pool_free(global_pool_bt, ps_bt_prev);
+		pool_free(global_pool_bt, bt_arg);
+	} else {
+		ra_free_list_insert(arena_arg, bt_arg);
+	}
+}
+
+static int ra_check_btag(struct arena *arena_arg,
+			 unsigned long long size_arg,
+			 void **ref,
+			 struct btag *bt_arg,
+			 unsigned long long align_arg,
+			 unsigned long long *base_arg,
+			 unsigned int align_log2)
+{
+	unsigned long long local_align_base;
+	int res = IMG_ERROR_FATAL;
+
+	while (bt_arg) {
+		if (align_arg > 1ULL)
+			local_align_base = ((bt_arg->base + align_arg - 1)
+				>> align_log2) << align_log2;
+		else
+			local_align_base = bt_arg->base;
+
+		if ((bt_arg->base + bt_arg->size) >=
+		     (local_align_base + size_arg)) {
+			ra_free_list_remove(arena_arg, bt_arg);
+
+			/*
+			 * with align_arg we might need to discard the front of
+			 * this segment
+			 */
+			if (local_align_base > bt_arg->base) {
+				struct btag *btneighbor;
+
+				btneighbor = ra_segment_split(arena_arg,
+							      bt_arg,
+							      (local_align_base -
+							       bt_arg->base));
+				/*
+				 * Partition the buffer, create a new boundary
+				 * tag
+				 */
+				if (!btneighbor)
+					return IMG_ERROR_UNEXPECTED_STATE;
+
+				ra_free_list_insert(arena_arg, bt_arg);
+				bt_arg = btneighbor;
+			}
+
+			/*
+			 * The segment might be too big, if so, discard the back
+			 * of the segment
+			 */
+			if (bt_arg->size > size_arg) {
+				struct btag *btneighbor;
+
+				btneighbor = ra_segment_split(arena_arg,
+							      bt_arg,
+							      size_arg);
+				/*
+				 * Partition the buffer, create a new boundary
+				 * tag
+				 */
+				if (!btneighbor)
+					return IMG_ERROR_UNEXPECTED_STATE;
+
+				ra_free_list_insert(arena_arg, btneighbor);
+			}
+
+			bt_arg->bt_type = RA_BOUNDARY_TAG_TYPE_LIVE;
+
+			res = vid_hash_insert(arena_arg->hash_tbl,
+					      bt_arg->base,
+					      (unsigned long)bt_arg);
+			if (res != IMG_SUCCESS) {
+				ra_free_bt(arena_arg, bt_arg);
+				*base_arg = 0;
+				return IMG_ERROR_UNEXPECTED_STATE;
+			}
+
+			if (ref)
+				*ref = bt_arg->ref;
+
+			*base_arg = bt_arg->base;
+			return IMG_SUCCESS;
+		}
+		bt_arg = bt_arg->nxt_free;
+	}
+
+	return res;
+}
+
+/*
+ * @Function	ra_attempt_alloc_aligned
+ * @Description	Attempt to allocate from an arena
+ * @Input	arena_arg: Pointer to the input arena
+ * @Input	size_arg: The requested allocation size
+ * @Input	ref: The user references associated with the allocated
+ *		segment
+ * @Input	align_arg: Required alignment
+ * @Output	base_arg: Allocated resource size
+ * @Return	IMG_SUCCESS or an error code
+ */
+static int ra_attempt_alloc_aligned(struct arena *arena_arg,
+				    unsigned long long size_arg,
+				    void **ref,
+				    unsigned long long align_arg,
+				    unsigned long long *base_arg)
+{
+	unsigned int index;
+	unsigned int align_log2;
+	int res = IMG_ERROR_FATAL;
+
+	if (!arena_arg || !base_arg)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/*
+	 * Take the log of the alignment to get number of bits to shift
+	 * left/right for multiply/divide. Assumption made here is that
+	 * alignment has to be a power of 2 value. Aserting otherwise.
+	 */
+	align_log2 = ra_log2(align_arg);
+
+	/*
+	 * Search for a near fit free boundary tag, start looking at the
+	 * log2 free table for our required size and work on up the table.
+	 */
+	index = ra_log2(size_arg);
+
+	/*
+	 * If the Size required is exactly 2**n then use the n bucket, because
+	 * we know that every free block in that bucket is larger than 2**n,
+	 * otherwise start at then next bucket up.
+	 */
+	if (size_arg > (1ull << index))
+		index++;
+
+	while ((index < FREE_TABLE_LIMIT) && !arena_arg->head_free[index])
+		index++;
+
+	if (index >= FREE_TABLE_LIMIT) {
+		pr_err("requested allocation size doesn't fit in the arena. Increase MMU HEAP Size\n");
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	while (index < FREE_TABLE_LIMIT) {
+		if (arena_arg->head_free[index]) {
+			/* we have a cached free boundary tag */
+			struct btag *local_bt =
+				arena_arg->head_free[index];
+
+			res = ra_check_btag(arena_arg,
+					    size_arg,
+					    ref,
+					    local_bt,
+					    align_arg,
+					    base_arg,
+					    align_log2);
+			if (res != IMG_SUCCESS)
+				return res;
+		}
+		index++;
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	vid_ra_init
+ * @Description	Initializes the RA module. Must be called before any other
+ *		ra API function
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_initialise(void)
+{
+	int res = IMG_ERROR_FATAL;
+
+	if (!global_init) {
+		res = pool_create("img-arena",
+				  sizeof(struct arena),
+				  &global_pool_arena);
+		if (res != IMG_SUCCESS)
+			return IMG_ERROR_UNEXPECTED_STATE;
+
+		res = pool_create("img-bt",
+				  sizeof(struct btag),
+				  &global_pool_bt);
+		if (res != IMG_SUCCESS) {
+			res = pool_delete(global_pool_arena);
+			global_pool_arena = NULL;
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+		global_init = 1;
+		res = IMG_SUCCESS;
+	}
+
+	return res;
+}
+
+/*
+ * @Function	vid_ra_deinit
+ * @Description	Deinitializes the RA module
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_deinit(void)
+{
+	int res = IMG_ERROR_FATAL;
+
+	if (global_init) {
+		if (global_pool_arena) {
+			res = pool_delete(global_pool_arena);
+			global_pool_arena = NULL;
+		}
+		if (global_pool_bt) {
+			res = pool_delete(global_pool_bt);
+			global_pool_bt = NULL;
+		}
+		global_init = 0;
+		res = IMG_SUCCESS;
+	}
+	return res;
+}
+
+/*
+ * @Function	vid_ra_create
+ * @Description	Used to create a resource arena.
+ * @Input	name: The name of the arena for diagnostic purposes
+ * @Input	base_arg: The base of an initial resource span or 0
+ * @Input	size_arg: The size of an initial resource span or 0
+ * @Input	quantum: The arena allocation quantum
+ * @Input	(*import_alloc_fxn): A resource allocation callback or NULL
+ * @Input	(*import_free_fxn): A resource de-allocation callback or NULL
+ * @Input	import_hdnl: Handle passed to alloc and free or NULL
+ * @Output	arena_hndl: The handle for the arene being created, or NULL
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_create(const unsigned char * const name,
+		  unsigned long long base_arg,
+		  unsigned long long size_arg,
+		  unsigned long	quantum,
+		  int (*import_alloc_fxn)(void * const import_hdnl,
+					  unsigned long long req_sz,
+					  unsigned long long * const actl_sz,
+					  void ** const ref,
+					  unsigned int alloc_flags,
+					  unsigned long long * const base_arg),
+		  int (*import_free_fxn)(void * const import_hdnl,
+					 unsigned long long import_base,
+					 void * const import_ref),
+					 void *import_hdnl,
+					 void **arena_hndl)
+{
+	struct arena *local_arena = NULL;
+	unsigned int idx = 0;
+	int res = IMG_ERROR_FATAL;
+
+	if (!arena_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	*(arena_hndl) = NULL;
+
+	if (global_init) {
+		res = pool_alloc(global_pool_arena, ((void **)&local_arena));
+		if (!local_arena || res != IMG_SUCCESS)
+			return IMG_ERROR_UNEXPECTED_STATE;
+
+		local_arena->name = NULL;
+		if (name)
+			local_arena->name = kstrdup((const signed char *)name,
+						    GFP_KERNEL);
+		if (import_alloc_fxn)
+			local_arena->import_alloc_fxn = import_alloc_fxn;
+		else
+			local_arena->import_alloc_fxn = ra_request_alloc_fail;
+
+		local_arena->import_free_fxn = import_free_fxn;
+		local_arena->import_hdnl = import_hdnl;
+
+		for (idx = 0; idx < FREE_TABLE_LIMIT; idx++)
+			local_arena->head_free[idx] = NULL;
+
+		local_arena->head_seg = NULL;
+		local_arena->tail_seg = NULL;
+		local_arena->quantum = quantum;
+
+		res = vid_hash_create(MINIMUM_HASH_SIZE,
+				      &local_arena->hash_tbl);
+
+		if (!local_arena->hash_tbl) {
+			vid_hash_delete(local_arena->hash_tbl);
+			kfree(local_arena->name);
+			local_arena->name = NULL;
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		//if (size_arg > (unsigned long long)0) {
+		if (size_arg > 0ULL) {
+			size_arg = (size_arg + quantum - 1) / quantum * quantum;
+
+			res = ra_insert_resource(local_arena,
+						 base_arg,
+						 size_arg);
+			if (res != IMG_SUCCESS) {
+				vid_hash_delete(local_arena->hash_tbl);
+				pool_free(global_pool_arena, local_arena);
+				kfree(local_arena->name);
+				local_arena->name = NULL;
+				return IMG_ERROR_UNEXPECTED_STATE;
+			}
+		}
+		*(arena_hndl) = local_arena;
+		res = IMG_SUCCESS;
+	}
+
+	return res;
+}
+
+/*
+ * @Function	vid_ra_delete
+ * @Description	Used to delete a resource arena. All resources allocated from
+ *		the arena must be freed before deleting the arena
+ * @Input	arena_hndl: The handle to the arena to delete
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_delete(void * const arena_hndl)
+{
+	int res = IMG_ERROR_FATAL;
+	struct arena *local_arena = NULL;
+	unsigned int idx;
+
+	if (!arena_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (global_init) {
+		local_arena = (struct arena *)arena_hndl;
+		kfree(local_arena->name);
+		local_arena->name = NULL;
+		for (idx = 0; idx < FREE_TABLE_LIMIT; idx++)
+			local_arena->head_free[idx] = NULL;
+
+		while (local_arena->head_seg) {
+			struct btag *local_bt = local_arena->head_seg;
+
+			ra_segment_list_remove(local_arena, local_bt);
+		}
+		res = vid_hash_delete(local_arena->hash_tbl);
+		if (res != IMG_SUCCESS)
+			return IMG_ERROR_UNEXPECTED_STATE;
+
+		res = pool_free(global_pool_arena, local_arena);
+		if (res != IMG_SUCCESS)
+			return IMG_ERROR_UNEXPECTED_STATE;
+	}
+
+	return res;
+}
+
+/*
+ * @Function	vid_ra_add
+ * @Description	Used to add a resource span to an arena. The span must not
+ *		overlap with any span previously added to the arena
+ * @Input	base_arg: The base_arg of the span
+ * @Input	size_arg: The size of the span
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_add(void * const arena_hndl, unsigned long long base_arg, unsigned long long size_arg)
+{
+	int res = IMG_ERROR_FATAL;
+	struct arena *local_arena = NULL;
+
+	if (!arena_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (global_init) {
+		local_arena = (struct arena *)arena_hndl;
+		size_arg = (size_arg + local_arena->quantum - 1) /
+			local_arena->quantum * local_arena->quantum;
+
+		res = ra_insert_resource(local_arena, base_arg, size_arg);
+		if (res != IMG_SUCCESS)
+			return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	return res;
+}
+
+/*
+ * @Function	vid_ra_alloc
+ * @Description	Used to allocate resource from an arena
+ * @Input	arena_hndl: The handle to the arena to create the resource
+ * @Input	request_size: The requested size of resource segment
+ * @Input	actl_size: The actualSize of resource segment
+ * @Input	ref: The user reference associated with allocated resource
+ *		span
+ * @Input	alloc_flags: AllocationFlags influencing allocation policy
+ * @Input	align_arg: The alignment constraint required for the allocated
+ *		segment
+ * @Output	base_args: The base of the allocated resource
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_alloc(void * const arena_hndl,
+		 unsigned long long request_size,
+		 unsigned long long * const actl_sz,
+		 void ** const ref,
+		 unsigned int alloc_flags,
+		 unsigned long long alignarg,
+		 unsigned long long * const basearg)
+{
+	int res = IMG_ERROR_FATAL;
+	struct arena *arn_ctx = NULL;
+	unsigned long long loc_size = request_size;
+
+	if (!arena_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (global_init) {
+		arn_ctx = (struct arena *)arena_hndl;
+		loc_size = ((loc_size + arn_ctx->quantum - 1) /
+				arn_ctx->quantum) * arn_ctx->quantum;
+
+		if (actl_sz)
+			*actl_sz = loc_size;
+
+		/*
+		 * If allocation failed then we might have an import source
+		 * which can provide more resource, else we will have to fail
+		 * the allocation to the caller.
+		 */
+		if (alloc_flags == RA_SEQUENTIAL_ALLOCATION)
+			res = ra_attempt_alloc_aligned(arn_ctx,
+						       loc_size,
+						       ref,
+						       alignarg,
+						       basearg);
+
+		if (res != IMG_SUCCESS) {
+			void *import_ref = NULL;
+			unsigned long long import_base = 0ULL;
+			unsigned long long locimprt_reqsz = loc_size;
+			unsigned long long locimprt_actsz = 0ULL;
+
+			res = arn_ctx->import_alloc_fxn(arn_ctx->import_hdnl,
+					locimprt_reqsz,
+					&locimprt_actsz,
+					&import_ref,
+					alloc_flags,
+					&import_base);
+
+			if (res == IMG_SUCCESS) {
+				struct btag *local_bt =
+					ra_insert_resource_span(arn_ctx,
+								import_base,
+								locimprt_actsz);
+
+				/*
+				 * Successfully import more resource, create a
+				 * span to represent it and retry the allocation
+				 * attempt
+				 */
+				if (!local_bt) {
+					/*
+					 * Insufficient resources to insert the
+					 * newly acquired span, so free it back
+					 */
+					arn_ctx->import_free_fxn(arn_ctx->import_hdnl,
+							import_base,
+							import_ref);
+					return IMG_ERROR_UNEXPECTED_STATE;
+				}
+				local_bt->ref = import_ref;
+				if (alloc_flags == RA_SEQUENTIAL_ALLOCATION) {
+					res = ra_attempt_alloc_aligned(arn_ctx,
+								       loc_size,
+								       ref,
+								       alignarg,
+								       basearg);
+				}
+			}
+		}
+	}
+
+	return res;
+}
+
+/*
+ * @Function	vid_ra_free
+ * @Description	Used to free a resource segment
+ * @Input	arena_hndl: The arena the segment was originally allocated from
+ * @Input	base_arg: The base of the span
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_free(void * const arena_hndl, unsigned long long base_arg)
+{
+	int res = IMG_ERROR_FATAL;
+	struct arena *local_arena = NULL;
+	struct btag *local_bt = NULL;
+	unsigned long	uip_res;
+
+	if (!arena_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (global_init) {
+		local_arena = (struct arena *)arena_hndl;
+
+		res = vid_hash_remove(local_arena->hash_tbl,
+				      base_arg,
+				      &uip_res);
+		if (res != IMG_SUCCESS)
+			return res;
+		local_bt = (struct btag *)uip_res;
+
+		ra_free_bt(local_arena, local_bt);
+	}
+
+	return res;
+}
diff --git a/drivers/staging/media/vxd/common/ra.h b/drivers/staging/media/vxd/common/ra.h
new file mode 100644
index 000000000000..a4d529d635d7
--- /dev/null
+++ b/drivers/staging/media/vxd/common/ra.h
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Implements generic resource allocation.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@xxxxxx>
+ *
+ * Re-written for upstream
+ *      Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
+ */
+#ifndef _RA_H_
+#define _RA_H_
+
+#define MINIMUM_HASH_SIZE  (64)
+#define FREE_TABLE_LIMIT   (64)
+
+/* Defines whether sequential or random allocation is used */
+enum {
+	RA_SEQUENTIAL_ALLOCATION = 0,
+	RA_RANDOM_ALLOCATION,
+	RA_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Defines boundary tag type */
+enum eboundary_tag_type {
+	RA_BOUNDARY_TAG_TYPE_SPAN = 0,
+	RA_BOUNDARY_TAG_TYPE_FREE,
+	RA_BOUNDARY_TAG_TYPE_LIVE,
+	RA_BOUNDARY_TAG_TYPE_MAX,
+	RA_BOUNDARY_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * @Description
+ * Boundary tags, used to describe a resource segment
+ *
+ * @enum0: span markers
+ * @enum1: free resource segment
+ * @enum2: allocated resource segment
+ * @enum3: max
+ * @base,size: The base resource of this segment and extent of this segment
+ * @nxt_seg, prv_seg: doubly linked ordered list of all segments
+ *			within the arena
+ * @nxt_free, prv_free: doubly linked un-ordered list of free segments
+ * @reference : a user reference associated with this span, user
+ *		references are currently only provided in
+ *		the callback mechanism
+ */
+struct btag {
+	unsigned int bt_type;
+	unsigned long long base;
+	unsigned long long size;
+	struct btag *nxt_seg;
+	struct btag *prv_seg;
+	struct btag *nxt_free;
+	struct btag *prv_free;
+	void *ref;
+};
+
+/*
+ * @Description
+ * resource allocation arena
+ *
+ * @name: arena for diagnostics output
+ * @quantum: allocations within this arena are quantum sized
+ * @max_idx: index of the last position in the psBTHeadFree table,
+ *		with available free space
+ * @import_alloc_fxn: import interface, if provided
+ * @import_free_fxn: import interface, if provided
+ * @import_hdnl: import interface, if provided
+ * @head_free: head of list of free boundary tags for indexed by Log2
+ *		of the boundary tag size. Power-of-two table of free lists
+ * @head_seg, tail_seg : resource ordered segment list
+ * @ps_hash : segment address to boundary tag hash table
+ */
+struct arena {
+	unsigned char *name;
+	unsigned long quantum;
+	unsigned int max_idx;
+	int (*import_alloc_fxn)(void *import_hdnl,
+				unsigned long long requested_size,
+				unsigned long long *actual_size,
+				void **ref,
+				unsigned int alloc_flags,
+				unsigned long long *base_addr);
+	int (*import_free_fxn)(void *import_hdnl,
+			       unsigned long long base,
+			       void *ref);
+	void *import_hdnl;
+	struct btag *head_free[FREE_TABLE_LIMIT];
+	struct btag *head_seg;
+	struct btag *tail_seg;
+	struct hash *hash_tbl;
+};
+
+/*
+ * @Function	vid_ra_init
+ * @Description	Initializes the RA module. Must be called before any other
+ *		ra API function
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_initialise(void);
+
+/*
+ * @Function	vid_ra_deinit
+ * @Description	Deinitializes the RA module
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_deinit(void);
+
+/*
+ * @Function	vid_ra_create
+ * @Description	Used to create a resource arena.
+ * @Input	name: The name of the arena for diagnostic purposes
+ * @Input	base_arg: The base of an initial resource span or 0
+ * @Input	size_arg: The size of an initial resource span or 0
+ * @Input	quantum: The arena allocation quantum
+ * @Input	(*import_alloc_fxn): A resource allocation callback or NULL
+ * @Input	(*import_free_fxn): A resource de-allocation callback or NULL
+ * @Input	import_hdnl: Handle passed to alloc and free or NULL
+ * @Output	arena_hndl: The handle for the arene being created, or NULL
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_create(const unsigned char * const name,
+		  unsigned long long base_arg,
+		  unsigned long long size_arg,
+		  unsigned long quantum,
+		  int (*import_alloc_fxn)(void * const import_hdnl,
+					  unsigned long long req_sz,
+					  unsigned long long * const actl_sz,
+					  void ** const ref,
+					  unsigned int alloc_flags,
+					  unsigned long long * const base_arg),
+		  int (*import_free_fxn)(void * const import_hdnl,
+					 unsigned long long import_base,
+					 void * const import_ref),
+		  void *import_hdnl,
+		  void **arena_hndl);
+
+/*
+ * @Function	vid_ra_delete
+ * @Description	Used to delete a resource arena. All resources allocated from
+ *		the arena must be freed before deleting the arena
+ * @Input	arena_hndl: The handle to the arena to delete
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_delete(void * const arena_hndl);
+
+/*
+ * @Function	vid_ra_add
+ * @Description	Used to add a resource span to an arena. The span must not
+ *		overlap with any span previously added to the arena
+ * @Input	base_arg: The base_arg of the span
+ * @Input	size_arg: The size of the span
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_add(void * const arena_hndl, unsigned long long base_arg, unsigned long long size_arg);
+
+/*
+ * @Function	vid_ra_alloc
+ * @Description	Used to allocate resource from an arena
+ * @Input	arena_hndl: The handle to the arena to create the resource
+ * @Input	request_size: The requested size of resource segment
+ * @Input	actl_size: The actualSize of resource segment
+ * @Input	ref: The user reference associated with allocated resource
+ *		span
+ * @Input	alloc_flags: AllocationFlags influencing allocation policy
+ * @Input	align_arg: The alignment constraint required for the allocated
+ *		segment
+ * @Output	base_args: The base of the allocated resource
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_alloc(void * const arena_hndl,
+		 unsigned long long request_size,
+		 unsigned long long * const actl_sz,
+		 void ** const ref,
+		 unsigned int alloc_flags,
+		 unsigned long long align_arg,
+		 unsigned long long * const base_arg);
+
+/*
+ * @Function	vid_ra_free
+ * @Description	Used to free a resource segment
+ * @Input	arena_hndl: The arena the segment was originally allocated from
+ * @Input	base_arg: The base of the span
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_free(void * const arena_hndl, unsigned long long base_arg);
+
+#endif
diff --git a/drivers/staging/media/vxd/common/talmmu_api.c b/drivers/staging/media/vxd/common/talmmu_api.c
new file mode 100644
index 000000000000..04ddcc33505c
--- /dev/null
+++ b/drivers/staging/media/vxd/common/talmmu_api.c
@@ -0,0 +1,753 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TAL MMU Extensions.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@xxxxxx>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
+ */
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_errors.h"
+#include "lst.h"
+#include "talmmu_api.h"
+
+static int global_init;
+static struct lst_t gl_dmtmpl_lst = {0};
+static struct mutex *global_lock;
+
+static int talmmu_devmem_free(void *mem_hndl)
+{
+	struct talmmu_memory *mem = mem_hndl;
+	struct talmmu_devmem_heap *mem_heap;
+
+	if (!mem_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	mem_heap = mem->devmem_heap;
+
+	if (!mem->ext_dev_virtaddr)
+		addr_cx_free(&mem_heap->ctx, "", mem->dev_virtoffset);
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	lst_remove(&mem_heap->memory_list, mem);
+
+	mutex_unlock(global_lock);
+
+	kfree(mem);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * talmmu_devmem_heap_empty - talmmu_devmem_heap_empty
+ * @devmem_heap_hndl: device memory heap handle
+ *
+ * This function is used for emptying the device memory heap list
+ */
+int talmmu_devmem_heap_empty(void *devmem_heap_hndl)
+{
+	struct talmmu_devmem_heap *devmem_heap = devmem_heap_hndl;
+
+	if (!devmem_heap)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	while (!lst_empty(&devmem_heap->memory_list))
+		talmmu_devmem_free(lst_first(&devmem_heap->memory_list));
+
+	addr_cx_deinitialise(&devmem_heap->ctx);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_heap_destroy
+ *
+ * @Description	This function is used for freeing the device memory heap
+ *
+ * @Input
+ *
+ * @Output
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+static void talmmu_devmem_heap_destroy(void *devmem_heap_hndl)
+{
+	struct talmmu_devmem_heap *devmem_heap = devmem_heap_hndl;
+
+	talmmu_devmem_heap_empty(devmem_heap_hndl);
+	kfree(devmem_heap);
+}
+
+/*
+ * @Function	talmmu_init
+ *
+ * @Description	This function is used to initialize the TALMMU component.
+ *
+ * @Input	None.
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_init(void)
+{
+	if (!global_init) {
+		/* If no mutex associated with this resource */
+		if (!global_lock) {
+			/* Create one */
+			global_lock = kzalloc(sizeof(*global_lock), GFP_KERNEL);
+			if (!global_lock)
+				return IMG_ERROR_OUT_OF_MEMORY;
+
+			mutex_init(global_lock);
+		}
+
+		lst_init(&gl_dmtmpl_lst);
+		global_init = 1;
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_deinit
+ *
+ * @Description	This function is used to de-initialize the TALMMU component.
+ *
+ * @Input	None.
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_deinit(void)
+{
+	struct talmmu_dm_tmpl *t;
+
+	if (global_init) {
+		while (!lst_empty(&gl_dmtmpl_lst)) {
+			t = (struct talmmu_dm_tmpl *)lst_first(&gl_dmtmpl_lst);
+			talmmu_devmem_template_destroy((void *)t);
+		}
+		mutex_destroy(global_lock);
+		kfree(global_lock);
+		global_lock = NULL;
+		global_init = 0;
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_template_create
+ *
+ * @Description	This function is used to create a device memory template
+ *
+ * @Input	devmem_info:  A pointer to a talmmu_devmem_info structure.
+ *
+ * @Output	devmem_template_hndl: A pointer used to return the template
+ *		handle
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_template_create(struct talmmu_devmem_info *devmem_info,
+				  void **devmem_template_hndl)
+{
+	struct talmmu_dm_tmpl *devmem_template;
+	struct talmmu_dm_tmpl *tmp_devmem_template;
+
+	if (!devmem_info)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	devmem_template = kzalloc(sizeof(*devmem_template), GFP_KERNEL);
+	if (!devmem_template)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	devmem_template->devmem_info = *devmem_info;
+
+	lst_init(&devmem_template->devmem_ctx_list);
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	tmp_devmem_template = lst_first(&gl_dmtmpl_lst);
+	while (tmp_devmem_template)
+		tmp_devmem_template = lst_next(tmp_devmem_template);
+
+	devmem_template->page_num_shift = 12;
+	devmem_template->byte_in_pagemask = 0xFFF;
+	devmem_template->heap_alignment = 0x400000;
+	devmem_template->pagetable_entries_perpage =
+		(devmem_template->devmem_info.page_size / sizeof(unsigned int));
+	devmem_template->pagetable_num_shift = 10;
+	devmem_template->index_in_pagetable_mask = 0x3FF;
+	devmem_template->pagedir_num_shift = 22;
+
+	lst_add(&gl_dmtmpl_lst, devmem_template);
+
+	mutex_unlock(global_lock);
+
+	*devmem_template_hndl = devmem_template;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_template_destroy
+ *
+ * @Description This function is used to obtain the template from the list and
+ *		destroy
+ *
+ * @Input	devmem_tmplt_hndl: Device memory template handle
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_template_destroy(void *devmem_tmplt_hndl)
+{
+	struct talmmu_dm_tmpl *dm_tmpl = devmem_tmplt_hndl;
+	unsigned int i;
+
+	if (!devmem_tmplt_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	while (!lst_empty(&dm_tmpl->devmem_ctx_list))
+		talmmu_devmem_ctx_destroy(lst_first(&dm_tmpl->devmem_ctx_list));
+
+	for (i = 0; i < dm_tmpl->num_heaps; i++)
+		talmmu_devmem_heap_destroy(dm_tmpl->devmem_heap[i]);
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	lst_remove(&gl_dmtmpl_lst, dm_tmpl);
+
+	mutex_unlock(global_lock);
+
+	kfree(dm_tmpl);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_create_heap
+ *
+ * @Description	This function is used to create a device memory heap
+ *
+ * @Input
+ *
+ * @Output
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+static int talmmu_create_heap(void *devmem_tmplt_hndl,
+			      struct talmmu_heap_info *heap_info_arg,
+			      unsigned char isfull,
+			      struct talmmu_devmem_heap **devmem_heap_arg)
+{
+	struct talmmu_dm_tmpl *devmem_template = devmem_tmplt_hndl;
+	struct talmmu_devmem_heap *devmem_heap;
+
+	/* Allocating memory for device memory heap */
+	devmem_heap = kzalloc(sizeof(*devmem_heap), GFP_KERNEL);
+	if (!devmem_heap)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/*
+	 * Update the device memory heap structure members
+	 * Update the device memory template
+	 */
+	devmem_heap->devmem_template = devmem_template;
+	/* Update the device memory heap information */
+	devmem_heap->heap_info = *heap_info_arg;
+
+	/* Initialize the device memory heap list */
+	lst_init(&devmem_heap->memory_list);
+
+	/* If full structure required */
+	if (isfull) {
+		addr_cx_initialise(&devmem_heap->ctx);
+		devmem_heap->regions.base_addr = 0;
+		devmem_heap->regions.size = devmem_heap->heap_info.size;
+		addr_cx_define_mem_region(&devmem_heap->ctx,
+					  &devmem_heap->regions);
+	}
+
+	*devmem_heap_arg = devmem_heap;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_heap_add
+ *
+ * @Description	This function is for creating and adding the heap to the
+ *		device memory template
+ *
+ * @Input	devmem_tmplt_hndl: device memory template handle
+ *
+ * @Input	heap_info_arg: pointer to the heap info structure
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_heap_add(void *devmem_tmplt_hndl,
+			   struct talmmu_heap_info *heap_info_arg)
+{
+	struct talmmu_dm_tmpl *devmem_template = devmem_tmplt_hndl;
+	struct talmmu_devmem_heap *devmem_heap;
+	unsigned int res;
+
+	if (!devmem_tmplt_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (!heap_info_arg)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	res = talmmu_create_heap(devmem_tmplt_hndl,
+				 heap_info_arg,
+				 1,
+				 &devmem_heap);
+	if (res != IMG_SUCCESS)
+		return res;
+
+	devmem_template->devmem_heap[devmem_template->num_heaps] = devmem_heap;
+	devmem_template->num_heaps++;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_ctx_create
+ *
+ * @Description	This function is used to create a device memory context
+ *
+ * @Input	devmem_tmplt_hndl: pointer to the device memory template handle
+ *
+ * @Input	mmu_ctx_id: MMU context ID used with the TAL
+ *
+ * @Output	devmem_ctx_hndl: pointer to the device memory context handle
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_ctx_create(void *devmem_tmplt_hndl,
+			     unsigned int mmu_ctx_id,
+			     void **devmem_ctx_hndl)
+{
+	struct talmmu_dm_tmpl *dm_tmpl = devmem_tmplt_hndl;
+	struct talmmu_devmem_ctx *dm_ctx;
+	struct talmmu_devmem_heap *dm_heap;
+	int i;
+	unsigned int res = IMG_SUCCESS;
+
+	if (!devmem_tmplt_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Allocate memory for device memory context */
+	dm_ctx = kzalloc((sizeof(struct talmmu_devmem_ctx)), GFP_KERNEL);
+	if (!dm_ctx)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/*
+	 * Update the device memory context structure members
+	 * Update the device memory template
+	 */
+	dm_ctx->devmem_template = dm_tmpl;
+	/* Update MMU context ID */
+	dm_ctx->mmu_ctx_id = mmu_ctx_id;
+
+	/* Check for PTD Alignment */
+	if (dm_tmpl->devmem_info.ptd_alignment == 0)
+		/*
+		 * Make sure alignment is a multiple of page size.
+		 * Set up PTD alignment to Page Size
+		 */
+		dm_tmpl->devmem_info.ptd_alignment =
+			dm_tmpl->devmem_info.page_size;
+
+	/* Reference or create heaps for this context */
+	for (i = 0; i < dm_tmpl->num_heaps; i++) {
+		dm_heap = dm_tmpl->devmem_heap[i];
+		if (!dm_heap)
+			goto error_heap_create;
+
+		switch (dm_heap->heap_info.heap_type) {
+		case TALMMU_HEAP_PERCONTEXT:
+			res = talmmu_create_heap(dm_tmpl,
+						 &dm_heap->heap_info,
+						 1,
+						 &dm_ctx->devmem_heap[i]);
+			if (res != IMG_SUCCESS)
+				goto error_heap_create;
+			break;
+
+		default:
+			break;
+		}
+
+		dm_ctx->num_heaps++;
+	}
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	/* Add the device memory context to the list */
+	lst_add(&dm_tmpl->devmem_ctx_list, dm_ctx);
+
+	dm_tmpl->num_ctxs++;
+
+	mutex_unlock(global_lock);
+
+	*devmem_ctx_hndl = dm_ctx;
+
+	return IMG_SUCCESS;
+
+error_heap_create:
+	/* Destroy the device memory heaps which were already created */
+	for (i--; i >= 0; i--) {
+		dm_heap = dm_ctx->devmem_heap[i];
+		if (dm_heap->heap_info.heap_type == TALMMU_HEAP_PERCONTEXT)
+			talmmu_devmem_heap_destroy(dm_heap);
+
+		dm_ctx->num_heaps--;
+	}
+	kfree(dm_ctx);
+	return res;
+}
+
+/*
+ * @Function	talmmu_devmem_ctx_destroy
+ *
+ * @Description	This function is used to get the device memory context from
+ *		the list and destroy
+ *
+ * @Input	devmem_ctx_hndl: device memory context handle
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_ctx_destroy(void *devmem_ctx_hndl)
+{
+	struct talmmu_devmem_ctx *devmem_ctx = devmem_ctx_hndl;
+	struct talmmu_dm_tmpl *devmem_template;
+	struct talmmu_devmem_heap *devmem_heap;
+	unsigned int i;
+
+	if (!devmem_ctx_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	devmem_template = devmem_ctx->devmem_template;
+
+	for (i = 0; i < devmem_ctx->num_heaps; i++) {
+		devmem_heap = devmem_ctx->devmem_heap[i];
+		if (!devmem_heap)
+			return IMG_ERROR_INVALID_PARAMETERS;
+
+		talmmu_devmem_heap_destroy(devmem_heap);
+	}
+
+	devmem_ctx->pagedir = NULL;
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	lst_remove(&devmem_template->devmem_ctx_list, devmem_ctx);
+
+	devmem_ctx->devmem_template->num_ctxs--;
+
+	mutex_unlock(global_lock);
+
+	kfree(devmem_ctx);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_get_heap_handle
+ *
+ * @Description	This function is used to get the device memory heap handle
+ *
+ * @Input	hid: heap id
+ *
+ * @Input	devmem_ctx_hndl: device memory context handle
+ *
+ * @Output	devmem_heap_hndl: pointer to the device memory heap handle
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_get_heap_handle(unsigned int hid,
+			   void *devmem_ctx_hndl,
+			   void **devmem_heap_hndl)
+{
+	struct talmmu_devmem_ctx *devmem_ctx = devmem_ctx_hndl;
+	unsigned int i;
+
+	if (!devmem_ctx_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	for (i = 0; i < devmem_ctx->num_heaps; i++) {
+		/*
+		 * Checking for requested heap id match and return the device
+		 * memory heap handle
+		 */
+		if (devmem_ctx->devmem_heap[i]->heap_info.heap_id == hid) {
+			*devmem_heap_hndl = devmem_ctx->devmem_heap[i];
+			return IMG_SUCCESS;
+		}
+	}
+
+	return IMG_ERROR_GENERIC_FAILURE;
+}
+
+/*
+ * @Function	talmmu_devmem_heap_options
+ *
+ * @Description	This function is used to set additional heap options
+ *
+ * @Input	devmem_heap_hndl: Handle for heap
+ *
+ * @Input	heap_opt_id: Heap options ID
+ *
+ * @Input	heap_options: Heap options
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+void talmmu_devmem_heap_options(void *devmem_heap_hndl,
+				enum talmmu_heap_option_id heap_opt_id,
+				union talmmu_heap_options heap_options)
+{
+	struct talmmu_devmem_heap *dm_heap = devmem_heap_hndl;
+
+	switch (heap_opt_id) {
+	case TALMMU_HEAP_OPT_ADD_GUARD_BAND:
+		dm_heap->guardband = heap_options.guardband_opt.guardband;
+		break;
+	default:
+		break;
+	}
+}
+
+/*
+ * @Function	talmmu_devmem_malloc_nonmap
+ *
+ * @Description
+ *
+ * @Input
+ *
+ * @Output
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+static int talmmu_devmem_alloc_nonmap(void *devmem_ctx_hndl,
+				      void *devmem_heap_hndl,
+				      unsigned int size,
+				      unsigned int align,
+				      unsigned int dev_virt_ofset,
+				      unsigned char ext_dev_vaddr,
+				      void **mem_hndl)
+{
+	struct talmmu_devmem_ctx *dm_ctx = devmem_ctx_hndl;
+	struct talmmu_dm_tmpl *dm_tmpl;
+	struct talmmu_devmem_heap *dm_heap = devmem_heap_hndl;
+	struct talmmu_memory *mem;
+	unsigned long long ui64_dev_offset = 0;
+	int res = IMG_SUCCESS;
+
+	if (!dm_ctx)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (!devmem_heap_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	dm_tmpl = dm_ctx->devmem_template;
+
+	/* Allocate memory for memory structure */
+	mem = kzalloc((sizeof(struct talmmu_memory)), GFP_KERNEL);
+	if (!mem)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	mem->devmem_heap = dm_heap;
+	mem->devmem_ctx = dm_ctx;
+	mem->ext_dev_virtaddr = ext_dev_vaddr;
+
+	/* We always for to be at least page aligned */
+	if (align >= dm_tmpl->devmem_info.page_size)
+		/*
+		 * alignment is larger than page size - make sure alignment is
+		 * a multiple of page size
+		 */
+		mem->alignment = align;
+	else
+		/*
+		 * alignment is smaller than page size - make sure page size is
+		 * a multiple of alignment. Now round up alignment to one page
+		 */
+		mem->alignment = dm_tmpl->devmem_info.page_size;
+
+	/* Round size up to next multiple of physical pages */
+	if ((size % dm_tmpl->devmem_info.page_size) != 0)
+		mem->size = ((size / dm_tmpl->devmem_info.page_size)
+			+ 1) * dm_tmpl->devmem_info.page_size;
+	else
+		mem->size = size;
+
+	/* If the device virtual address was externally defined */
+	if (mem->ext_dev_virtaddr) {
+		res = IMG_ERROR_INVALID_PARAMETERS;
+		goto free_mem;
+	}
+
+	res = addr_cx_malloc_align_res(&dm_heap->ctx, "",
+				       (mem->size + dm_heap->guardband),
+				       mem->alignment,
+				       &ui64_dev_offset);
+
+	mem->dev_virtoffset = (unsigned int)ui64_dev_offset;
+	if (res != IMG_SUCCESS)
+		/*
+		 * If heap space is unavaliable return NULL, the caller must
+		 * handle this condition
+		 */
+		goto free_virt;
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	/*
+	 * Add memory allocation to the list for this heap...
+	 * If the heap is empty...
+	 */
+	if (lst_empty(&dm_heap->memory_list))
+		/*
+		 * Save flag to indicate whether the device virtual address
+		 * is allocated internally or externally...
+		 */
+		dm_heap->ext_dev_virtaddr = mem->ext_dev_virtaddr;
+
+	/*
+	 * Once we have started allocating in one way ensure that we continue
+	 * to do this...
+	 */
+	lst_add(&dm_heap->memory_list, mem);
+
+	mutex_unlock(global_lock);
+
+	*mem_hndl = mem;
+
+	return IMG_SUCCESS;
+
+free_virt:
+	addr_cx_free(&dm_heap->ctx, "", mem->dev_virtoffset);
+free_mem:
+	kfree(mem);
+
+	return res;
+}
+
+/*
+ * @Function	talmmu_devmem_addr_alloc
+ *
+ * @Description
+ *
+ * @Input
+ *
+ * @Output
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_addr_alloc(void *devmem_ctx_hndl,
+			     void *devmem_heap_hndl,
+			     unsigned int size,
+			     unsigned int align,
+			     void **mem_hndl)
+{
+	unsigned int res;
+	void *mem;
+
+	res = talmmu_devmem_alloc_nonmap(devmem_ctx_hndl,
+					 devmem_heap_hndl,
+					 size,
+					 align,
+					 0,
+					 0,
+					 &mem);
+	if (res != IMG_SUCCESS)
+		return res;
+
+	*mem_hndl = mem;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_addr_free
+ *
+ * @Description	This function is used to free device memory allocated using
+ *		talmmu_devmem_addr_alloc().
+ *
+ * @Input	mem_hndl : Handle for the memory object
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_addr_free(void *mem_hndl)
+{
+	unsigned int res;
+
+	if (!mem_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* free device memory allocated by calling talmmu_devmem_free() */
+	res = talmmu_devmem_free(mem_hndl);
+
+	return res;
+}
+
+/*
+ * @Function	talmmu_get_dev_virt_addr
+ *
+ * @Description	This function is use to obtain the device (virtual) memory
+ *		address which may be required for as a device virtual address
+ *		in some of the TAL image functions
+ *
+ * @Input	mem_hndl : Handle for the memory object
+ *
+ * @Output	dev_virt: A piointer used to return the device virtual address
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_get_dev_virt_addr(void *mem_hndl,
+			     unsigned int *dev_virt)
+{
+	struct talmmu_memory *mem = mem_hndl;
+	struct talmmu_devmem_heap *devmem_heap;
+
+	if (!mem_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	devmem_heap = mem->devmem_heap;
+
+	/*
+	 * Device virtual address is addition of the specific device virtual
+	 * offset and the base device virtual address from the heap information
+	 */
+	*dev_virt = (devmem_heap->heap_info.basedev_virtaddr +
+		mem->dev_virtoffset);
+
+	return IMG_SUCCESS;
+}
diff --git a/drivers/staging/media/vxd/common/talmmu_api.h b/drivers/staging/media/vxd/common/talmmu_api.h
new file mode 100644
index 000000000000..f37f78394d54
--- /dev/null
+++ b/drivers/staging/media/vxd/common/talmmu_api.h
@@ -0,0 +1,246 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TAL MMU Extensions.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@xxxxxx>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@xxxxxxxxxxxxxxxxxxx>
+ */
+#include "addr_alloc.h"
+#include "ra.h"
+#include "lst.h"
+
+#ifndef __TALMMU_API_H__
+#define __TALMMU_API_H__
+
+#define	TALMMU_MAX_DEVICE_HEAPS	(32)
+#define	TALMMU_MAX_TEMPLATES	(32)
+
+/* MMU type */
+enum talmmu_mmu_type {
+	/* 4kb pages and 32-bit address range */
+	TALMMU_MMUTYPE_4K_PAGES_32BIT_ADDR = 0x1,
+	/* variable size pages and 32-bit address */
+	TALMMU_MMUTYPE_VAR_PAGES_32BIT_ADDR,
+	/* 4kb pages and 36-bit address range */
+	TALMMU_MMUTYPE_4K_PAGES_36BIT_ADDR,
+	/* 4kb pages and 40-bit address range */
+	TALMMU_MMUTYPE_4K_PAGES_40BIT_ADDR,
+	/* variable size pages and 40-bit address range */
+	TALMMU_MMUTYPE_VP_40BIT,
+	TALMMU_MMUTYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Device flags */
+enum talmmu_dev_flags {
+	TALMMU_DEVFLAGS_NONE = 0x0,
+	TALMMU_DEVFLAGS_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Heap type */
+enum talmmu_heap_type {
+	TALMMU_HEAP_SHARED_EXPORTED,
+	TALMMU_HEAP_PERCONTEXT,
+	TALMMU_HEAP_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Heap flags */
+enum talmmu_eheapflags {
+	TALMMU_HEAPFLAGS_NONE = 0x0,
+	TALMMU_HEAPFLAGS_SET_CACHE_CONSISTENCY = 0x00000001,
+	TALMMU_HEAPFLAGS_128BYTE_INTERLEAVE = 0x00000002,
+	TALMMU_HEAPFLAGS_256BYTE_INTERLEAVE = 0x00000004,
+	TALMMU_HEAPFLAGS_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Contains the device memory information */
+struct talmmu_devmem_info {
+	/* device id */
+	unsigned int device_id;
+	/* mmu type */
+	enum talmmu_mmu_type mmu_type;
+	/* Device flags - bit flags that can be combined */
+	enum talmmu_dev_flags dev_flags;
+	/* Name of the memory space for page directory allocations */
+	unsigned char *pagedir_memspace_name;
+	/* Name of the memory space for page table allocations */
+	unsigned char *pagetable_memspace_name;
+	/* Page size in bytes */
+	unsigned int page_size;
+	/* PTD alignment, must be multiple of Page size */
+	unsigned int ptd_alignment;
+};
+
+struct talmmu_heap_info {
+	/* heap id */
+	unsigned int heap_id;
+	/* heap type */
+	enum talmmu_heap_type heap_type;
+	/* heap flags - bit flags that can be combined */
+	enum talmmu_eheapflags heap_flags;
+	/* Name of the memory space for memory allocations */
+	unsigned char *memspace_name;
+	/* Base device virtual address */
+	unsigned int basedev_virtaddr;
+	/* size in bytes */
+	unsigned int size;
+};
+
+/* Device memory template information */
+struct talmmu_dm_tmpl {
+	/* list */
+	struct lst_t list;
+	/* Copy of device memory info structure */
+	struct talmmu_devmem_info devmem_info;
+	/* Memory space ID for PTD allocations */
+	void *ptd_memspace_hndl;
+	/* Memory space ID for Page Table allocations */
+	void *ptentry_memspace_hndl;
+	/* number of heaps */
+	unsigned int num_heaps;
+	/* Array of heap pointers */
+	struct talmmu_devmem_heap *devmem_heap[TALMMU_MAX_DEVICE_HEAPS];
+	/* Number of active contexts */
+	unsigned int num_ctxs;
+	/* List of device memory context created from this template */
+	struct lst_t devmem_ctx_list;
+	/* Number of bits to shift right to obtain page number */
+	unsigned int page_num_shift;
+	/* Mask to extract byte-within-page */
+	unsigned int byte_in_pagemask;
+	/* Heap alignment */
+	unsigned int heap_alignment;
+	/* Page table entries/page */
+	unsigned int pagetable_entries_perpage;
+	/* Number of bits to shift right to obtain page table number */
+	unsigned int pagetable_num_shift;
+	/* Mask to extract index-within-page-table */
+	unsigned int index_in_pagetable_mask;
+	/* Number of bits to shift right to obtain page dir number */
+	unsigned int pagedir_num_shift;
+};
+
+/* Device memory heap information */
+struct talmmu_devmem_heap {
+	/* list item */
+	struct lst_t list;
+	/* Copy of the heap info structure */
+	struct talmmu_heap_info heap_info;
+	/* Pointer to the device memory template */
+	struct talmmu_dm_tmpl *devmem_template;
+	/* true if device virtual address offset allocated externally by user */
+	unsigned int ext_dev_virtaddr;
+	/* list of memory allocations */
+	struct lst_t memory_list;
+	/* Memory space ID for memory allocations */
+	void *memspace_hndl;
+	/* Address context structure */
+	struct addr_context ctx;
+	/* Regions structure */
+	struct addr_region regions;
+	/* size of heap guard band */
+	unsigned int guardband;
+};
+
+struct talmmu_devmem_ctx {
+	/* list item */
+	struct lst_t list;
+	/* Pointer to device template */
+	struct talmmu_dm_tmpl *devmem_template;
+	/* No. of heaps */
+	unsigned int num_heaps;
+	/* Array of heap pointers */
+	struct talmmu_devmem_heap *devmem_heap[TALMMU_MAX_DEVICE_HEAPS];
+	/* The MMU context id */
+	unsigned int mmu_ctx_id;
+	/* Pointer to the memory that represents Page directory */
+	unsigned int *pagedir;
+};
+
+struct talmmu_memory {
+	/* list item */
+	struct lst_t list;
+	/* Heap from which memory was allocated */
+	struct talmmu_devmem_heap *devmem_heap;
+	/* Context through which memory was allocated */
+	struct talmmu_devmem_ctx *devmem_ctx;
+	/* size */
+	unsigned int size;
+	/* alignment */
+	unsigned int alignment;
+	/* device virtual offset of allocation */
+	unsigned int dev_virtoffset;
+	/* true if device virtual address offset allocated externally by user */
+	unsigned int ext_dev_virtaddr;
+};
+
+/* This type defines the event types for the TALMMU callbacks */
+enum talmmu_event {
+	/* Function to flush the cache. */
+	TALMMU_EVENT_FLUSH_CACHE,
+	/*! Function to write the page directory address to the device */
+	TALMMU_EVENT_WRITE_PAGE_DIRECTORY_REF,
+	/* Placeholder*/
+	TALMMU_NO_OF_EVENTS
+};
+
+enum talmmu_heap_option_id {
+	/* Add guard band to all mallocs */
+	TALMMU_HEAP_OPT_ADD_GUARD_BAND,
+	TALMMU_HEAP_OPT_SET_MEM_ATTRIB,
+	TALMMU_HEAP_OPT_SET_MEM_POOL,
+
+	/* Placeholder */
+	TALMMU_NO_OF_OPTIONS,
+	TALMMU_NO_OF_FORCE32BITS = 0x7FFFFFFFU
+};
+
+struct talmmu_guardband_options {
+	unsigned int guardband;
+};
+
+union talmmu_heap_options {
+	/* Guardband parameters */
+	struct talmmu_guardband_options guardband_opt;
+};
+
+int talmmu_init(void);
+int talmmu_deinit(void);
+int talmmu_devmem_template_create(struct talmmu_devmem_info *devmem_info,
+				  void **devmem_template_hndl);
+int talmmu_devmem_heap_add(void *devmem_tmplt_hndl,
+			   struct talmmu_heap_info *heap_info_arg);
+int talmmu_devmem_template_destroy(void *devmem_tmplt_hndl);
+int talmmu_devmem_ctx_create(void *devmem_tmplt_hndl,
+			     unsigned int mmu_ctx_id,
+			     void **devmem_ctx_hndl);
+int talmmu_devmem_ctx_destroy(void *devmem_ctx_hndl);
+int talmmu_get_heap_handle(unsigned int hid,
+			   void *devmem_ctx_hndl,
+			   void **devmem_heap_hndl);
+/**
+ * talmmu_devmem_heap_empty - talmmu_devmem_heap_empty
+ * @devmem_heap_hndl: device memory heap handle
+ *
+ * This function is used for emptying the device memory heap list
+ */
+
+int talmmu_devmem_heap_empty(void *devmem_heap_hndl);
+void talmmu_devmem_heap_options(void *devmem_heap_hndl,
+				enum talmmu_heap_option_id heap_opt_id,
+				union talmmu_heap_options heap_options);
+int talmmu_devmem_addr_alloc(void *devmem_ctx_hndl,
+			     void *devmem_heap_hndl,
+			     unsigned int size,
+			     unsigned int align,
+			     void **mem_hndl);
+int talmmu_devmem_addr_free(void *mem_hndl);
+int talmmu_get_dev_virt_addr(void *mem_hndl,
+			     unsigned int *dev_virt);
+
+#endif /* __TALMMU_API_H__ */
-- 
2.17.1


-- 






This
message contains confidential information and is intended only 
for the
individual(s) named. If you are not the intended
recipient, you are 
notified that disclosing, copying, distributing or taking any
action in 
reliance on the contents of this mail and attached file/s is strictly
prohibited. Please notify the
sender immediately and delete this e-mail 
from your system. E-mail transmission
cannot be guaranteed to be secured or 
error-free as information could be
intercepted, corrupted, lost, destroyed, 
arrive late or incomplete, or contain
viruses. The sender therefore does 
not accept liability for any errors or
omissions in the contents of this 
message, which arise as a result of e-mail
transmission.





[Index of Archives]     [Linux Driver Development]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux