summaryrefslogtreecommitdiff
path: root/drivers/dsp/bridge/rmgr/drv_interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dsp/bridge/rmgr/drv_interface.c')
-rw-r--r--drivers/dsp/bridge/rmgr/drv_interface.c760
1 files changed, 760 insertions, 0 deletions
diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c b/drivers/dsp/bridge/rmgr/drv_interface.c
new file mode 100644
index 000000000000..a81b12d21625
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/drv_interface.c
@@ -0,0 +1,760 @@
+/*
+ * drv_interface.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * ======== linux_driver.c ========
+ * Description:
+ * DSP/BIOS Bridge driver interface.
+ *
+ * Public Functions:
+ * driver_init
+ * driver_exit
+ * driver_open
+ * driver_release
+ * driver_ioctl
+ * driver_mmap
+ *
+ *! Revision History
+ *! ================
+ *! 21-Apr-2004 map Deprecated use of MODULE_PARM for kernel versions
+ *! greater than 2.5, use module_param.
+ *! 08-Mar-2004 sb Added the dsp_debug argument, which keeps the DSP in self
+ *! loop after image load and waits in a loop for DSP to start
+ *! 16-Feb-2004 vp Deprecated the usage of MOD_INC_USE_COUNT and
+ *! MOD_DEC_USE_COUNT
+ *! for kernel versions greater than 2.5
+ *! 20-May-2003 vp Added unregister functions for the DPM.
+ *! 24-Mar-2003 sb Pass pid instead of driverContext to DSP_Close
+ *! 24-Mar-2003 vp Added Power Management support.
+ *! 21-Mar-2003 sb Configure SHM size using insmod argument shm_size
+ *! 10-Feb-2003 vp Updated based on code review comments
+ *! 18-Oct-2002 sb Created initial version
+ */
+
+/* ----------------------------------- Host OS */
+
+#include <dspbridge/host_os.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/cdev.h>
+#ifdef CONFIG_PM
+#include <mach/board-3430sdp.h>
+#endif
+
+/* ----------------------------------- DSP/BIOS Bridge */
+#include <dspbridge/std.h>
+#include <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/* ----------------------------------- Trace & Debug */
+#include <dspbridge/gt.h>
+#include <dspbridge/dbc.h>
+
+/* ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/services.h>
+#include <dspbridge/sync.h>
+#include <dspbridge/reg.h>
+#include <dspbridge/csl.h>
+
+/* ----------------------------------- Platform Manager */
+#include <dspbridge/wcdioctl.h>
+#include <dspbridge/_dcd.h>
+#include <dspbridge/dspdrv.h>
+#include <dspbridge/dbreg.h>
+
+/* ----------------------------------- Resource Manager */
+#include <dspbridge/pwr.h>
+
+/* ----------------------------------- This */
+#include <drv_interface.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <dspbridge/cfg.h>
+#include <dspbridge/resourcecleanup.h>
+#include <dspbridge/chnl.h>
+#include <dspbridge/proc.h>
+#include <dspbridge/cfg.h>
+#include <dspbridge/dev.h>
+#include <dspbridge/drvdefs.h>
+#include <dspbridge/drv.h>
+#include <dspbridge/dbreg.h>
+#endif
+#ifdef CONFIG_PM
+#include <mach/omap-pm.h>
+#include <mach-omap2/omap3-opp.h>
+#endif
+
+#define BRIDGE_NAME "C6410"
+/* ----------------------------------- Globals */
+#define DRIVER_NAME "DspBridge"
+#define DRIVER_MAJOR 0 /* Linux assigns our Major device number */
+#define DRIVER_MINOR 0 /* Linux assigns our Major device number */
+
+#ifdef OMAP44XX
+s32 dsp_debug = 1;
+#else
+s32 dsp_debug;
+#endif
+
+struct platform_device *omap_dspbridge_dev;
+
+struct bridge_dev {
+ struct cdev cdev;
+};
+
+static struct bridge_dev *bridge_device;
+
+static struct class *bridge_class;
+
+static u32 driverContext;
+#ifdef CONFIG_BRIDGE_DEBUG
+static char *GT_str;
+#endif /* CONFIG_BRIDGE_DEBUG */
+static s32 driver_major = DRIVER_MAJOR;
+static s32 driver_minor = DRIVER_MINOR;
+static char *base_img;
+char *iva_img;
+static char *num_procs = "C55=1";
+static s32 shm_size = 0x400000; /* 4 MB */
+static u32 phys_mempool_base;
+static u32 phys_mempool_size;
+static int tc_wordswapon; /* Default value is always false */
+
+#ifdef CONFIG_PM
+struct omap34xx_bridge_suspend_data {
+ int suspended;
+ wait_queue_head_t suspend_wq;
+};
+
+static struct omap34xx_bridge_suspend_data bridge_suspend_data;
+
+static int omap34xxbridge_suspend_lockout(
+ struct omap34xx_bridge_suspend_data *s, struct file *f)
+{
+ if ((s)->suspended) {
+ if ((f)->f_flags & O_NONBLOCK)
+ return DSP_EDPMSUSPEND;
+ wait_event_interruptible((s)->suspend_wq, (s)->suspended == 0);
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef DEBUG
+module_param(GT_str, charp, 0);
+MODULE_PARM_DESC(GT_str, "GT string, default = NULL");
+
+module_param(dsp_debug, int, 0);
+MODULE_PARM_DESC(dsp_debug, "Wait after loading DSP image. default = false");
+#endif
+
+module_param(driver_major, int, 0); /* Driver's major number */
+MODULE_PARM_DESC(driver_major, "Major device number, default = 0 (auto)");
+
+module_param(driver_minor, int, 0); /* Driver's major number */
+MODULE_PARM_DESC(driver_minor, "Minor device number, default = 0 (auto)");
+
+module_param(base_img, charp, 0);
+MODULE_PARM_DESC(base_img, "DSP base image, default = NULL");
+
+module_param(shm_size, int, 0);
+MODULE_PARM_DESC(shm_size, "SHM size, default = 4 MB, minimum = 64 KB");
+
+module_param(phys_mempool_base, uint, 0);
+MODULE_PARM_DESC(phys_mempool_base,
+ "Physical memory pool base passed to driver");
+
+module_param(phys_mempool_size, uint, 0);
+MODULE_PARM_DESC(phys_mempool_size,
+ "Physical memory pool size passed to driver");
+module_param(tc_wordswapon, int, 0);
+MODULE_PARM_DESC(tc_wordswapon, "TC Word Swap Option. default = 0");
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_LICENSE("GPL");
+
+static char *driver_name = DRIVER_NAME;
+
+#ifdef CONFIG_BRIDGE_DEBUG
+static struct GT_Mask driverTrace;
+#endif /* CONFIG_BRIDGE_DEBUG */
+
+static struct file_operations bridge_fops = {
+ .open = bridge_open,
+ .release = bridge_release,
+ .ioctl = bridge_ioctl,
+ .mmap = bridge_mmap,
+};
+
+#ifdef CONFIG_PM
+static u32 timeOut = 1000;
+#ifdef CONFIG_BRIDGE_DVFS
+static struct clk *clk_handle;
+s32 dsp_max_opps = VDD1_OPP5;
+#endif
+
+/* Maximum Opps that can be requested by IVA*/
+/*vdd1 rate table*/
+#ifdef CONFIG_BRIDGE_DVFS
+const struct omap_opp vdd1_rate_table_bridge[] = {
+ {0, 0, 0},
+ /*OPP1*/
+ {S125M, VDD1_OPP1, 0},
+ /*OPP2*/
+ {S250M, VDD1_OPP2, 0},
+ /*OPP3*/
+ {S500M, VDD1_OPP3, 0},
+ /*OPP4*/
+ {S550M, VDD1_OPP4, 0},
+ /*OPP5*/
+ {S600M, VDD1_OPP5, 0},
+};
+#endif
+#endif
+
+struct dspbridge_platform_data *omap_dspbridge_pdata;
+
+u32 vdd1_dsp_freq[6][4] = {
+ {0, 0, 0, 0},
+ /*OPP1*/
+ {0, 90000, 0, 86000},
+ /*OPP2*/
+ {0, 180000, 80000, 170000},
+ /*OPP3*/
+ {0, 360000, 160000, 340000},
+ /*OPP4*/
+ {0, 396000, 325000, 376000},
+ /*OPP5*/
+ {0, 430000, 355000, 430000},
+};
+
+#ifdef CONFIG_BRIDGE_DVFS
+static int dspbridge_post_scale(struct notifier_block *op, unsigned long level,
+ void *ptr)
+{
+ PWR_PM_PostScale(PRCM_VDD1, level);
+ return 0;
+}
+
+static struct notifier_block iva_clk_notifier = {
+ .notifier_call = dspbridge_post_scale,
+ NULL,
+};
+#endif
+
+static int __devinit omap34xx_bridge_probe(struct platform_device *pdev)
+{
+ int status;
+ u32 initStatus;
+ u32 temp;
+ dev_t dev = 0 ;
+ int result;
+#ifdef CONFIG_BRIDGE_DVFS
+ int i = 0;
+#endif
+ struct dspbridge_platform_data *pdata = pdev->dev.platform_data;
+
+ omap_dspbridge_dev = pdev;
+
+ /* use 2.6 device model */
+ if (driver_major) {
+ dev = MKDEV(driver_major, driver_minor);
+ result = register_chrdev_region(dev, 1, driver_name);
+ } else {
+ result = alloc_chrdev_region(&dev, driver_minor, 1,
+ driver_name);
+ driver_major = MAJOR(dev);
+ }
+
+ if (result < 0) {
+ GT_1trace(driverTrace, GT_7CLASS, "bridge_init: "
+ "Can't get Major %d \n", driver_major);
+ return result;
+ }
+
+ bridge_device = kmalloc(sizeof(struct bridge_dev), GFP_KERNEL);
+ if (!bridge_device) {
+ result = -ENOMEM;
+ unregister_chrdev_region(dev, 1);
+ return result;
+ }
+ memset(bridge_device, 0, sizeof(struct bridge_dev));
+ cdev_init(&bridge_device->cdev, &bridge_fops);
+ bridge_device->cdev.owner = THIS_MODULE;
+ bridge_device->cdev.ops = &bridge_fops;
+
+ status = cdev_add(&bridge_device->cdev, dev, 1);
+
+ if (status) {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "Failed to add the bridge device \n");
+ return status;
+ }
+
+ /* udev support */
+ bridge_class = class_create(THIS_MODULE, "ti_bridge");
+
+ if (IS_ERR(bridge_class))
+ GT_0trace(driverTrace, GT_7CLASS,
+ "Error creating bridge class \n");
+
+ device_create(bridge_class, NULL, MKDEV(driver_major, driver_minor),
+ NULL, "DspBridge");
+
+ GT_init();
+ GT_create(&driverTrace, "LD");
+
+#ifdef DEBUG
+ if (GT_str)
+ GT_set(GT_str);
+#elif defined(DDSP_DEBUG_PRODUCT) && GT_TRACE
+ GT_set("**=67");
+#endif
+
+ GT_0trace(driverTrace, GT_ENTER, "-> driver_init\n");
+
+#ifdef CONFIG_PM
+ /* Initialize the wait queue */
+ if (!status) {
+ bridge_suspend_data.suspended = 0;
+ init_waitqueue_head(&bridge_suspend_data.suspend_wq);
+ }
+#endif
+
+ SERVICES_Init();
+
+ /* Autostart flag. This should be set to true if the DSP image should
+ * be loaded and run during bridge module initialization */
+
+ if (base_img) {
+ temp = true;
+ REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
+ sizeof(temp));
+ REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *)base_img,
+ strlen(base_img) + 1);
+ } else {
+ temp = false;
+ REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
+ sizeof(temp));
+ REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *) "\0", (u32)2);
+ }
+ REG_SetValue(NULL, NULL, NUMPROCS, REG_SZ, (u8 *) num_procs,
+ strlen(num_procs) + 1);
+
+ if (shm_size >= 0x10000) { /* 64 KB */
+ initStatus = REG_SetValue(NULL, NULL, SHMSIZE, REG_DWORD,
+ (u8 *)&shm_size, sizeof(shm_size));
+ } else {
+ initStatus = DSP_EINVALIDARG;
+ status = -1;
+ GT_0trace(driverTrace, GT_7CLASS,
+ "SHM size must be at least 64 KB\n");
+ }
+ GT_1trace(driverTrace, GT_7CLASS,
+ "requested shm_size = 0x%x\n", shm_size);
+
+ if (pdata->phys_mempool_base && pdata->phys_mempool_size) {
+ phys_mempool_base = pdata->phys_mempool_base;
+ phys_mempool_size = pdata->phys_mempool_size;
+ }
+
+ if (phys_mempool_base > 0x0) {
+ initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLBASE,
+ REG_DWORD, (u8 *)&phys_mempool_base,
+ sizeof(phys_mempool_base));
+ }
+ GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_base = 0x%x \n",
+ phys_mempool_base);
+
+ if (phys_mempool_size > 0x0) {
+ initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLSIZE,
+ REG_DWORD, (u8 *)&phys_mempool_size,
+ sizeof(phys_mempool_size));
+ }
+ GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_size = 0x%x\n",
+ phys_mempool_base);
+ if ((phys_mempool_base > 0x0) && (phys_mempool_size > 0x0))
+ MEM_ExtPhysPoolInit(phys_mempool_base, phys_mempool_size);
+ if (tc_wordswapon) {
+ GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is enabled\n");
+ REG_SetValue(NULL, NULL, TCWORDSWAP, REG_DWORD,
+ (u8 *)&tc_wordswapon, sizeof(tc_wordswapon));
+ } else {
+ GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is disabled\n");
+ REG_SetValue(NULL, NULL, TCWORDSWAP,
+ REG_DWORD, (u8 *)&tc_wordswapon,
+ sizeof(tc_wordswapon));
+ }
+ if (DSP_SUCCEEDED(initStatus)) {
+#ifdef CONFIG_BRIDGE_DVFS
+ for (i = 0; i < 6; i++)
+ pdata->mpu_speed[i] = vdd1_rate_table_bridge[i].rate;
+
+ clk_handle = clk_get(NULL, "iva2_ck");
+ if (!clk_handle) {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_get failed to get iva2_ck \n");
+ } else {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_get PASS to get iva2_ck \n");
+ }
+ if (!clk_notifier_register(clk_handle, &iva_clk_notifier)) {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_notifier_register PASS for iva2_ck \n");
+ } else {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_notifier_register FAIL for iva2_ck \n");
+ }
+#endif
+ driverContext = DSP_Init(&initStatus);
+ if (DSP_FAILED(initStatus)) {
+ status = -1;
+ GT_0trace(driverTrace, GT_7CLASS,
+ "DSP/BIOS Bridge initialization Failed\n");
+ } else {
+ GT_0trace(driverTrace, GT_5CLASS,
+ "DSP/BIOS Bridge driver loaded\n");
+ }
+ }
+
+ DBC_Assert(status == 0);
+ DBC_Assert(DSP_SUCCEEDED(initStatus));
+ GT_0trace(driverTrace, GT_ENTER, " <- driver_init\n");
+ return status;
+}
+
+static int __devexit omap34xx_bridge_remove(struct platform_device *pdev)
+{
+ dev_t devno;
+ bool ret;
+ DSP_STATUS dsp_status = DSP_SOK;
+ HANDLE hDrvObject = NULL;
+ struct PROCESS_CONTEXT *pTmp = NULL;
+ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
+
+ GT_0trace(driverTrace, GT_ENTER, "-> driver_exit\n");
+
+ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_FAILED(dsp_status))
+ goto func_cont;
+ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
+ while (pCtxtclosed != NULL) {
+ GT_1trace(driverTrace, GT_5CLASS, "***Cleanup of "
+ "process***%d\n", pCtxtclosed->pid);
+ DRV_RemoveAllResources(pCtxtclosed);
+ PROC_Detach(pCtxtclosed->hProcessor);
+ pTmp = pCtxtclosed->next;
+ DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
+ pCtxtclosed, (void *)pCtxtclosed->pid);
+ pCtxtclosed = pTmp;
+ }
+func_cont:
+ if (driverContext) {
+ /* Put the DSP in reset state */
+ ret = DSP_Deinit(driverContext);
+ driverContext = 0;
+ DBC_Assert(ret == true);
+ }
+ SERVICES_Exit();
+ GT_exit();
+ /* unregister the clock notifier */
+#ifdef CONFIG_BRIDGE_DVFS
+ if (!clk_notifier_unregister(clk_handle, &iva_clk_notifier)) {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_notifier_unregister PASS for iva2_ck \n");
+ } else {
+ GT_0trace(driverTrace, GT_7CLASS,
+ "clk_notifier_unregister PASS for iva2_ck \n");
+ }
+
+ clk_put(clk_handle);
+ clk_handle = NULL;
+#endif /* #ifdef CONFIG_BRIDGE_DVFS */
+
+ devno = MKDEV(driver_major, driver_minor);
+ if (bridge_device) {
+ cdev_del(&bridge_device->cdev);
+ kfree(bridge_device);
+ }
+ unregister_chrdev_region(devno, 1);
+ if (bridge_class) {
+ /* remove the device from sysfs */
+ device_destroy(bridge_class, MKDEV(driver_major, driver_minor));
+ class_destroy(bridge_class);
+
+ }
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int bridge_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ u32 status;
+ u32 command = PWR_EMERGENCYDEEPSLEEP;
+
+ status = PWR_SleepDSP(command, timeOut);
+ if (DSP_FAILED(status))
+ return -1;
+
+ bridge_suspend_data.suspended = 1;
+ return 0;
+}
+
+static int bridge_resume(struct platform_device *pdev)
+{
+ u32 status;
+
+ status = PWR_WakeDSP(timeOut);
+ if (DSP_FAILED(status))
+ return -1;
+
+ bridge_suspend_data.suspended = 0;
+ wake_up(&bridge_suspend_data.suspend_wq);
+ return 0;
+}
+#else
+#define bridge_suspend NULL
+#define bridge_resume NULL
+#endif
+
+static struct platform_driver bridge_driver = {
+ .driver = {
+ .name = BRIDGE_NAME,
+ },
+ .probe = omap34xx_bridge_probe,
+ .remove = __devexit_p(omap34xx_bridge_remove),
+ .suspend = bridge_suspend,
+ .resume = bridge_resume,
+};
+
+static int __init bridge_init(void)
+{
+ return platform_driver_register(&bridge_driver);
+}
+
+static void __exit bridge_exit(void)
+{
+ platform_driver_unregister(&bridge_driver);
+}
+
+/* This function is called when an application opens handle to the
+ * bridge driver. */
+
+static int bridge_open(struct inode *ip, struct file *filp)
+{
+ int status = 0;
+#ifndef RES_CLEANUP_DISABLE
+ u32 hProcess;
+ DSP_STATUS dsp_status = DSP_SOK;
+ HANDLE hDrvObject = NULL;
+ struct PROCESS_CONTEXT *pPctxt = NULL;
+ struct PROCESS_CONTEXT *next_node = NULL;
+ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
+ struct PROCESS_CONTEXT *pCtxttraverse = NULL;
+ struct task_struct *tsk = NULL;
+ struct pid *pnr = NULL;
+ GT_0trace(driverTrace, GT_ENTER, "-> driver_open\n");
+ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+
+ /* Checking weather task structure for all process existing
+ * in the process context list If not removing those processes*/
+ if (DSP_FAILED(dsp_status))
+ goto func_cont;
+
+ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
+ while (pCtxtclosed != NULL) {
+ pnr = find_get_pid(pCtxtclosed->pid);
+ tsk = pid_task(pnr, PIDTYPE_PID);
+ next_node = pCtxtclosed->next;
+
+ if ((tsk == NULL) || (tsk->exit_state == EXIT_ZOMBIE)) {
+
+ GT_1trace(driverTrace, GT_5CLASS,
+ "***Task structure not existing for "
+ "process***%d\n", pCtxtclosed->pid);
+ DRV_RemoveAllResources(pCtxtclosed);
+ if (pCtxtclosed->hProcessor != NULL) {
+ DRV_GetProcCtxtList(&pCtxttraverse,
+ (struct DRV_OBJECT *)hDrvObject);
+ if (pCtxttraverse->next == NULL) {
+ PROC_Detach(pCtxtclosed->hProcessor);
+ } else {
+ if ((pCtxtclosed->pid ==
+ pCtxttraverse->pid) &&
+ (pCtxttraverse->next != NULL)) {
+ pCtxttraverse =
+ pCtxttraverse->next;
+ }
+ while ((pCtxttraverse != NULL) &&
+ (pCtxtclosed->hProcessor
+ != pCtxttraverse->hProcessor)) {
+ pCtxttraverse =
+ pCtxttraverse->next;
+ if ((pCtxttraverse != NULL) &&
+ (pCtxtclosed->pid ==
+ pCtxttraverse->pid)) {
+ pCtxttraverse =
+ pCtxttraverse->next;
+ }
+ }
+ if (pCtxttraverse == NULL) {
+ PROC_Detach
+ (pCtxtclosed->hProcessor);
+ }
+ }
+ }
+ DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
+ pCtxtclosed,
+ (void *)pCtxtclosed->pid);
+ }
+ pCtxtclosed = next_node;
+ }
+func_cont:
+ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+ if (DSP_SUCCEEDED(dsp_status))
+ dsp_status = DRV_InsertProcContext(
+ (struct DRV_OBJECT *)hDrvObject, &pPctxt);
+
+ if (pPctxt != NULL) {
+ /* Return PID instead of process handle */
+ hProcess = current->pid;
+
+ DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
+ DRV_ProcSetPID(pPctxt, hProcess);
+ }
+#endif
+
+ GT_0trace(driverTrace, GT_ENTER, " <- driver_open\n");
+ return status;
+}
+
+/* This function is called when an application closes handle to the bridge
+ * driver. */
+static int bridge_release(struct inode *ip, struct file *filp)
+{
+ int status;
+ u32 pid;
+
+ GT_0trace(driverTrace, GT_ENTER, "-> driver_release\n");
+
+ /* Return PID instead of process handle */
+ pid = current->pid;
+
+ status = DSP_Close(pid);
+
+
+ (status == true) ? (status = 0) : (status = -1);
+
+ GT_0trace(driverTrace, GT_ENTER, " <- driver_release\n");
+
+ return status;
+}
+
+/* This function provides IO interface to the bridge driver. */
+static int bridge_ioctl(struct inode *ip, struct file *filp, unsigned int code,
+ unsigned long args)
+{
+ int status;
+ u32 retval = DSP_SOK;
+ union Trapped_Args pBufIn;
+
+ DBC_Require(filp != NULL);
+#ifdef CONFIG_PM
+ status = omap34xxbridge_suspend_lockout(&bridge_suspend_data, filp);
+ if (status != 0)
+ return status;
+#endif
+
+ GT_0trace(driverTrace, GT_ENTER, " -> driver_ioctl\n");
+
+ status = copy_from_user(&pBufIn, (union Trapped_Args *)args,
+ sizeof(union Trapped_Args));
+
+ if (status >= 0) {
+ status = WCD_CallDevIOCtl(code, &pBufIn, &retval);
+
+ if (DSP_SUCCEEDED(status)) {
+ status = retval;
+ } else {
+ GT_1trace(driverTrace, GT_7CLASS,
+ "IOCTL Failed, code : 0x%x\n", code);
+ status = -1;
+ }
+
+ }
+
+ GT_0trace(driverTrace, GT_ENTER, " <- driver_ioctl\n");
+
+ return status;
+}
+
+/* This function maps kernel space memory to user space memory. */
+static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+#if GT_TRACE
+ u32 offset = vma->vm_pgoff << PAGE_SHIFT;
+#endif
+ u32 status;
+
+ DBC_Assert(vma->vm_start < vma->vm_end);
+
+ vma->vm_flags |= VM_RESERVED | VM_IO;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ GT_6trace(driverTrace, GT_3CLASS,
+ "vm filp %p offset %lx start %lx end %lx"
+ " page_prot %lx flags %lx\n", filp, offset, vma->vm_start,
+ vma->vm_end, vma->vm_page_prot, vma->vm_flags);
+
+ status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+ if (status != 0)
+ status = -EAGAIN;
+
+ return status;
+}
+
+#ifndef RES_CLEANUP_DISABLE
+/* To remove all process resources before removing the process from the
+ * process context list*/
+DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt)
+{
+ DSP_STATUS status = DSP_SOK;
+ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+ if (pCtxt != NULL) {
+ DRV_RemoveAllSTRMResElements(pCtxt);
+ DRV_RemoveAllNodeResElements(pCtxt);
+ DRV_RemoveAllDMMResElements(pCtxt);
+ DRV_ProcUpdatestate(pCtxt, PROC_RES_FREED);
+ }
+ return status;
+}
+#endif
+
+/* Bridge driver initialization and de-initialization functions */
+module_init(bridge_init);
+module_exit(bridge_exit);
+