]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
ARM: OMAP: DSPGW: DSP Gateway driver 3.3.1
authorToshihiro Kobayashi <Toshihiro.Kobayashi@nokia.com>
Thu, 21 Sep 2006 14:41:36 +0000 (17:41 +0300)
committerJuha Yrjola <juha.yrjola@solidboot.com>
Thu, 21 Sep 2006 15:45:32 +0000 (18:45 +0300)
Here's the patch that updates DSP Gateway driver to 3.3.1, that
supports omap2 DSP. It also contains generic mailbox interface
considering IVA use on 2420, but this patch itself doesn't contain any
IVA driver.

Regarding omap2, this code is tested only on our 2420 custom board, so
feedbacks from testing on other chips / boards will be greatly
appreciated.

Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
35 files changed:
arch/arm/mach-omap1/Kconfig
arch/arm/mach-omap2/io.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/dsp/Kconfig
arch/arm/plat-omap/dsp/dsp.h
arch/arm/plat-omap/dsp/dsp_common.c
arch/arm/plat-omap/dsp/dsp_common.h
arch/arm/plat-omap/dsp/dsp_core.c
arch/arm/plat-omap/dsp/dsp_ctl.c
arch/arm/plat-omap/dsp/dsp_ctl_core.c
arch/arm/plat-omap/dsp/dsp_mbcmd.h [new file with mode: 0644]
arch/arm/plat-omap/dsp/dsp_mem.c
arch/arm/plat-omap/dsp/error.c
arch/arm/plat-omap/dsp/fifo.h
arch/arm/plat-omap/dsp/hardware_dsp.h
arch/arm/plat-omap/dsp/ioctl.h [new file with mode: 0644]
arch/arm/plat-omap/dsp/ipbuf.c
arch/arm/plat-omap/dsp/ipbuf.h
arch/arm/plat-omap/dsp/mblog.c
arch/arm/plat-omap/dsp/omap1_dsp.h [new file with mode: 0644]
arch/arm/plat-omap/dsp/omap2_dsp.h [new file with mode: 0644]
arch/arm/plat-omap/dsp/proclist.h
arch/arm/plat-omap/dsp/task.c
arch/arm/plat-omap/dsp/taskwatch.c
arch/arm/plat-omap/dsp/uaccess_dsp.S
arch/arm/plat-omap/dsp/uaccess_dsp.h
arch/arm/plat-omap/mailbox.c [new file with mode: 0644]
arch/arm/plat-omap/mailbox_hw.h [new file with mode: 0644]
include/asm-arm/arch-omap/dsp.h [deleted file]
include/asm-arm/arch-omap/dsp_common.h
include/asm-arm/arch-omap/io.h
include/asm-arm/arch-omap/irqs.h
include/asm-arm/arch-omap/mailbox.h [new file with mode: 0644]
include/asm-arm/arch-omap/omap24xx.h

index 781f0d4ea3efed90ab0f85c0e5d1d7853edb3ab3..ab1b17d35bd32322a416937bd10caff4f9114fa1 100644 (file)
@@ -179,5 +179,3 @@ config OMAP_ARM_30MHZ
        help
           Enable 30MHz clock for OMAP CPU. If unsure, say N.
 
-source "arch/arm/plat-omap/dsp/Kconfig"
-
index a0728c33e5d9e60de43b6f867b1efcfd61c1561f..df251fefc48fba96eae2845e99bbec724dd5de54 100644 (file)
@@ -44,6 +44,24 @@ static struct map_desc omap2_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(L4_24XX_PHYS),
                .length         = L4_24XX_SIZE,
                .type           = MT_DEVICE
+       },
+       {
+               .virtual        = DSP_MEM_24XX_VIRT,
+               .pfn            = __phys_to_pfn(DSP_MEM_24XX_PHYS),
+               .length         = DSP_MEM_24XX_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = DSP_IPI_24XX_VIRT,
+               .pfn            = __phys_to_pfn(DSP_IPI_24XX_PHYS),
+               .length         = DSP_IPI_24XX_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = DSP_MMU_24XX_VIRT,
+               .pfn            = __phys_to_pfn(DSP_MMU_24XX_PHYS),
+               .length         = DSP_MMU_24XX_SIZE,
+               .type           = MT_DEVICE
        }
 };
 
index 75f14947149faf45f938bb570c711549676c546d..2b56996154ae4345c2727a70bbcb982a84f49b29 100644 (file)
@@ -172,6 +172,8 @@ config OMAP_SERIAL_WAKE
          to data on the serial RX line. This allows you to wake the
          system from serial console.
 
+source "arch/arm/plat-omap/dsp/Kconfig"
+
 endmenu
 
 endif
index 6a3a3e81484020df6cb35a968f6f60c252bc97b6..e49bef89bf39b246e3bc5ca5b4e1369093e0c59a 100644 (file)
@@ -26,4 +26,4 @@ obj-$(CONFIG_OMAP_COMPONENT_VERSION) += component-version.o
 obj-$(CONFIG_OMAP_GPIO_SWITCH) += gpio-switch.o
 
 # DSP subsystem
-obj-y += dsp/
+obj-$(CONFIG_OMAP_DSP) += dsp/ mailbox.o
index 47f06b21e2e6c4147f2b9e74debafc59b492d50b..71da40bc538ef968894ffe816c033da3a1754a1c 100644 (file)
@@ -1,7 +1,7 @@
 
 config OMAP_DSP
        tristate "OMAP DSP driver (DSP Gateway)"
-       depends on ARCH_OMAP15XX || ARCH_OMAP16XX
+       depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP24XX
        help
          This enables OMAP DSP driver, DSP Gateway.
 
index 48974ad271a0cf502c141b356bba625f2137d740..8ec81a99339bc7e72a4f6c067ffaf43c4f3e3ae3 100644 (file)
@@ -1,32 +1,36 @@
 /*
- * linux/arch/arm/mach-omap/dsp/dsp.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * Header for OMAP DSP driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/06/09:  DSP Gateway version 3.3
  */
 
+#include <linux/platform_device.h>
 #include "hardware_dsp.h"
 #include "dsp_common.h"
 
+/*
+ * MAJOR device number: !! allocated arbitrary !!
+ */
+#define OMAP_DSP_CTL_MAJOR             96
+#define OMAP_DSP_TASK_MAJOR            97
+
 #define OLD_BINARY_SUPPORT     y
 
 #ifdef OLD_BINARY_SUPPORT
 #endif
 
 #define DSP_INIT_PAGE  0xfff000
+
+#ifdef CONFIG_ARCH_OMAP1
 /* idle program will be placed at IDLEPG_BASE. */
 #define IDLEPG_BASE    0xfffe00
 #define IDLEPG_SIZE    0x100
+#endif /* CONFIG_ARCH_OMAP1 */
 
 /* timeout value for DSP response */
 #define DSP_TIMEOUT    (10 * HZ)
@@ -50,30 +57,37 @@ enum dsp_mem_type_e {
        MEM_TYPE_EXTERN,
 };
 
-enum arm_dsp_dir {
+enum arm_dsp_dir_e {
        DIR_A2D,
        DIR_D2A,
 };
 
-/*
- * INT_D2A_MB value definition
- *   INT_DSP_MAILBOX1: use Mailbox 1 (INT 10) for DSP->ARM mailbox
- *   INT_DSP_MAILBOX2: use Mailbox 2 (INT 11) for DSP->ARM mailbox
- */
-#define INT_D2A_MB1    INT_DSP_MAILBOX1
+enum cfgstat_e {
+       CFGSTAT_CLEAN = 0,
+       CFGSTAT_READY,
+       CFGSTAT_SUSPEND,
+       CFGSTAT_RESUME, /* request only */
+       CFGSTAT_MAX
+};
 
-/* keep 2 entries for OMAP_DSP_TID_FREE and OMAP_DSP_TID_ANON */
+enum errcode_e {
+       ERRCODE_WDT = 0,
+       ERRCODE_MMU,
+       ERRCODE_MAX
+};
+
+/* keep 2 entries for TID_FREE and TID_ANON */
 #define TASKDEV_MAX    254
 
+#define MK32(uw,lw)    (((u32)(uw)) << 16 | (lw))
 #define MKLONG(uw,lw)  (((unsigned long)(uw)) << 16 | (lw))
 #define MKVIRT(uw,lw)  dspword_to_virt(MKLONG((uw), (lw)));
-#define MBCMD(nm)      OMAP_DSP_MBCMD_##nm
 
 struct sync_seq {
-       unsigned short da_dsp;
-       unsigned short da_arm;
-       unsigned short ad_dsp;
-       unsigned short ad_arm;
+       u16 da_dsp;
+       u16 da_arm;
+       u16 ad_dsp;
+       u16 ad_arm;
 };
 
 struct mem_sync_struct {
@@ -82,93 +96,106 @@ struct mem_sync_struct {
        struct sync_seq *SDRAM;
 };
 
-/* struct mbcmd and struct mbcmd_hw must be compatible */
+/* struct mbcmd and union mbcmd_hw must be compatible */
 struct mbcmd {
-       unsigned short cmd_l:8;
-       unsigned short cmd_h:7;
-       unsigned short seq:1;
-       unsigned short data;
-};
-
-struct mbcmd_hw {
-       unsigned short cmd;
-       unsigned short data;
+       u32 data:16;
+       u32 cmd_l:8;
+       u32 cmd_h:7;
+       u32 seq:1;
 };
 
-#define mbcmd_set(mb, h, l, d) \
-       do { \
-               (mb).cmd_h = (h); \
-               (mb).cmd_l = (l); \
-               (mb).data  = (d); \
-       } while(0)
+#define MBCMD_INIT(h, l, d) { \
+               .cmd_h = (h), \
+               .cmd_l = (l), \
+               .data  = (d), \
+       }
 
 struct mb_exarg {
-       unsigned char tid;
+       u8 tid;
        int argc;
-       unsigned short *argv;
+       u16 *argv;
 };
 
-extern void dsp_mb_start(void);
-extern void dsp_mb_stop(void);
-extern int dsp_mb_config(void *p);
-extern int sync_with_dsp(unsigned short *syncwd, unsigned short tid,
-                        int try_cnt);
-extern int __mbcmd_send(struct mbcmd *mb);
-extern int __dsp_mbcmd_send(struct mbcmd *mb, struct mb_exarg *arg,
-                           int recovery_flag);
-#define dsp_mbcmd_send(mb)             __dsp_mbcmd_send(mb, NULL, 0)
-#define dsp_mbcmd_send_exarg(mb, arg)  __dsp_mbcmd_send(mb, arg, 0)
-extern int __dsp_mbcmd_send_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
-                                    wait_queue_head_t *q);
+extern struct mbx *mbx_dsp;
+extern void dsp_mbx_start(void);
+extern void dsp_mbx_stop(void);
+extern int dsp_mbx_config(void *p);
+extern int sync_with_dsp(u16 *syncwd, u16 tid, int try_cnt);
+extern int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+                                 int recovery_flag);
+#define dsp_mbcmd_send(mb)             __dsp_mbcmd_send_exarg((mb), NULL, 0)
+#define dsp_mbcmd_send_exarg(mb, arg)  __dsp_mbcmd_send_exarg((mb), (arg), 0)
+extern int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+                                        wait_queue_head_t *q);
 #define dsp_mbcmd_send_and_wait(mb, q) \
-       __dsp_mbcmd_send_and_wait(mb, NULL, q)
-#define dsp_mbcmd_send_and_wait_exarg(mb, arg, q) \
-       __dsp_mbcmd_send_and_wait(mb, arg, q)
-int __dsp_mbsend(unsigned char cmdh, unsigned char cmdl, unsigned short data,
-                int recovery_flag);
-#define dsp_mbsend(cmdh, cmdl, data) \
-       __dsp_mbsend(cmdh, cmdl, data, 0)
-#define dsp_mbsend_recovery(cmdh, cmdl, data) \
-       __dsp_mbsend(cmdh, cmdl, data, 1)
-
+       dsp_mbcmd_send_and_wait_exarg((mb), NULL, (q))
+
+static __inline__ int __mbcompose_send_exarg(u8 cmd_h, u8 cmd_l, u16 data,
+                                            struct mb_exarg *arg,
+                                            int recovery_flag)
+{
+       struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
+       return __dsp_mbcmd_send_exarg(&mb, arg, recovery_flag);
+}
+#define mbcompose_send(cmd_h, cmd_l, data) \
+       __mbcompose_send_exarg(MBX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 0)
+#define mbcompose_send_exarg(cmd_h, cmd_l, data, arg) \
+       __mbcompose_send_exarg(MBX_CMD_DSP_##cmd_h, (cmd_l), (data), arg, 0)
+#define mbcompose_send_recovery(cmd_h, cmd_l, data) \
+       __mbcompose_send_exarg(MBX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 1)
+
+static __inline__ int __mbcompose_send_and_wait_exarg(u8 cmd_h, u8 cmd_l,
+                                                     u16 data,
+                                                     struct mb_exarg *arg,
+                                                     wait_queue_head_t *q)
+{
+       struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
+       return dsp_mbcmd_send_and_wait_exarg(&mb, arg, q);
+}
+#define mbcompose_send_and_wait(cmd_h, cmd_l, data, q) \
+       __mbcompose_send_and_wait_exarg(MBX_CMD_DSP_##cmd_h, (cmd_l), (data), \
+                                       NULL, (q))
+#define mbcompose_send_and_wait_exarg(cmd_h, cmd_l, data, arg, q) \
+       __mbcompose_send_and_wait_exarg(MBX_CMD_DSP_##cmd_h, (cmd_l), (data), \
+                                       (arg), (q))
+
+extern struct ipbuf_head *bid_to_ipbuf(u16 bid);
 extern void ipbuf_start(void);
 extern void ipbuf_stop(void);
-extern int ipbuf_config(unsigned short ln, unsigned short lsz, void *base);
-extern int ipbuf_sys_config(void *p, enum arm_dsp_dir dir);
-extern int ipbuf_p_validate(void *p, enum arm_dsp_dir dir);
-extern unsigned short get_free_ipbuf(unsigned char tid);
-extern void unuse_ipbuf_nowait(unsigned short bid);
-extern void unuse_ipbuf(unsigned short bid);
-extern void release_ipbuf(unsigned short bid);
+extern int ipbuf_config(u16 ln, u16 lsz, void *base);
+extern int ipbuf_sys_config(void *p, enum arm_dsp_dir_e dir);
+extern int ipbuf_p_validate(void *p, enum arm_dsp_dir_e dir);
+extern struct ipbuf_head *get_free_ipbuf(u8 tid);
+extern void release_ipbuf(struct ipbuf_head *ipb_h);
 extern void balance_ipbuf(void);
+extern void unuse_ipbuf(struct ipbuf_head *ipb_h);
+extern void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h);
 
 #define release_ipbuf_pvt(ipbuf_pvt) \
        do { \
-               (ipbuf_pvt)->s = OMAP_DSP_TID_FREE; \
+               (ipbuf_pvt)->s = TID_FREE; \
        } while(0)
 
 extern int mbx_revision;
 
-extern int dsp_is_ready(void);
-extern int dspuncfg(void);
-extern void dsp_runlevel(unsigned char level);
-extern int dsp_suspend(void);
-extern int dsp_resume(void);
+extern int dsp_cfgstat_request(enum cfgstat_e st);
+extern enum cfgstat_e dsp_cfgstat_get_stat(void);
+extern int dsp_set_runlevel(u8 level);
 
-extern int dsp_task_config_all(unsigned char n);
+extern int dsp_task_config_all(u8 n);
 extern void dsp_task_unconfig_all(void);
-extern unsigned char dsp_task_count(void);
+extern u8 dsp_task_count(void);
 extern int dsp_taskmod_busy(void);
 extern int dsp_mkdev(char *name);
 extern int dsp_rmdev(char *name);
-extern int dsp_tadd(unsigned char minor, unsigned long adr);
-extern int dsp_tdel(unsigned char minor);
-extern int dsp_tkill(unsigned char minor);
+extern int dsp_tadd_minor(unsigned char minor, dsp_long_t adr);
+extern int dsp_tdel_minor(unsigned char minor);
+extern int dsp_tkill_minor(unsigned char minor);
 extern long taskdev_state_stale(unsigned char minor);
-extern int dsp_dbg_config(short *buf, unsigned short sz, unsigned short lsz);
+extern int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz);
 extern void dsp_dbg_stop(void);
 
-extern int ipbuf_is_held(unsigned char tid, unsigned short bid);
+extern int ipbuf_is_held(u8 tid, u16 bid);
 
 extern int dsp_mem_sync_inc(void);
 extern int dsp_mem_sync_config(struct mem_sync_struct *sync);
@@ -176,7 +203,9 @@ extern enum dsp_mem_type_e dsp_mem_type(void *vadr, size_t len);
 extern int dsp_address_validate(void *p, size_t len, char *fmt, ...);
 extern int dsp_mem_enable(void *adr);
 extern void dsp_mem_disable(void *adr);
+#ifdef CONFIG_ARCH_OMAP1
 extern void dsp_mem_usecount_clear(void);
+#endif
 extern void exmap_use(void *vadr, size_t len);
 extern void exmap_unuse(void *vadr, size_t len);
 extern unsigned long dsp_virt_to_phys(void *vadr, size_t *len);
@@ -189,13 +218,11 @@ extern void dsp_twch_touch(void);
 
 extern void dsp_err_start(void);
 extern void dsp_err_stop(void);
-extern void dsp_err_mmu_set(unsigned long adr);
-extern void dsp_err_mmu_clear(void);
-extern int dsp_err_mmu_isset(void);
-extern void dsp_err_wdt_clear(void);
-extern int dsp_err_wdt_isset(void);
+extern void dsp_err_set(enum errcode_e code, unsigned long arg);
+extern void dsp_err_clear(enum errcode_e code);
+extern int dsp_err_isset(enum errcode_e code);
 
-enum cmd_l_type {
+enum cmd_l_type_e {
        CMD_L_TYPE_NULL,
        CMD_L_TYPE_TID,
        CMD_L_TYPE_SUBCMD,
@@ -203,7 +230,7 @@ enum cmd_l_type {
 
 struct cmdinfo {
        char *name;
-       enum cmd_l_type cmd_l_type;
+       enum cmd_l_type_e cmd_l_type;
        void (*handler)(struct mbcmd *mb);
 };
 
@@ -212,15 +239,11 @@ extern const struct cmdinfo *cmdinfo[];
 #define cmd_name(mb)   (cmdinfo[(mb).cmd_h]->name)
 extern char *subcmd_name(struct mbcmd *mb);
 
-extern void mblog_add(struct mbcmd *mb, enum arm_dsp_dir dir);
+extern void mblog_add(struct mbcmd *mb, enum arm_dsp_dir_e dir);
 #ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
-extern void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir dir);
+extern void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir_e dir);
 #else /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
 #define mblog_printcmd(mb, dir)        do {} while(0)
 #endif /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
 
-#ifdef CONFIG_PROC_FS
-extern struct proc_dir_entry *procdir_dsp;
-#endif /* CONFIG_PROC_FS */
-
 extern struct platform_device dsp_device;
index 378d564fbaa5ecedeb5212d9662551be2e1b35d2..4c35df808855ea5d346ae3a939b15153d60a13a2 100644 (file)
@@ -1,31 +1,27 @@
 /*
- * linux/arch/arm/mach-omap/dsp/dsp_common.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * OMAP DSP driver static part
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/06/13:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
-#include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 #include <asm/irq.h>
-#include <asm/arch/dsp.h>
+#ifdef CONFIG_ARCH_OMAP1
 #include <asm/arch/tc.h>
+#endif
 #include "dsp_common.h"
 
+#if defined(CONFIG_ARCH_OMAP1)
+#define dsp_boot_config(mode)  omap_writew((mode), MPUI_DSP_BOOT_CONFIG)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define dsp_boot_config(mode)  writel((mode), DSP_IPI_DSPBOOTCONFIG)
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1)
 struct clk *dsp_ck_handle;
 struct clk *api_ck_handle;
-unsigned long dspmem_base, dspmem_size,
-             daram_base, daram_size,
-             saram_base, saram_size;
+#elif defined(CONFIG_ARCH_OMAP2)
+struct clk *dsp_fck_handle;
+struct clk *dsp_ick_handle;
+#endif
+dsp_long_t dspmem_base, dspmem_size,
+          daram_base, daram_size,
+          saram_base, saram_size;
 
 struct cpustat {
        struct mutex lock;
-       enum e_cpustat stat;
-       enum e_cpustat req;
-       unsigned short icrmask;
+       enum cpustat_e stat;
+       enum cpustat_e req;
+       u16 icrmask;
+#ifdef CONFIG_ARCH_OMAP1
        struct {
                int mpui;
                int mem;
@@ -58,13 +67,13 @@ struct cpustat {
        } usecount;
        int (*mem_req_cb)(void);
        void (*mem_rel_cb)(void);
-};
-struct cpustat cpustat = {
+#endif
+} cpustat = {
        .stat = CPUSTAT_RESET,
        .icrmask = 0xffff,
 };
 
-int dsp_set_rstvect(unsigned long adr)
+int dsp_set_rstvect(dsp_long_t adr)
 {
        unsigned long *dst_adr;
 
@@ -75,17 +84,26 @@ int dsp_set_rstvect(unsigned long adr)
        /* word swap */
        *dst_adr = ((adr & 0xffff) << 16) | (adr >> 16);
        /* fill 8 bytes! */
-       *(dst_adr+1) = 0;
+       *(dst_adr + 1) = 0;
        /* direct boot */
-       omap_writew(MPUI_DSP_BOOT_CONFIG_DIRECT, MPUI_DSP_BOOT_CONFIG);
+       dsp_boot_config(DSP_BOOT_CONFIG_DIRECT);
 
        return 0;
 }
 
-static void simple_load_code(unsigned char *src_c, unsigned short *dst, int len)
+dsp_long_t dsp_get_rstvect(void)
+{
+       unsigned long *dst_adr;
+
+       dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT);
+       return ((*dst_adr & 0xffff) << 16) | (*dst_adr >> 16);
+}
+
+#ifdef CONFIG_ARCH_OMAP1
+static void simple_load_code(unsigned char *src_c, u16 *dst, int len)
 {
        int i;
-       unsigned short *src = (unsigned short *)src_c;
+       u16 *src = (u16 *)src_c;
        int len_w;
 
        /* len must be multiple of 2. */
@@ -165,7 +183,7 @@ static void simple_load_code(unsigned char *src_c, unsigned short *dst, int len)
  * DSP Gateway driver will overwrite this value with other value,
  * to avoid confliction with the user program.
  */
-static unsigned long idle_boot_base = DSP_BOOT_ADR_MPUI;
+static dsp_long_t idle_boot_base = DSP_BOOT_ADR_MPUI;
 
 static void dsp_gbl_idle(void)
 {
@@ -175,12 +193,12 @@ static void dsp_gbl_idle(void)
        clk_enable(api_ck_handle);
 
 #if 0
-       omap_writew(MPUI_DSP_BOOT_CONFIG_IDLE, MPUI_DSP_BOOT_CONFIG);
+       dsp_boot_config(DSP_BOOT_CONFIG_IDLE);
 #endif
        simple_load_code(idle_text, dspbyte_to_virt(idle_boot_base),
                         GBL_IDLE_TEXT_SIZE);
        if (idle_boot_base == DSP_BOOT_ADR_MPUI)
-               omap_writew(MPUI_DSP_BOOT_CONFIG_MPUI, MPUI_DSP_BOOT_CONFIG);
+               dsp_boot_config(DSP_BOOT_CONFIG_MPUI);
        else
                dsp_set_rstvect(idle_boot_base);
 
@@ -191,7 +209,7 @@ static void dsp_gbl_idle(void)
 
 static void dsp_cpu_idle(void)
 {
-       unsigned short icr_tmp;
+       u16 icr_tmp;
        unsigned char icrh, icrl;
 
        __dsp_reset();
@@ -202,8 +220,7 @@ static void dsp_cpu_idle(void)
         * DMA should not sleep for DARAM/SARAM access
         * DPLL should not sleep while any other domain is active
         */
-       icr_tmp = cpustat.icrmask & ~(DSPREG_ICR_DMA_IDLE_DOMAIN |
-                                     DSPREG_ICR_DPLL_IDLE_DOMAIN);
+       icr_tmp = cpustat.icrmask & ~(DSPREG_ICR_DMA | DSPREG_ICR_DPLL);
        icrh = icr_tmp >> 8;
        icrl = icr_tmp & 0xff;
        {
@@ -212,7 +229,7 @@ static void dsp_cpu_idle(void)
                                 CPU_IDLE_TEXT_SIZE);
        }
        if (idle_boot_base == DSP_BOOT_ADR_MPUI)
-               omap_writew(MPUI_DSP_BOOT_CONFIG_MPUI, MPUI_DSP_BOOT_CONFIG);
+               dsp_boot_config(DSP_BOOT_CONFIG_MPUI);
        else
                dsp_set_rstvect(idle_boot_base);
        __dsp_run();
@@ -220,7 +237,7 @@ static void dsp_cpu_idle(void)
        clk_disable(api_ck_handle);
 }
 
-void dsp_set_idle_boot_base(unsigned long adr, size_t size)
+void dsp_set_idle_boot_base(dsp_long_t adr, size_t size)
 {
        if (adr == idle_boot_base)
                return;
@@ -239,6 +256,13 @@ void dsp_set_idle_boot_base(unsigned long adr, size_t size)
                dsp_cpu_idle();
 }
 
+void dsp_reset_idle_boot_base(void)
+{
+       idle_boot_base = DSP_BOOT_ADR_MPUI;
+}
+
+#endif /* CONFIG_ARCH_OMAP1 */
+
 static int init_done;
 
 static int __init omap_dsp_init(void)
@@ -265,19 +289,30 @@ static int __init omap_dsp_init(void)
                saram_base = OMAP16XX_SARAM_BASE;
                saram_size = OMAP16XX_SARAM_SIZE;
        }
+#endif
+#ifdef CONFIG_ARCH_OMAP24XX
+       if (cpu_is_omap24xx()) {
+               dspmem_base = DSP_MEM_24XX_VIRT;
+               dspmem_size = DSP_MEM_24XX_SIZE;
+               daram_base = OMAP24XX_DARAM_BASE;
+               daram_size = OMAP24XX_DARAM_SIZE;
+               saram_base = OMAP24XX_SARAM_BASE;
+               saram_size = OMAP24XX_SARAM_SIZE;
+       }
 #endif
        if (dspmem_size == 0) {
                printk(KERN_ERR "omapdsp: unsupported omap architecture.\n");
                return -ENODEV;
        }
 
-       dsp_ck_handle = clk_get(0, "dsp_ck");
+#if defined(CONFIG_ARCH_OMAP1)
+       dsp_ck_handle = clk_get(NULL, "dsp_ck");
        if (IS_ERR(dsp_ck_handle)) {
                printk(KERN_ERR "omapdsp: could not acquire dsp_ck handle.\n");
                return PTR_ERR(dsp_ck_handle);
        }
 
-       api_ck_handle = clk_get(0, "api_ck");
+       api_ck_handle = clk_get(NULL, "api_ck");
        if (IS_ERR(api_ck_handle)) {
                printk(KERN_ERR "omapdsp: could not acquire api_ck handle.\n");
                return PTR_ERR(api_ck_handle);
@@ -290,18 +325,33 @@ static int __init omap_dsp_init(void)
        mpui_byteswap_off();
        mpui_wordswap_on();
        tc_wordswap();
+#elif defined(CONFIG_ARCH_OMAP2)
+       dsp_fck_handle = clk_get(NULL, "dsp_fck");
+       if (IS_ERR(dsp_fck_handle)) {
+               printk(KERN_ERR "omapdsp: could not acquire dsp_fck handle.\n");
+               return PTR_ERR(dsp_fck_handle);
+       }
+
+       dsp_ick_handle = clk_get(NULL, "dsp_ick");
+       if (IS_ERR(dsp_ick_handle)) {
+               printk(KERN_ERR "omapdsp: could not acquire dsp_ick handle.\n");
+               return PTR_ERR(dsp_ick_handle);
+       }
+#endif
 
        init_done = 1;
        printk(KERN_INFO "omap_dsp_init() done\n");
        return 0;
 }
 
+#if defined(CONFIG_ARCH_OMAP1)
 static int dsp_late_init(void)
 {
        clk_disable(api_ck_handle);
        return 0;
 }
 late_initcall(dsp_late_init);
+#endif
 
 static void dsp_cpustat_update(void)
 {
@@ -310,23 +360,32 @@ static void dsp_cpustat_update(void)
 
        if (cpustat.req == CPUSTAT_RUN) {
                if (cpustat.stat < CPUSTAT_RUN) {
+#if defined(CONFIG_ARCH_OMAP1)
                        __dsp_reset();
                        clk_enable(api_ck_handle);
                        udelay(10);
                        __dsp_run();
+#elif defined(CONFIG_ARCH_OMAP2)
+                       __dsp_core_disable();
+                       udelay(10);
+                       __dsp_core_enable();
+#endif
                        cpustat.stat = CPUSTAT_RUN;
                        enable_irq(INT_DSP_MMU);
                }
                return;
        }
 
-       /* cpustat.stat < CPUSTAT_RUN */
+       /* cpustat.req < CPUSTAT_RUN */
 
        if (cpustat.stat == CPUSTAT_RUN) {
                disable_irq(INT_DSP_MMU);
+#ifdef CONFIG_ARCH_OMAP1
                clk_disable(api_ck_handle);
+#endif
        }
 
+#ifdef CONFIG_ARCH_OMAP1
        /*
         * (1) when ARM wants DARAM access, MPUI should be SAM and
         *     DSP needs to be on.
@@ -355,17 +414,22 @@ static void dsp_cpustat_update(void)
                }
                return;
        }
+#endif /* CONFIG_ARCH_OMAP1 */
 
        /*
         * no user, no request
         */
        if (cpustat.stat != CPUSTAT_RESET) {
+#if defined(CONFIG_ARCH_OMAP1)
                __dsp_reset();
+#elif defined(CONFIG_ARCH_OMAP2)
+               __dsp_core_disable();
+#endif
                cpustat.stat = CPUSTAT_RESET;
        }
 }
 
-void dsp_cpustat_request(enum e_cpustat req)
+void dsp_cpustat_request(enum cpustat_e req)
 {
        mutex_lock(&cpustat.lock);
        cpustat.req = req;
@@ -373,17 +437,17 @@ void dsp_cpustat_request(enum e_cpustat req)
        mutex_unlock(&cpustat.lock);
 }
 
-enum e_cpustat dsp_cpustat_get_stat(void)
+enum cpustat_e dsp_cpustat_get_stat(void)
 {
        return cpustat.stat;
 }
 
-unsigned short dsp_cpustat_get_icrmask(void)
+u16 dsp_cpustat_get_icrmask(void)
 {
        return cpustat.icrmask;
 }
 
-void dsp_cpustat_set_icrmask(unsigned short mask)
+void dsp_cpustat_set_icrmask(u16 mask)
 {
        mutex_lock(&cpustat.lock);
        cpustat.icrmask = mask;
@@ -391,6 +455,7 @@ void dsp_cpustat_set_icrmask(unsigned short mask)
        mutex_unlock(&cpustat.lock);
 }
 
+#ifdef CONFIG_ARCH_OMAP1
 void omap_dsp_request_mpui(void)
 {
        mutex_lock(&cpustat.lock);
@@ -499,6 +564,7 @@ void dsp_unregister_mem_cb(void)
        cpustat.mem_rel_cb = NULL;
        mutex_unlock(&cpustat.lock);
 }
+#endif /* CONFIG_ARCH_OMAP1 */
 
 /*
  * Audio power control function prototypes and defaults
@@ -522,14 +588,21 @@ EXPORT_SYMBOL(omap_dsp_audio_pwr_down_request);
 
 arch_initcall(omap_dsp_init);
 
+#ifdef CONFIG_ARCH_OMAP1
 EXPORT_SYMBOL(omap_dsp_request_mpui);
 EXPORT_SYMBOL(omap_dsp_release_mpui);
 EXPORT_SYMBOL(omap_dsp_request_mem);
 EXPORT_SYMBOL(omap_dsp_release_mem);
+#endif /* CONFIG_ARCH_OMAP1 */
 
 #ifdef CONFIG_OMAP_DSP_MODULE
+#if defined(CONFIG_ARCH_OMAP1)
 EXPORT_SYMBOL(dsp_ck_handle);
 EXPORT_SYMBOL(api_ck_handle);
+#elif defined(CONFIG_ARCH_OMAP2)
+EXPORT_SYMBOL(dsp_fck_handle);
+EXPORT_SYMBOL(dsp_ick_handle);
+#endif
 EXPORT_SYMBOL(dspmem_base);
 EXPORT_SYMBOL(dspmem_size);
 EXPORT_SYMBOL(daram_base);
@@ -537,13 +610,19 @@ EXPORT_SYMBOL(daram_size);
 EXPORT_SYMBOL(saram_base);
 EXPORT_SYMBOL(saram_size);
 EXPORT_SYMBOL(dsp_set_rstvect);
+EXPORT_SYMBOL(dsp_get_rstvect);
+#ifdef CONFIG_ARCH_OMAP1
 EXPORT_SYMBOL(dsp_set_idle_boot_base);
+EXPORT_SYMBOL(dsp_reset_idle_boot_base);
+#endif /* CONFIG_ARCH_OMAP1 */
 EXPORT_SYMBOL(dsp_cpustat_request);
 EXPORT_SYMBOL(dsp_cpustat_get_stat);
 EXPORT_SYMBOL(dsp_cpustat_get_icrmask);
 EXPORT_SYMBOL(dsp_cpustat_set_icrmask);
+#ifdef CONFIG_ARCH_OMAP1
 EXPORT_SYMBOL(dsp_register_mem_cb);
 EXPORT_SYMBOL(dsp_unregister_mem_cb);
+#endif /* CONFIG_ARCH_OMAP1 */
 
 EXPORT_SYMBOL(__cpu_flush_kern_tlb_range);
 EXPORT_SYMBOL(cpu_architecture);
index 36034bd8ae42beaccca54bc89c11437646fe8ed7..54fd2283b43bd6e1cb8faacb5a464534eedb5d6d 100644 (file)
@@ -1,29 +1,29 @@
 /*
- * linux/arch/arm/mach-omap/dsp/dsp_common.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * Header for OMAP DSP driver static part
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/06/13:  DSP Gateway version 3.3
  */
 
+#ifndef DRIVER_DSP_COMMON_H
+#define DRIVER_DSP_COMMON_H
+
 #include "hardware_dsp.h"
 
 #define DSPSPACE_SIZE  0x1000000
        do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
 #define omap_clr_bit_regl(b,r) \
        do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
+#define omap_set_bits_regl(val,mask,r) \
+       do { omap_writel((omap_readl(r) & ~(mask)) | (val), (r)); } while(0)
+
+#if defined(CONFIG_ARCH_OMAP15XX)
+#define INT_DSP_MMU    INT_1510_DSP_MMU
+#elif defined(CONFIG_ARCH_OMAP16XX)
+#define INT_DSP_MMU    INT_1610_DSP_MMU
+#elif defined(CONFIG_ARCH_OMAP24XX)
+#define INT_DSP_MMU    INT_24XX_DSP_MMU
+#endif
 
 #define dspword_to_virt(dw)    ((void *)(dspmem_base + ((dw) << 1)))
 #define dspbyte_to_virt(db)    ((void *)(dspmem_base + (db)))
-#define virt_to_dspword(va)    (((unsigned long)(va) - dspmem_base) >> 1)
-#define virt_to_dspbyte(va)    ((unsigned long)(va) - dspmem_base)
+#define virt_to_dspword(va) \
+       ((dsp_long_t)(((unsigned long)(va) - dspmem_base) >> 1))
+#define virt_to_dspbyte(va) \
+       ((dsp_long_t)((unsigned long)(va) - dspmem_base))
 #define is_dsp_internal_mem(va) \
        (((unsigned long)(va) >= dspmem_base) &&  \
         ((unsigned long)(va) < dspmem_base + dspmem_size))
 #define is_dspbyte_internal_mem(db)    ((db) < dspmem_size)
 #define is_dspword_internal_mem(dw)    (((dw) << 1) < dspmem_size)
 
+#ifdef CONFIG_ARCH_OMAP1
 /*
  * MPUI byteswap/wordswap on/off
  *   default setting: wordswap = all, byteswap = APIMEM only
  */
 #define mpui_wordswap_on() \
-       do { \
-               omap_writel( \
-                       (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_WORDSWAP_MASK) | \
-                       MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL); \
-       } while(0)
+       omap_set_bits_regl(MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL_WORDSWAP_MASK, \
+                          MPUI_CTRL)
 
 #define mpui_wordswap_off() \
-       do { \
-               omap_writel( \
-                       (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_WORDSWAP_MASK) | \
-                       MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL); \
-       } while(0)
+       omap_set_bits_regl(MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL_WORDSWAP_MASK, \
+                          MPUI_CTRL)
 
 #define mpui_byteswap_on() \
-       do { \
-               omap_writel( \
-                       (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_BYTESWAP_MASK) | \
-                       MPUI_CTRL_BYTESWAP_API, MPUI_CTRL); \
-       } while(0)
+       omap_set_bits_regl(MPUI_CTRL_BYTESWAP_API, MPUI_CTRL_BYTESWAP_MASK, \
+                          MPUI_CTRL)
 
 #define mpui_byteswap_off() \
-       do { \
-               omap_writel( \
-                       (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_BYTESWAP_MASK) | \
-                       MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL); \
-       } while(0)
+       omap_set_bits_regl(MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL_BYTESWAP_MASK, \
+                          MPUI_CTRL)
 
 /*
  * TC wordswap on / off
                            TC_ENDIANISM); \
        } while(0)
 
-#define tc_noswap() \
-       do {  \
-               omap_writel(omap_readl(TC_ENDIANISM) & ~TC_ENDIANISM_EN, \
-                           TC_ENDIANISM); \
-       } while(0)
+#define tc_noswap()    omap_clr_bit_regl(TC_ENDIANISM_EN, TC_ENDIANISM)
 
 /*
  * enable priority registers, EMIF, MPUI control logic
 #define __dsp_disable()        omap_clr_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
 #define __dsp_run()    omap_set_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
 #define __dsp_reset()  omap_clr_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
+#endif /* CONFIG_ARCH_OMAP1 */
 
+#ifdef CONFIG_ARCH_OMAP2
+/*
+ * PRCM / IPI control logic
+ */
+#define RSTCTRL_RST1_DSP       0x00000001
+#define RSTCTRL_RST2_DSP       0x00000002
+#define __dsp_core_enable() \
+       do { RM_RSTCTRL_DSP &= ~RSTCTRL_RST1_DSP; } while (0)
+#define __dsp_core_disable() \
+       do { RM_RSTCTRL_DSP |= RSTCTRL_RST1_DSP; } while (0)
+#define __dsp_per_enable() \
+       do { RM_RSTCTRL_DSP &= ~RSTCTRL_RST2_DSP; } while (0)
+#define __dsp_per_disable() \
+       do { RM_RSTCTRL_DSP |= RSTCTRL_RST2_DSP; } while (0)
+#endif /* CONFIG_ARCH_OMAP2 */
+
+typedef u32 dsp_long_t;        /* must have ability to carry TADD_ABORTADR */
+
+#if defined(CONFIG_ARCH_OMAP1)
 extern struct clk *dsp_ck_handle;
 extern struct clk *api_ck_handle;
-extern unsigned long dspmem_base, dspmem_size,
-                    daram_base, daram_size,
-                    saram_base, saram_size;
+#elif defined(CONFIG_ARCH_OMAP2)
+extern struct clk *dsp_fck_handle;
+extern struct clk *dsp_ick_handle;
+#endif
+extern dsp_long_t dspmem_base, dspmem_size,
+                 daram_base, daram_size,
+                 saram_base, saram_size;
 
-enum e_cpustat {
+enum cpustat_e {
        CPUSTAT_RESET = 0,
-       CPUSTAT_GBL_IDLE = 1,
-       CPUSTAT_CPU_IDLE = 2,
-       CPUSTAT_RUN = 3
+#ifdef CONFIG_ARCH_OMAP1
+       CPUSTAT_GBL_IDLE,
+       CPUSTAT_CPU_IDLE,
+#endif
+       CPUSTAT_RUN,
+       CPUSTAT_MAX
 };
 
-#define cpustat_name(stat) \
-       ((stat == CPUSTAT_RESET)    ? "RESET" :\
-        (stat == CPUSTAT_GBL_IDLE) ? "GBL_IDLE" :\
-        (stat == CPUSTAT_CPU_IDLE) ? "CPU_IDLE" :\
-        (stat == CPUSTAT_RUN)      ? "RUN" :\
-                                     "unknown")
-
-int dsp_set_rstvect(unsigned long adr);
-void dsp_set_idle_boot_base(unsigned long adr, size_t size);
-void dsp_cpustat_request(enum e_cpustat req);
-enum e_cpustat dsp_cpustat_get_stat(void);
-unsigned short dsp_cpustat_get_icrmask(void);
-void dsp_cpustat_set_icrmask(unsigned short mask);
+int dsp_set_rstvect(dsp_long_t adr);
+dsp_long_t dsp_get_rstvect(void);
+#ifdef CONFIG_ARCH_OMAP1
+void dsp_set_idle_boot_base(dsp_long_t adr, size_t size);
+void dsp_reset_idle_boot_base(void);
+#endif
+void dsp_cpustat_request(enum cpustat_e req);
+enum cpustat_e dsp_cpustat_get_stat(void);
+u16 dsp_cpustat_get_icrmask(void);
+void dsp_cpustat_set_icrmask(u16 mask);
+#ifdef CONFIG_ARCH_OMAP1
 void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void));
 void dsp_unregister_mem_cb(void);
+#endif
+
+#endif /* DRIVER_DSP_COMMON_H */
index 2e1cdca0e63eaabdacdf83e1ce6f7f5545a76b3d..39765890e135d5ab7f052008f08d5eaff51fe248 100644 (file)
 /*
- * linux/arch/arm/mach-omap/dsp/dsp_core.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * OMAP DSP driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/06/07:  DSP Gateway version 3.3
  */
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/signal.h>
+#include <linux/err.h>
+#include <linux/clk.h>
 #include <asm/delay.h>
-#include <asm/irq.h>
+#include <asm/arch/mailbox.h>
 #include <asm/arch/dsp_common.h>
-#include <asm/arch/dsp.h>
-#include "hardware_dsp.h"
+#include "dsp_mbcmd.h"
 #include "dsp.h"
 #include "ipbuf.h"
 
-
 MODULE_AUTHOR("Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>");
 MODULE_DESCRIPTION("OMAP DSP driver module");
 MODULE_LICENSE("GPL");
 
-enum mbseq_check_level {
-       MBSEQ_CHECK_NONE,       /* no check */
-       MBSEQ_CHECK_VERBOSE,    /* discard the illegal command and
-                                  error report */
-       MBSEQ_CHECK_SILENT,     /* discard the illegal command */
-};
-
-static enum mbseq_check_level mbseq_check_level = MBSEQ_CHECK_VERBOSE;
-
-static int mbx1_valid;
+struct mbx *mbx_dsp;
 static struct sync_seq *mbseq;
-static unsigned short mbseq_expect_tmp;
-static unsigned short *mbseq_expect = &mbseq_expect_tmp;
+static u16 mbseq_expect_tmp;
+static u16 *mbseq_expect = &mbseq_expect_tmp;
 
 /*
  * mailbox commands
  */
-extern void mbx1_wdsnd(struct mbcmd *mb);
-extern void mbx1_wdreq(struct mbcmd *mb);
-extern void mbx1_bksnd(struct mbcmd *mb);
-extern void mbx1_bkreq(struct mbcmd *mb);
-extern void mbx1_bkyld(struct mbcmd *mb);
-extern void mbx1_bksndp(struct mbcmd *mb);
-extern void mbx1_bkreqp(struct mbcmd *mb);
-extern void mbx1_tctl(struct mbcmd *mb);
-extern void mbx1_poll(struct mbcmd *mb);
+extern void mbx_wdsnd(struct mbcmd *mb);
+extern void mbx_wdreq(struct mbcmd *mb);
+extern void mbx_bksnd(struct mbcmd *mb);
+extern void mbx_bkreq(struct mbcmd *mb);
+extern void mbx_bkyld(struct mbcmd *mb);
+extern void mbx_bksndp(struct mbcmd *mb);
+extern void mbx_bkreqp(struct mbcmd *mb);
+extern void mbx_tctl(struct mbcmd *mb);
+extern void mbx_poll(struct mbcmd *mb);
 #ifdef OLD_BINARY_SUPPORT
 /* v3.3 obsolete */
-extern void mbx1_wdt(struct mbcmd *mb);
+extern void mbx_wdt(struct mbcmd *mb);
 #endif
-extern void mbx1_suspend(struct mbcmd *mb);
-static void mbx1_kfunc(struct mbcmd *mb);
-extern void mbx1_tcfg(struct mbcmd *mb);
-extern void mbx1_tadd(struct mbcmd *mb);
-extern void mbx1_tdel(struct mbcmd *mb);
-extern void mbx1_dspcfg(struct mbcmd *mb);
-extern void mbx1_regrw(struct mbcmd *mb);
-extern void mbx1_getvar(struct mbcmd *mb);
-extern void mbx1_err(struct mbcmd *mb);
-extern void mbx1_dbg(struct mbcmd *mb);
+extern void mbx_suspend(struct mbcmd *mb);
+static void mbx_kfunc(struct mbcmd *mb);
+extern void mbx_tcfg(struct mbcmd *mb);
+extern void mbx_tadd(struct mbcmd *mb);
+extern void mbx_tdel(struct mbcmd *mb);
+extern void mbx_dspcfg(struct mbcmd *mb);
+extern void mbx_regrw(struct mbcmd *mb);
+extern void mbx_getvar(struct mbcmd *mb);
+extern void mbx_err(struct mbcmd *mb);
+extern void mbx_dbg(struct mbcmd *mb);
 
 static const struct cmdinfo
-       cif_null     = { "Unknown",  CMD_L_TYPE_NULL,   NULL         },
-       cif_wdsnd    = { "WDSND",    CMD_L_TYPE_TID,    mbx1_wdsnd   },
-       cif_wdreq    = { "WDREQ",    CMD_L_TYPE_TID,    mbx1_wdreq   },
-       cif_bksnd    = { "BKSND",    CMD_L_TYPE_TID,    mbx1_bksnd   },
-       cif_bkreq    = { "BKREQ",    CMD_L_TYPE_TID,    mbx1_bkreq   },
-       cif_bkyld    = { "BKYLD",    CMD_L_TYPE_NULL,   mbx1_bkyld   },
-       cif_bksndp   = { "BKSNDP",   CMD_L_TYPE_TID,    mbx1_bksndp  },
-       cif_bkreqp   = { "BKREQP",   CMD_L_TYPE_TID,    mbx1_bkreqp  },
-       cif_tctl     = { "TCTL",     CMD_L_TYPE_TID,    mbx1_tctl    },
-       cif_poll     = { "POLL",     CMD_L_TYPE_NULL,   mbx1_poll    },
+       cif_wdsnd    = { "WDSND",    CMD_L_TYPE_TID,    mbx_wdsnd   },
+       cif_wdreq    = { "WDREQ",    CMD_L_TYPE_TID,    mbx_wdreq   },
+       cif_bksnd    = { "BKSND",    CMD_L_TYPE_TID,    mbx_bksnd   },
+       cif_bkreq    = { "BKREQ",    CMD_L_TYPE_TID,    mbx_bkreq   },
+       cif_bkyld    = { "BKYLD",    CMD_L_TYPE_NULL,   mbx_bkyld   },
+       cif_bksndp   = { "BKSNDP",   CMD_L_TYPE_TID,    mbx_bksndp  },
+       cif_bkreqp   = { "BKREQP",   CMD_L_TYPE_TID,    mbx_bkreqp  },
+       cif_tctl     = { "TCTL",     CMD_L_TYPE_TID,    mbx_tctl    },
+       cif_poll     = { "POLL",     CMD_L_TYPE_NULL,   mbx_poll    },
 #ifdef OLD_BINARY_SUPPORT
        /* v3.3 obsolete */
-       cif_wdt      = { "WDT",      CMD_L_TYPE_NULL,   mbx1_wdt     },
+       cif_wdt      = { "WDT",      CMD_L_TYPE_NULL,   mbx_wdt     },
 #endif
-       cif_runlevel = { "RUNLEVEL", CMD_L_TYPE_SUBCMD, NULL         },
-       cif_pm       = { "PM",       CMD_L_TYPE_SUBCMD, NULL         },
-       cif_suspend  = { "SUSPEND",  CMD_L_TYPE_NULL,   mbx1_suspend },
-       cif_kfunc    = { "KFUNC",    CMD_L_TYPE_SUBCMD, mbx1_kfunc   },
-       cif_tcfg     = { "TCFG",     CMD_L_TYPE_TID,    mbx1_tcfg    },
-       cif_tadd     = { "TADD",     CMD_L_TYPE_TID,    mbx1_tadd    },
-       cif_tdel     = { "TDEL",     CMD_L_TYPE_TID,    mbx1_tdel    },
-       cif_tstop    = { "TSTOP",    CMD_L_TYPE_TID,    NULL         },
-       cif_dspcfg   = { "DSPCFG",   CMD_L_TYPE_SUBCMD, mbx1_dspcfg  },
-       cif_regrw    = { "REGRW",    CMD_L_TYPE_SUBCMD, mbx1_regrw   },
-       cif_getvar   = { "GETVAR",   CMD_L_TYPE_SUBCMD, mbx1_getvar  },
-       cif_setvar   = { "SETVAR",   CMD_L_TYPE_SUBCMD, NULL         },
-       cif_err      = { "ERR",      CMD_L_TYPE_SUBCMD, mbx1_err     },
-       cif_dbg      = { "DBG",      CMD_L_TYPE_NULL,   mbx1_dbg     };
-
-const struct cmdinfo *cmdinfo[128] = {
-/*00*/ &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-/*10*/ &cif_wdsnd, &cif_wdreq, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-/*20*/ &cif_bksnd, &cif_bkreq, &cif_null, &cif_bkyld,
-       &cif_bksndp, &cif_bkreqp, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-/*30*/ &cif_tctl, &cif_null, &cif_poll, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-/*40*/ &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
+       cif_runlevel = { "RUNLEVEL", CMD_L_TYPE_SUBCMD, NULL        },
+       cif_pm       = { "PM",       CMD_L_TYPE_SUBCMD, NULL        },
+       cif_suspend  = { "SUSPEND",  CMD_L_TYPE_NULL,   mbx_suspend },
+       cif_kfunc    = { "KFUNC",    CMD_L_TYPE_SUBCMD, mbx_kfunc   },
+       cif_tcfg     = { "TCFG",     CMD_L_TYPE_TID,    mbx_tcfg    },
+       cif_tadd     = { "TADD",     CMD_L_TYPE_TID,    mbx_tadd    },
+       cif_tdel     = { "TDEL",     CMD_L_TYPE_TID,    mbx_tdel    },
+       cif_tstop    = { "TSTOP",    CMD_L_TYPE_TID,    NULL        },
+       cif_dspcfg   = { "DSPCFG",   CMD_L_TYPE_SUBCMD, mbx_dspcfg  },
+       cif_regrw    = { "REGRW",    CMD_L_TYPE_SUBCMD, mbx_regrw   },
+       cif_getvar   = { "GETVAR",   CMD_L_TYPE_SUBCMD, mbx_getvar  },
+       cif_setvar   = { "SETVAR",   CMD_L_TYPE_SUBCMD, NULL        },
+       cif_err      = { "ERR",      CMD_L_TYPE_SUBCMD, mbx_err     },
+       cif_dbg      = { "DBG",      CMD_L_TYPE_NULL,   mbx_dbg     };
+
+const struct cmdinfo *cmdinfo[MBX_CMD_MAX] = {
+       [MBX_CMD_DSP_WDSND]    = &cif_wdsnd,
+       [MBX_CMD_DSP_WDREQ]    = &cif_wdreq,
+       [MBX_CMD_DSP_BKSND]    = &cif_bksnd,
+       [MBX_CMD_DSP_BKREQ]    = &cif_bkreq,
+       [MBX_CMD_DSP_BKYLD]    = &cif_bkyld,
+       [MBX_CMD_DSP_BKSNDP]   = &cif_bksndp,
+       [MBX_CMD_DSP_BKREQP]   = &cif_bkreqp,
+       [MBX_CMD_DSP_TCTL]     = &cif_tctl,
+       [MBX_CMD_DSP_POLL]     = &cif_poll,
 #ifdef OLD_BINARY_SUPPORT
-       /* v3.3 obsolete */
-/*50*/ &cif_wdt, &cif_runlevel, &cif_pm, &cif_suspend,
-#else
-/*50*/ &cif_null, &cif_runlevel, &cif_pm, &cif_suspend,
+       [MBX_CMD_DSP_WDT]      = &cif_wdt, /* v3.3 obsolete */
 #endif
-       &cif_kfunc, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-/*60*/ &cif_tcfg, &cif_null, &cif_tadd, &cif_tdel,
-       &cif_null, &cif_tstop, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null,
-/*70*/ &cif_dspcfg, &cif_null, &cif_regrw, &cif_null,
-       &cif_getvar, &cif_setvar, &cif_null, &cif_null,
-       &cif_err, &cif_dbg, &cif_null, &cif_null,
-       &cif_null, &cif_null, &cif_null, &cif_null
+       [MBX_CMD_DSP_RUNLEVEL] = &cif_runlevel,
+       [MBX_CMD_DSP_PM]       = &cif_pm,
+       [MBX_CMD_DSP_SUSPEND]  = &cif_suspend,
+       [MBX_CMD_DSP_KFUNC]    = &cif_kfunc,
+       [MBX_CMD_DSP_TCFG]     = &cif_tcfg,
+       [MBX_CMD_DSP_TADD]     = &cif_tadd,
+       [MBX_CMD_DSP_TDEL]     = &cif_tdel,
+       [MBX_CMD_DSP_TSTOP]    = &cif_tstop,
+       [MBX_CMD_DSP_DSPCFG]   = &cif_dspcfg,
+       [MBX_CMD_DSP_REGRW]    = &cif_regrw,
+       [MBX_CMD_DSP_GETVAR]   = &cif_getvar,
+       [MBX_CMD_DSP_SETVAR]   = &cif_setvar,
+       [MBX_CMD_DSP_ERR]      = &cif_err,
+       [MBX_CMD_DSP_DBG]      = &cif_dbg,
 };
 
-int sync_with_dsp(unsigned short *syncwd, unsigned short tid, int try_cnt)
+int sync_with_dsp(u16 *adr, u16 val, int try_cnt)
 {
        int try;
 
-       if (*(volatile unsigned short *)syncwd == tid)
+       if (*(volatile u16 *)adr == val)
                return 0;
 
        for (try = 0; try < try_cnt; try++) {
                udelay(1);
-               if (*(volatile unsigned short *)syncwd == tid) {
+               if (*(volatile u16 *)adr == val) {
                        /* success! */
                        printk(KERN_INFO
                               "omapdsp: sync_with_dsp(): try = %d\n", try);
@@ -180,73 +150,11 @@ int sync_with_dsp(unsigned short *syncwd, unsigned short tid, int try_cnt)
        return -1;
 }
 
-static __inline__ int mbsync_irq_save(unsigned long *flags, int try_cnt)
-{
-       int cnt;
-
-       local_irq_save(*flags);
-       if (omap_readw(MAILBOX_ARM2DSP1_Flag) == 0)
-               return 0;
-       /*
-        * mailbox is busy. wait for some usecs...
-        */
-       local_irq_restore(*flags);
-       for (cnt = 0; cnt < try_cnt; cnt++) {
-               udelay(1);
-               local_irq_save(*flags);
-               if (omap_readw(MAILBOX_ARM2DSP1_Flag) == 0)     /* success! */
-                       return 0;
-               local_irq_restore(*flags);
-       }
-
-       /* fail! */
-       return -1;
-}
-
-#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
-#define print_mb_busy_abort(mb) \
-       printk(KERN_DEBUG \
-              "mbx: mailbox is busy. %s is aborting.\n", cmd_name(*mb))
-#define print_mb_mmu_abort(mb) \
-       printk(KERN_DEBUG \
-              "mbx: mmu interrupt is set. %s is aborting.\n", cmd_name(*mb))
-#else /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
-#define print_mb_busy_abort(mb)        do {} while(0)
-#define print_mb_mmu_abort(mb) do {} while(0)
-#endif /* !CONFIG_OMAP_DSP_MBCMD_VERBOSE */
-
-int __mbcmd_send(struct mbcmd *mb)
-{
-       struct mbcmd_hw *mb_hw = (struct mbcmd_hw *)mb;
-       unsigned long flags;
-
-       /*
-        * DSP mailbox interrupt latency must be less than 1ms.
-        */
-       if (mbsync_irq_save(&flags, 1000) < 0) {
-               print_mb_busy_abort(mb);
-               return -1;
-       }
-
-       if (mbseq) {
-               mb->seq = mbseq->ad_arm;
-               mbseq->ad_arm++;
-       } else
-               mb->seq = 0;
-       mblog_add(mb, DIR_A2D);
-       mblog_printcmd(mb, DIR_A2D);
-
-       omap_writew(mb_hw->data, MAILBOX_ARM2DSP1);
-       omap_writew(mb_hw->cmd, MAILBOX_ARM2DSP1b);
-
-       local_irq_restore(flags);
-       return 0;
-}
-
 /*
- * __dsp_mbcmd_send(): mailbox dispatcher
+ * __dsp_mbcmd_send_exarg(): mailbox dispatcher
  */
-int __dsp_mbcmd_send(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
+int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+                          int recovery_flag)
 {
        static DEFINE_MUTEX(mbsend_lock);
        int ret = 0;
@@ -255,8 +163,10 @@ int __dsp_mbcmd_send(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
         * while MMU fault is set,
         * only recovery command can be executed
         */
-       if (dsp_err_mmu_isset() && !recovery_flag) {
-               print_mb_mmu_abort(mb);
+       if (dsp_err_isset(ERRCODE_MMU) && !recovery_flag) {
+               printk(KERN_ERR
+                      "mbx: mmu interrupt is set. %s is aborting.\n",
+                      cmd_name(*mb));
                return -1;
        }
 
@@ -275,7 +185,7 @@ int __dsp_mbcmd_send(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
                 * Therefore, we can call this function here safely.
                 */
                dsp_mem_enable(ipbuf_sys_ad);
-               if (sync_with_dsp(&ipbuf_sys_ad->s, OMAP_DSP_TID_FREE, 10) < 0) {
+               if (sync_with_dsp(&ipbuf_sys_ad->s, TID_FREE, 10) < 0) {
                        printk(KERN_ERR "omapdsp: ipbuf_sys_ad is busy.\n");
                        dsp_mem_disable(ipbuf_sys_ad);
                        ret = -EBUSY;
@@ -288,15 +198,21 @@ int __dsp_mbcmd_send(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
                dsp_mem_disable(ipbuf_sys_ad);
        }
 
-       ret = __mbcmd_send(mb);
+       if (mbseq)
+               mbseq->ad_arm++;
+
+       mblog_add(mb, DIR_A2D);
+       mblog_printcmd(mb, DIR_A2D);
+
+       ret = mbx_send(mbx_dsp, *(mbx_msg_t *)mb);
 
 out:
        mutex_unlock(&mbsend_lock);
        return ret;
 }
 
-int __dsp_mbcmd_send_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
-                             wait_queue_head_t *q)
+int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+                                 wait_queue_head_t *q)
 {
        long current_state;
        DECLARE_WAITQUEUE(wait, current);
@@ -316,35 +232,47 @@ int __dsp_mbcmd_send_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
        return 0;
 }
 
-int __dsp_mbsend(unsigned char cmdh, unsigned char cmdl, unsigned short data,
-                int recovery_flag)
+/*
+ * mbcmd receiver
+ */
+static void mbcmd_receiver(mbx_msg_t msg)
 {
-       struct mbcmd mb;
+       struct mbcmd *mb = (struct mbcmd *)&msg;
+
+       if (cmdinfo[mb->cmd_h] == NULL) {
+               printk(KERN_ERR
+                      "invalid message (%08x) for mbcmd_receiver().\n", msg);
+               return;
+       }
+
+       (*mbseq_expect)++;
+
+       mblog_add(mb, DIR_D2A);
+       mblog_printcmd(mb, DIR_D2A);
 
-       mbcmd_set(mb, cmdh, cmdl, data);
-       return __dsp_mbcmd_send(&mb, NULL, recovery_flag);
+       /* call handler for the command */
+       if (cmdinfo[mb->cmd_h]->handler)
+               cmdinfo[mb->cmd_h]->handler(mb);
+       else
+               printk(KERN_ERR "mbx: %s is not allowed from DSP.\n",
+                      cmd_name(*mb));
 }
 
 static int mbsync_hold_mem_active;
 
-void dsp_mb_start(void)
+void dsp_mbx_start(void)
 {
-       mbx1_valid = 1; /* start interpreting */
+       mbx_init_seq(mbx_dsp);
        mbseq_expect_tmp = 0;
 }
 
-void dsp_mb_stop(void)
+void dsp_mbx_stop(void)
 {
-       mbx1_valid = 0; /* stop interpreting */
-       if (mbsync_hold_mem_active) {
-               dsp_mem_disable((void *)daram_base);
-               mbsync_hold_mem_active = 0;
-       }
        mbseq = NULL;
        mbseq_expect = &mbseq_expect_tmp;
 }
 
-int dsp_mb_config(void *p)
+int dsp_mbx_config(void *p)
 {
        unsigned long flags;
 
@@ -372,106 +300,76 @@ int dsp_mb_config(void *p)
        return 0;
 }
 
-/*
- * mbq: mailbox queue
- */
-#define MBQ_DEPTH      16
-struct mbq {
-       struct mbcmd mb[MBQ_DEPTH];
-       int rp, wp, full;
-} mbq = {
-       .rp = 0,
-       .wp = 0,
-};
+static int __init dsp_mbx_init(void)
+{
+       int i;
+       int ret;
 
-#define mbq_inc(p)     do { if (++(p) == MBQ_DEPTH) (p) = 0; } while(0)
+       for (i = 0; i < MBX_CMD_MAX; i++) {
+               if (cmdinfo[i] != NULL) {
+                       ret = register_mbx_receiver(mbx_dsp, i, mbcmd_receiver);
+                       if (ret)
+                               goto fail;
+               }
+       }
 
-/*
- * workqueue for mbx1
- */
-static void do_mbx1(void)
-{
-       int empty = 0;
+       return 0;
 
-       disable_irq(INT_D2A_MB1);
-       if ((mbq.rp == mbq.wp) && !mbq.full)
-               empty = 1;
-       enable_irq(INT_D2A_MB1);
+fail:
+       for (i--; i; i--)
+               unregister_mbx_receiver(mbx_dsp, i, mbcmd_receiver);
 
-       while (!empty) {
-               struct mbcmd *mb;
+       return ret;
+}
 
-               mb = &mbq.mb[mbq.rp];
+static void dsp_mbx_exit(void)
+{
+       int i;
 
-               mblog_add(mb, DIR_D2A);
-               mblog_printcmd(mb, DIR_D2A);
+       for (i = 0; i < MBX_CMD_MAX; i++) {
+               if (cmdinfo[i] != NULL)
+                       unregister_mbx_receiver(mbx_dsp, i, mbcmd_receiver);
+       }
 
-               /*
-                * call handler for each command
-                */
-               if (cmdinfo[mb->cmd_h]->handler)
-                       cmdinfo[mb->cmd_h]->handler(mb);
-               else if (cmdinfo[mb->cmd_h] != &cif_null)
-                       printk(KERN_ERR "mbx: %s is not allowed from DSP.\n",
-                              cmd_name(*mb));
-               else
-                       printk(KERN_ERR
-                              "mbx: Unrecognized command: "
-                              "cmd=0x%04x, data=0x%04x\n",
-                              ((struct mbcmd_hw *)mb)->cmd & 0x7fff, mb->data);
-
-               disable_irq(INT_D2A_MB1);
-               mbq_inc(mbq.rp);
-               if (mbq.rp == mbq.wp)
-                       empty = 1;
-               /* if mbq has been full, now we have a room. */
-               if (mbq.full) {
-                       mbq.full = 0;
-                       enable_irq(INT_D2A_MB1);
-               }
-               enable_irq(INT_D2A_MB1);
+       if (mbsync_hold_mem_active) {
+               dsp_mem_disable((void *)daram_base);
+               mbsync_hold_mem_active = 0;
        }
 }
 
-static DECLARE_WORK(mbx1_work, (void (*)(void *))do_mbx1, NULL);
-
 /*
  * kernel function dispatcher
  */
-extern void mbx1_fbctl_upd(void);
-extern void mbx1_fbctl_disable(void);
+extern void mbx_fbctl_upd(void);
+extern void mbx_fbctl_disable(struct mbcmd *mb);
 
-static void mbx1_kfunc_fbctl(unsigned short data)
+static void mbx_kfunc_fbctl(struct mbcmd *mb)
 {
-       switch (data) {
-       case OMAP_DSP_MBCMD_FBCTL_UPD:
-               mbx1_fbctl_upd();
+       switch (mb->data) {
+       case FBCTL_UPD:
+               mbx_fbctl_upd();
                break;
-       case OMAP_DSP_MBCMD_FBCTL_DISABLE:
-               mbx1_fbctl_disable();
+       case FBCTL_DISABLE:
+               mbx_fbctl_disable(mb);
                break;
        default:
                printk(KERN_ERR
-                      "mailbox: Unknown FBCTL from DSP: 0x%04x\n", data);
+                      "mbx: Unknown FBCTL from DSP: 0x%04x\n", mb->data);
        }
 }
 
-static void mbx1_kfunc_audio_pwr(unsigned short data)
+static void mbx_kfunc_audio_pwr(unsigned short data)
 {
-       struct mbcmd mb;
-
        switch (data) {
-       case OMAP_DSP_MBCMD_AUDIO_PWR_UP:
+       case AUDIO_PWR_UP:
                omap_dsp_audio_pwr_up_request(0);
                /* send back ack */
-               mbcmd_set(mb, MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR,
-                         OMAP_DSP_MBCMD_AUDIO_PWR_UP);
-               dsp_mbcmd_send(&mb);
+               mbcompose_send(KFUNC, KFUNC_AUDIO_PWR, AUDIO_PWR_UP);
                break;
-       case OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1:
+       case AUDIO_PWR_DOWN1:
                omap_dsp_audio_pwr_down_request(1);
                break;
-       case OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2:
+       case AUDIO_PWR_DOWN2:
                omap_dsp_audio_pwr_down_request(2);
                break;
        default:
@@ -480,118 +378,21 @@ static void mbx1_kfunc_audio_pwr(unsigned short data)
        }
 }
 
-static void mbx1_kfunc(struct mbcmd *mb)
+static void mbx_kfunc(struct mbcmd *mb)
 {
        switch (mb->cmd_l) {
-       case OMAP_DSP_MBCMD_KFUNC_FBCTL:
-               mbx1_kfunc_fbctl(mb->data);
+       case KFUNC_FBCTL:
+               mbx_kfunc_fbctl(mb);
                break;
-       case OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR:
-               mbx1_kfunc_audio_pwr(mb->data);
+       case KFUNC_AUDIO_PWR:
+               mbx_kfunc_audio_pwr(mb->data);
                break;
        default:
                printk(KERN_ERR
-                      "mailbox: Unknown kfunc from DSP: 0x%02x\n", mb->cmd_l);
-       }
-}
-
-/*
- * mailbox interrupt handler
- */
-static irqreturn_t mbx1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       union {
-               struct mbcmd sw;
-               struct mbcmd_hw hw;
-       } *mb = (void *)&mbq.mb[mbq.wp];
-
-#if (INT_D2A_MB1 == INT_DSP_MAILBOX1)
-       mb->hw.data = omap_readw(MAILBOX_DSP2ARM1);
-       mb->hw.cmd  = omap_readw(MAILBOX_DSP2ARM1b);
-#elif (INT_D2A_MB1 == INT_DSP_MAILBOX2)
-       mb->hw.data = omap_readw(MAILBOX_DSP2ARM2);
-       mb->hw.cmd  = omap_readw(MAILBOX_DSP2ARM2b);
-#endif
-
-       /* if mbx1 has not been validated yet, discard. */
-       if (!mbx1_valid)
-               return IRQ_HANDLED;
-
-       if (mb->sw.seq != (*mbseq_expect & 1)) {
-               switch (mbseq_check_level) {
-               case MBSEQ_CHECK_NONE:
-                       break;
-               case MBSEQ_CHECK_VERBOSE:
-                       printk(KERN_INFO
-                              "mbx: illegal seq bit!!!  ignoring this command."
-                              " (%04x:%04x)\n", mb->hw.cmd, mb->hw.data);
-                       return IRQ_HANDLED;
-               case MBSEQ_CHECK_SILENT:
-                       return IRQ_HANDLED;
-               }
-       }
-
-       (*mbseq_expect)++;
-
-       mbq_inc(mbq.wp);
-       if (mbq.wp == mbq.rp) { /* mbq is full */
-               mbq.full = 1;
-               disable_irq(INT_D2A_MB1);
+                      "mbx: Unknown KFUNC from DSP: 0x%02x\n", mb->cmd_l);
        }
-       schedule_work(&mbx1_work);
-
-       return IRQ_HANDLED;
 }
 
-static irqreturn_t mbx2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       unsigned short cmd, data;
-
-#if (INT_D2A_MB1 == INT_DSP_MAILBOX1)
-       data = omap_readw(MAILBOX_DSP2ARM2);
-       cmd  = omap_readw(MAILBOX_DSP2ARM2b);
-#elif (INT_D2A_MB1 == INT_DSP_MAILBOX2)
-       data = omap_readw(MAILBOX_DSP2ARM1);
-       cmd  = omap_readw(MAILBOX_DSP2ARM1b);
-#endif
-       printk(KERN_DEBUG
-              "mailbox2 interrupt!  cmd=%04x, data=%04x\n", cmd, data);
-
-       return IRQ_HANDLED;
-}
-
-#if 0
-static void mpuio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       printk(KERN_INFO "MPUIO interrupt!\n");
-}
-#endif
-
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry *procdir_dsp = NULL;
-
-static void dsp_create_procdir_dsp(void)
-{
-       procdir_dsp = proc_mkdir("dsp", 0);
-       if (procdir_dsp == NULL) {
-               printk(KERN_ERR
-                      "omapdsp: failed to register proc directory: dsp\n");
-       }
-}
-
-static void dsp_remove_procdir_dsp(void)
-{
-       procdir_dsp = NULL;
-       remove_proc_entry("dsp", 0);
-}
-#else /* CONFIG_PROC_FS */
-#define dsp_create_procdir_dsp()       do { } while (0)
-#define dsp_remove_procdir_dsp()       do { } while (0)
-#endif /* CONFIG_PROC_FS */
-
-extern irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id,
-                                    struct pt_regs *regs);
-
 extern int  dsp_ctl_core_init(void);
 extern void dsp_ctl_core_exit(void);
 extern void dsp_ctl_init(void);
@@ -613,21 +414,16 @@ static void dsp_dev_release(struct device *dev)
 /*
  * driver functions
  */
-#if (INT_D2A_MB1 == INT_DSP_MAILBOX1)
-#      define INT_D2A_MB2 INT_DSP_MAILBOX2
-#elif(INT_D2A_MB1 == INT_DSP_MAILBOX2) /* swap MB1 and MB2 */
-#      define INT_D2A_MB2 INT_DSP_MAILBOX1
-#endif
-
 static int __init dsp_drv_probe(struct platform_device *pdev)
 {
        int ret;
 
        printk(KERN_INFO "OMAP DSP driver initialization\n");
-
-       //__dsp_enable(); // XXX
-
-       dsp_create_procdir_dsp();
+#ifdef CONFIG_ARCH_OMAP2
+       clk_enable(dsp_fck_handle);
+       clk_enable(dsp_ick_handle);
+       __dsp_per_enable();
+#endif
 
        if ((ret = dsp_ctl_core_init()) < 0)
                goto fail1;
@@ -637,52 +433,11 @@ static int __init dsp_drv_probe(struct platform_device *pdev)
        mblog_init();
        if ((ret = dsp_taskmod_init()) < 0)
                goto fail3;
-
-       /*
-        * mailbox interrupt handlers registration
-        */
-       ret = request_irq(INT_D2A_MB1, mbx1_interrupt, SA_INTERRUPT, "dsp",
-                         &pdev->dev);
-       if (ret) {
-               printk(KERN_ERR
-                      "failed to register mailbox1 interrupt: %d\n", ret);
+       if ((ret = dsp_mbx_init()) < 0)
                goto fail4;
-       }
-
-       ret = request_irq(INT_D2A_MB2, mbx2_interrupt, SA_INTERRUPT, "dsp",
-                         &pdev->dev);
-       if (ret) {
-               printk(KERN_ERR
-                      "failed to register mailbox2 interrupt: %d\n", ret);
-               goto fail5;
-       }
-
-       ret = request_irq(INT_DSP_MMU, dsp_mmu_interrupt, SA_INTERRUPT, "dsp",
-                         &pdev->dev);
-       if (ret) {
-               printk(KERN_ERR
-                      "failed to register DSP MMU interrupt: %d\n", ret);
-               goto fail6;
-       }
-
-       /* MMU interrupt is not enabled until DSP runs */
-       disable_irq(INT_DSP_MMU);
-
-#if 0
-       ret = request_irq(INT_MPUIO, mpuio_interrupt, SA_INTERRUPT, "dsp", dev);
-       if (ret) {
-               printk(KERN_ERR
-                      "failed to register MPUIO interrupt: %d\n", ret);
-               goto fail7;
-       }
-#endif
 
        return 0;
 
-fail6:
-       free_irq(INT_D2A_MB2, &pdev->dev);
-fail5:
-       free_irq(INT_D2A_MB1, &pdev->dev);
 fail4:
        dsp_taskmod_exit();
 fail3:
@@ -692,9 +447,11 @@ fail3:
 fail2:
        dsp_ctl_core_exit();
 fail1:
-       dsp_remove_procdir_dsp();
-
-       //__dsp_disable(); // XXX
+#ifdef CONFIG_ARCH_OMAP2
+       __dsp_per_disable();
+       clk_disable(dsp_ick_handle);
+       clk_disable(dsp_fck_handle);
+#endif
        return ret;
 }
 
@@ -702,41 +459,34 @@ static int dsp_drv_remove(struct platform_device *pdev)
 {
        dsp_cpustat_request(CPUSTAT_RESET);
 
-#if 0
-       free_irq(INT_MPUIO, dev);
-#endif
-       free_irq(INT_DSP_MMU, &pdev->dev);
-       free_irq(INT_D2A_MB2, &pdev->dev);
-       free_irq(INT_D2A_MB1, &pdev->dev);
-
-       /* recover disable_depth */
-       enable_irq(INT_DSP_MMU);
-
-       dspuncfg();
+       dsp_cfgstat_request(CFGSTAT_CLEAN);
+       dsp_mbx_exit();
        dsp_taskmod_exit();
        mblog_exit();
        dsp_ctl_exit();
        dsp_mem_exit();
 
        dsp_ctl_core_exit();
-       dsp_remove_procdir_dsp();
-
-       //__dsp_disable(); // XXX
 
+#ifdef CONFIG_ARCH_OMAP2
+       __dsp_per_disable();
+       clk_disable(dsp_ick_handle);
+       clk_disable(dsp_fck_handle);
+#endif
        return 0;
 }
 
 #ifdef CONFIG_PM
 static int dsp_drv_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       dsp_suspend();
+       dsp_cfgstat_request(CFGSTAT_SUSPEND);
 
        return 0;
 }
 
 static int dsp_drv_resume(struct platform_device *pdev)
 {
-       dsp_resume();
+       dsp_cfgstat_request(CFGSTAT_RESUME);
 
        return 0;
 }
@@ -746,14 +496,6 @@ static int dsp_drv_resume(struct platform_device *pdev)
 #endif /* CONFIG_PM */
 
 static struct resource dsp_resources[] = {
-       {
-               .start = INT_DSP_MAILBOX1,
-               .flags = IORESOURCE_IRQ,
-       },
-       {
-               .start = INT_DSP_MAILBOX2,
-               .flags = IORESOURCE_IRQ,
-       },
        {
                .start = INT_DSP_MMU,
                .flags = IORESOURCE_IRQ,
@@ -784,6 +526,12 @@ static int __init omap_dsp_mod_init(void)
 {
        int ret;
 
+       mbx_dsp = mbx_get("DSP");
+       if (IS_ERR(mbx_dsp)) {
+               printk(KERN_ERR "failed to get mailbox handler for DSP.\n");
+               goto fail1;
+       }
+
        ret = platform_device_register(&dsp_device);
        if (ret) {
                printk(KERN_ERR "failed to register the DSP device: %d\n", ret);
index 3fab9489c974e3eb84f3b92dbddc930ec380569f..4323150b1d847b45b70670052ffa84311984c68a 100644 (file)
@@ -1,35 +1,29 @@
 /*
- * linux/arch/arm/mach-omap/dsp/dsp_ctl.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * OMAP DSP control device driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/06/09:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/device.h>
-#include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/ioctls.h>
-#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
 #include "hardware_dsp.h"
+#include "dsp_mbcmd.h"
 #include "dsp.h"
 #include "ipbuf.h"
+#include "ioctl.h"
+
+enum dsp_space_e {
+       SPACE_MEM,
+       SPACE_IO,
+};
+
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+static enum fbstat_e {
+       FBSTAT_DISABLED = 0,
+       FBSTAT_ENABLED,
+       FBSTAT_MAX,
+} fbstat = FBSTAT_ENABLED;
+#endif
+
+static enum cfgstat_e cfgstat;
+int mbx_revision;
+static u8 n_stask;
 
+static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
+                         char *buf);
+static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
+                           char *buf);
+static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
+                           char *buf);
+static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
+                            const char *buf, size_t count);
 static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
                             char *buf);
-static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
-extern struct device_attribute dev_attr_ipbuf;
-
-static enum cfgstat {
-       CFG_ERR,
-       CFG_READY,
-       CFG_SUSPEND
-} cfgstat;
-int mbx_revision;
-static DECLARE_WAIT_QUEUE_HEAD(ioctl_wait_q);
-static unsigned short ioctl_wait_cmd;
-static DEFINE_MUTEX(ioctl_lock);
 
-static unsigned char n_stask;
+#define __ATTR_RW(_name, _mode) { \
+       .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
+       .show   = _name##_show,                                 \
+       .store  = _name##_store,                                        \
+}
+
+static struct device_attribute dev_attr_ifver     = __ATTR_RO(ifver);
+static struct device_attribute dev_attr_cpustat   = __ATTR_RO(cpustat);
+static struct device_attribute dev_attr_icrmask   = __ATTR_RW(icrmask, 0644);
+static struct device_attribute dev_attr_loadinfo  = __ATTR_RO(loadinfo);
 
 /*
- * control functions
+ * misc interactive mailbox command operations
  */
-static short varread_val[5]; /* maximum */
+static struct misc_mb_wait_struct {
+       struct mutex lock;
+       wait_queue_head_t wait_q;
+       u8 cmd_h;
+       u8 cmd_l;
+       u16 *retvp;
+} misc_mb_wait = {
+       .lock = __MUTEX_INITIALIZER(misc_mb_wait.lock),
+       .wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(misc_mb_wait.wait_q),
+};
 
-static int dsp_regread(unsigned short cmd_l, unsigned short adr,
-                      unsigned short *val)
+static int __misc_mbcompose_send_and_wait(u8 cmd_h, u8 cmd_l, u16 data,
+                                         u16 *retvp)
 {
-       struct mbcmd mb;
+       struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
        int ret = 0;
 
-       if (mutex_lock_interruptible(&ioctl_lock))
-               return -ERESTARTSYS;
+       if (mutex_lock_interruptible(&misc_mb_wait.lock))
+               return -EINTR;
 
-       ioctl_wait_cmd = MBCMD(REGRW);
-       mbcmd_set(mb, MBCMD(REGRW), cmd_l, adr);
-       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+       misc_mb_wait.cmd_h = mb.cmd_h;
+       misc_mb_wait.cmd_l = mb.cmd_l;
+       misc_mb_wait.retvp = retvp;
+       dsp_mbcmd_send_and_wait(&mb, &misc_mb_wait.wait_q);
 
-       if (ioctl_wait_cmd != 0) {
-               printk(KERN_ERR "omapdsp: register read error!\n");
+       if (misc_mb_wait.cmd_h != 0)
                ret = -EINVAL;
-               goto up_out;
+
+       mutex_unlock(&misc_mb_wait.lock);
+       return ret;
+}
+
+#define misc_mbcompose_send_and_wait(cmd_h, cmd_l, data, retvp) \
+               __misc_mbcompose_send_and_wait(MBX_CMD_DSP_##cmd_h, (cmd_l), \
+                                              (data), (retvp));
+
+static int misc_mbcmd_response(struct mbcmd *mb, int argc, int match_cmd_l_flag)
+{
+       volatile u16 *buf;
+       int i;
+
+       /* if match_cmd_l_v flag is set, cmd_l needs to be matched as well. */
+       if (!waitqueue_active(&misc_mb_wait.wait_q) ||
+           (misc_mb_wait.cmd_h != mb->cmd_h) ||
+           (match_cmd_l_flag && (misc_mb_wait.cmd_l != mb->cmd_l))) {
+               const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
+               char cmdstr[32];
+
+               if (ci->cmd_l_type == CMD_L_TYPE_SUBCMD)
+                       sprintf(cmdstr, "%s:%s", ci->name, subcmd_name(mb));
+               else
+                       strcpy(cmdstr, ci->name);
+               printk(KERN_WARNING
+                      "mbx: unexpected command %s received!\n", cmdstr);
+               return -1;
+       }
+
+       /*
+        * if argc == 1, receive data through mbx:data register.
+        * if argc > 1, receive through ipbuf_sys.
+        */
+       if (argc == 1)
+               misc_mb_wait.retvp[0] = mb->data;
+       else if (argc > 1) {
+               if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+                       printk(KERN_ERR "mbx: %s - ipbuf_sys_da read failed!\n",
+                              cmdinfo[mb->cmd_h]->name);
+                       return -1;
+               }
+               if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
+                       printk(KERN_ERR "mbx: %s - IPBUF sync failed!\n",
+                              cmdinfo[mb->cmd_h]->name);
+                       dsp_mem_disable(ipbuf_sys_da);
+                       return -1;
+               }
+               /* need word access. do not use memcpy. */
+               buf = ipbuf_sys_da->d;
+               for (i = 0; i < argc; i++)
+                       misc_mb_wait.retvp[i] = buf[i];
+               release_ipbuf_pvt(ipbuf_sys_da);
+               dsp_mem_disable(ipbuf_sys_da);
        }
 
-       *val = varread_val[0];
+       misc_mb_wait.cmd_h = 0;
+       wake_up_interruptible(&misc_mb_wait.wait_q);
+       return 0;
+}
+
+static int dsp_regread(enum dsp_space_e space, u16 adr, u16 *val)
+{
+       u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMR : REGRW_IOR;
+       int ret; 
+
+       ret = misc_mbcompose_send_and_wait(REGRW, cmd_l, adr, val);
+       if ((ret < 0) && (ret != -EINTR))
+               printk(KERN_ERR "omapdsp: register read error!\n");
 
-up_out:
-       mutex_unlock(&ioctl_lock);
        return ret;
 }
 
-static int dsp_regwrite(unsigned short cmd_l, unsigned short adr,
-                       unsigned short val)
+static int dsp_regwrite(enum dsp_space_e space, u16 adr, u16 val)
 {
-       struct mbcmd mb;
+       u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMW : REGRW_IOW;
        struct mb_exarg arg = {
-               .tid  = OMAP_DSP_TID_ANON,
+               .tid  = TID_ANON,
                .argc = 1,
                .argv = &val,
        };
 
-       mbcmd_set(mb, MBCMD(REGRW), cmd_l, adr);
-       dsp_mbcmd_send_exarg(&mb, &arg);
+       mbcompose_send_exarg(REGRW, cmd_l, adr, &arg);
        return 0;
 }
 
-static int dsp_getvar(unsigned char varid, unsigned short *val, int sz)
+static int dsp_getvar(u8 varid, u16 *val)
 {
-       struct mbcmd mb;
-       int ret = 0;
-
-       if (mutex_lock_interruptible(&ioctl_lock))
-               return -ERESTARTSYS;
-
-       ioctl_wait_cmd = MBCMD(GETVAR);
-       mbcmd_set(mb, MBCMD(GETVAR), varid, 0);
-       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+       int ret;
 
-       if (ioctl_wait_cmd != 0) {
+       ret = misc_mbcompose_send_and_wait(GETVAR, varid, 0, val);
+       if ((ret < 0) && (ret != -EINTR))
                printk(KERN_ERR "omapdsp: variable read error!\n");
-               ret = -EINVAL;
-               goto up_out;
-       }
-
-       memcpy(val, varread_val, sz * sizeof(short));
 
-up_out:
-       mutex_unlock(&ioctl_lock);
        return ret;
 }
 
-static int dsp_setvar(unsigned char varid, unsigned short val)
+static int dsp_setvar(u8 varid, u16 val)
 {
-       dsp_mbsend(MBCMD(SETVAR), varid, val);
+       mbcompose_send(SETVAR, varid, val);
        return 0;
 }
 
-static int dspcfg(void)
+/*
+ * dsp_cfg() return value
+ *  = 0: OK
+ *  = 1: failed, but state is clear. (DSPCFG command failed)
+ *  < 0: failed. need cleanup.
+ */
+static int dsp_cfg(void)
 {
-       struct mbcmd mb;
        int ret = 0;
 
-       if (mutex_lock_interruptible(&ioctl_lock))
-               return -ERESTARTSYS;
-
-       if (cfgstat != CFG_ERR) {
-               printk(KERN_ERR
-                      "omapdsp: DSP has been already configured. "
-                      "do unconfig!\n");
-               ret = -EBUSY;
-               goto up_out;
-       }
-
+#ifdef CONFIG_ARCH_OMAP1
        /* for safety */
        dsp_mem_usecount_clear();
+#endif
 
        /*
         * DSPCFG command and dsp_mem_start() must be called
@@ -163,215 +233,270 @@ static int dspcfg(void)
         */
        dsp_mem_enable((void *)dspmem_base);
 
-       dsp_mb_start();
+       dsp_mbx_start();
        dsp_twch_start();
        dsp_mem_start();
        dsp_err_start();
 
        mbx_revision = -1;
-       ioctl_wait_cmd = MBCMD(DSPCFG);
-       mbcmd_set(mb, MBCMD(DSPCFG), OMAP_DSP_MBCMD_DSPCFG_REQ, 0);
-       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
 
-       if (ioctl_wait_cmd != 0) {
-               printk(KERN_ERR "omapdsp: configuration error!\n");
-               ret = -EINVAL;
-               cfgstat = CFG_ERR;
-               goto up_out;
+       ret = misc_mbcompose_send_and_wait(DSPCFG, DSPCFG_REQ, 0, NULL);
+       if (ret < 0) {
+               if (ret != -EINTR)
+                       printk(KERN_ERR "omapdsp: configuration error!\n");
+               ret = 1;
+               goto out;
        }
 
-#ifdef OLD_BINARY_SUPPORT
+#if defined(CONFIG_ARCH_OMAP1) && defined(OLD_BINARY_SUPPORT)
        /*
         * MBREV 3.2 or earlier doesn't assume DMA domain is on
         * when DSPCFG command is sent
         */
        if ((mbx_revision == MBREV_3_0) ||
            (mbx_revision == MBREV_3_2)) {
-               ret = dsp_mbsend(MBCMD(PM), OMAP_DSP_MBCMD_PM_ENABLE,
-                                DSPREG_ICR_DMA_IDLE_DOMAIN);
+               if ((ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA)) < 0)
+                       goto out;
        }
 #endif
 
-       if ((ret = dsp_task_config_all(n_stask)) < 0) {
-               mutex_unlock(&ioctl_lock);
-               dspuncfg();
-               dsp_mem_disable((void *)dspmem_base);
-               return -EINVAL;
-       }
+       if ((ret = dsp_task_config_all(n_stask)) < 0)
+               goto out;
 
-       cfgstat = CFG_READY;
+       /* initialization */
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+       fbstat = FBSTAT_ENABLED;
+#endif
 
        /* send parameter */
-       if ((ret = dsp_setvar(OMAP_DSP_MBCMD_VARID_ICRMASK,
-                             dsp_cpustat_get_icrmask())) < 0)
-               goto up_out;
+       if ((ret = dsp_setvar(VARID_ICRMASK, dsp_cpustat_get_icrmask())) < 0)
+               goto out;
 
        /* create runtime sysfs entries */
        device_create_file(&dsp_device.dev, &dev_attr_loadinfo);
-       device_create_file(&dsp_device.dev, &dev_attr_ipbuf);
 
-up_out:
+out:
        dsp_mem_disable((void *)dspmem_base);
-       mutex_unlock(&ioctl_lock);
        return ret;
 }
 
-int dspuncfg(void)
+static int dsp_uncfg(void)
 {
        if (dsp_taskmod_busy()) {
                printk(KERN_WARNING "omapdsp: tasks are busy.\n");
                return -EBUSY;
        }
 
-       if (mutex_lock_interruptible(&ioctl_lock))
-               return -ERESTARTSYS;
-
        /* FIXME: lock task module */
 
        /* remove runtime sysfs entries */
        device_remove_file(&dsp_device.dev, &dev_attr_loadinfo);
-       device_remove_file(&dsp_device.dev, &dev_attr_ipbuf);
 
-       dsp_mb_stop();
+       dsp_mbx_stop();
        dsp_twch_stop();
        dsp_mem_stop();
        dsp_err_stop();
        dsp_dbg_stop();
        dsp_task_unconfig_all();
        ipbuf_stop();
-       cfgstat = CFG_ERR;
 
-       mutex_unlock(&ioctl_lock);
        return 0;
 }
 
-int dsp_is_ready(void)
+static int dsp_suspend(void)
 {
-       return (cfgstat == CFG_READY) ? 1 : 0;
+       int ret;
+
+       ret = misc_mbcompose_send_and_wait(SUSPEND, 0, 0, NULL);
+       if (ret < 0) {
+               if (ret != -EINVAL)
+                       printk(KERN_ERR "omapdsp: DSP suspend error!\n");
+               return ret;
+       }
+
+       udelay(100);    /* wait for DSP-side execution */
+       return 0;
 }
 
-/*
- * polls all tasks
- */
-int dsp_poll(void)
+int dsp_cfgstat_request(enum cfgstat_e st_req)
 {
-       struct mbcmd mb;
-       int ret = 0;
+       static DEFINE_MUTEX(cfgstat_lock);
+       int ret = 0, ret_override = 0;
 
-       if (mutex_lock_interruptible(&ioctl_lock))
-               return -ERESTARTSYS;
+       if (mutex_lock_interruptible(&cfgstat_lock))
+               return -EINTR;
 
-       ioctl_wait_cmd = MBCMD(POLL);
-       mbcmd_set(mb, MBCMD(POLL), 0, 0);
-       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+again:
+       switch (st_req) {
 
-       if (ioctl_wait_cmd != 0) {
-               printk(KERN_ERR "omapdsp: poll error!\n");
-               ret = -EINVAL;
-               goto up_out;
-       }
+       /* cfgstat takes CLEAN, READY or SUSPEND,
+          while st_req can take SUSPEND in addition. */
 
-up_out:
-       mutex_unlock(&ioctl_lock);
-       return ret;
-}
+       case CFGSTAT_CLEAN:
+               if (cfgstat == CFGSTAT_CLEAN)
+                       goto up_out;
+               if ((ret = dsp_uncfg()) < 0)
+                       goto up_out;
+               break;
 
-void dsp_runlevel(unsigned char level)
-{
-       if (level == OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY)
-               dsp_mbsend_recovery(MBCMD(RUNLEVEL), level, 0);
-       else
-               dsp_mbsend(MBCMD(RUNLEVEL), level, 0);
-}
+       case CFGSTAT_READY:
+               if (cfgstat != CFGSTAT_CLEAN) {
+                       printk(KERN_ERR "omapdsp: DSP is ready already!\n");
+                       ret = -EINVAL;
+                       goto up_out;
+               }
 
-static enum cfgstat cfgstat_save_suspend;
+               ret = dsp_cfg();
+               if (ret > 0) {  /* failed, but state is clear. */
+                       ret = -EINVAL;
+                       goto up_out;
+               } else if (ret < 0) {   /* failed, need cleanup. */
+                       st_req = CFGSTAT_CLEAN;
+                       ret_override = ret;
+                       goto again;
+               }
+               break;
+       
+       /*
+        * suspend / resume
+        * DSP is not reset within this code, but done in omap_pm_suspend.
+        * so if these functions are called from sysfs,
+        * DSP should be reset / unreset out of these functions.
+        */
+       case CFGSTAT_SUSPEND:
+               switch (cfgstat) {
+
+               case CFGSTAT_CLEAN:
+                       if (dsp_cpustat_get_stat() == CPUSTAT_RUN) {
+                               printk(KERN_WARNING
+                                      "omapdsp: illegal operation -- trying "
+                                      "suspend DSP while it is running but "
+                                      "not configured.\n"
+                                      "  Resetting DSP.\n");
+                               dsp_cpustat_request(CPUSTAT_RESET);
+                               ret = -EINVAL;
+                       }
+                       goto up_out;
 
-/*
- * suspend / resume callbacks
- * DSP is not reset within this code, but done in omap_pm_suspend.
- * so if these functions are called as OMAP_DSP_IOCTL_SUSPEND,
- * DSP should be reset / unreset out of these functions.
- */
-int dsp_suspend(void)
-{
-       struct mbcmd mb;
-       int ret = 0;
+               case CFGSTAT_READY:
+                       if ((ret = dsp_suspend()) < 0)
+                               goto up_out;
+                       break;
 
-       if (cfgstat == CFG_SUSPEND) {
-               printk(KERN_ERR "omapdsp: DSP is already in suspend state.\n");
-               return -EINVAL;
-       }
+               case CFGSTAT_SUSPEND:
+                       goto up_out;
 
-       if (mutex_lock_interruptible(&ioctl_lock))
-               return -ERESTARTSYS;
+               default:
+                       BUG();
 
-       cfgstat_save_suspend = cfgstat;
-       if (!dsp_is_ready()) {
-               if (dsp_cpustat_get_stat() == CPUSTAT_RUN) {
-                       printk(KERN_WARNING
-                              "omapdsp: illegal operation: trying suspend DSP "
-                              "while it is running but has not configured "
-                              "yet.\n"
-                              "  Resetting DSP...\n");
                }
-               goto transition;
-       }
 
-       ioctl_wait_cmd = MBCMD(SUSPEND);
-       mbcmd_set(mb, MBCMD(SUSPEND), 0, 0);
-       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+               break;
+       
+       case CFGSTAT_RESUME:
+               if (cfgstat != CFGSTAT_SUSPEND) {
+                       printk(KERN_WARNING
+                              "omapdsp: DSP resume request, but DSP is not in "
+                              "suspend state.\n");
+                       ret = -EINVAL;
+                       goto up_out;
+               }
+               st_req = CFGSTAT_READY;
+               break;
+       
+       default:
+               BUG();
 
-       if (ioctl_wait_cmd != 0) {
-               printk(KERN_ERR "omapdsp: DSP suspend error!\n");
-               ret = -EINVAL;
-               goto up_out;
        }
 
-       udelay(100);
-transition:
-       cfgstat = CFG_SUSPEND;
+       cfgstat = st_req;
 up_out:
-       mutex_unlock(&ioctl_lock);
+       mutex_unlock(&cfgstat_lock);
+       return ret_override ? ret_override : ret;
+}
+
+enum cfgstat_e dsp_cfgstat_get_stat(void)
+{
+       return cfgstat;
+}
+
+/*
+ * polls all tasks
+ */
+static int dsp_poll(void)
+{
+       int ret;
+
+       ret = misc_mbcompose_send_and_wait(POLL, 0, 0, NULL);
+       if ((ret < 0) && (ret != -EINTR))
+               printk(KERN_ERR "omapdsp: poll error!\n");
+
        return ret;
 }
 
-int dsp_resume(void)
+int dsp_set_runlevel(u8 level)
 {
-       if (cfgstat != CFG_SUSPEND) {
-               printk(KERN_ERR "omapdsp: DSP is not in suspend state.\n");
-               return -EINVAL;
+       if (level == RUNLEVEL_RECOVERY) {
+               if (mbcompose_send_recovery(RUNLEVEL, level, 0) < 0)
+                       return -EINVAL;
+       } else {
+               if ((level < RUNLEVEL_USER) ||
+                   (level > RUNLEVEL_SUPER))
+                       return -EINVAL;
+               if (mbcompose_send(RUNLEVEL, level, 0) < 0)
+                       return -EINVAL;
        }
 
-       cfgstat = cfgstat_save_suspend;
        return 0;
 }
 
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
 static void dsp_fbctl_enable(void)
 {
-       dsp_mbsend(MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_FBCTL,
-                  OMAP_DSP_MBCMD_FBCTL_ENABLE);
+       mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_ENABLE);
 }
 
 static int dsp_fbctl_disable(void)
 {
+       int ret;
+
+       ret = misc_mbcompose_send_and_wait(KFUNC, KFUNC_FBCTL, FBCTL_DISABLE,
+                                          NULL);
+       if ((ret < 0) && (ret != -EINTR))
+               printk(KERN_ERR "omapdsp: fb disable error!\n");
+
+       return 0;
+}
+
+static int dsp_fbstat_request(enum fbstat_e st)
+{
+       static DEFINE_MUTEX(fbstat_lock);
        int ret = 0;
-       struct mbcmd mb;
 
-       if (mutex_lock_interruptible(&ioctl_lock))
-               return -ERESTARTSYS;
+       if (mutex_lock_interruptible(&fbstat_lock))
+               return -EINTR;
 
-       ioctl_wait_cmd = MBCMD(KFUNC);
-       mbcmd_set(mb, MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_FBCTL,
-                 OMAP_DSP_MBCMD_FBCTL_DISABLE);
-       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
-       if (ioctl_wait_cmd != 0) {
-               printk(KERN_ERR "omapdsp: fb disable error!\n");
-               ret = -EINVAL;
+       if (st == fbstat)
+               goto up_out;
+
+       switch (st) {
+       case FBSTAT_ENABLED:
+               dsp_fbctl_enable();
+               break;
+       case FBSTAT_DISABLED:
+               if ((ret = dsp_fbctl_disable()) < 0)
+                       goto up_out;
+               break;
+       default:
+               BUG();
        }
-       mutex_unlock(&ioctl_lock);
 
-       return ret;
+       fbstat = st;
+up_out:
+       mutex_unlock(&fbstat_lock);
+       return 0;
 }
+#endif /* CONFIG_OMAP_DSP_FBEXPORT */
 
 /*
  * DSP control device file operations
@@ -385,55 +510,60 @@ static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
        /*
         * command level 1: commands which don't need lock
         */
-       case OMAP_DSP_IOCTL_RUN:
+       case DSPCTL_IOCTL_RUN:
                dsp_cpustat_request(CPUSTAT_RUN);
                break;
 
-       case OMAP_DSP_IOCTL_RESET:
+       case DSPCTL_IOCTL_RESET:
                dsp_cpustat_request(CPUSTAT_RESET);
                break;
 
-       case OMAP_DSP_IOCTL_SETRSTVECT:
-               ret = dsp_set_rstvect((unsigned long)arg);
+       case DSPCTL_IOCTL_SETRSTVECT:
+               ret = dsp_set_rstvect((dsp_long_t)arg);
                break;
 
-       case OMAP_DSP_IOCTL_CPU_IDLE:
+#ifdef CONFIG_ARCH_OMAP1
+       case DSPCTL_IOCTL_CPU_IDLE:
                dsp_cpustat_request(CPUSTAT_CPU_IDLE);
                break;
 
-       case OMAP_DSP_IOCTL_GBL_IDLE:
+       case DSPCTL_IOCTL_GBL_IDLE:
                dsp_cpustat_request(CPUSTAT_GBL_IDLE);
                break;
 
-       case OMAP_DSP_IOCTL_MPUI_WORDSWAP_ON:
+       case DSPCTL_IOCTL_MPUI_WORDSWAP_ON:
                mpui_wordswap_on();
                break;
 
-       case OMAP_DSP_IOCTL_MPUI_WORDSWAP_OFF:
+       case DSPCTL_IOCTL_MPUI_WORDSWAP_OFF:
                mpui_wordswap_off();
                break;
 
-       case OMAP_DSP_IOCTL_MPUI_BYTESWAP_ON:
+       case DSPCTL_IOCTL_MPUI_BYTESWAP_ON:
                mpui_byteswap_on();
                break;
 
-       case OMAP_DSP_IOCTL_MPUI_BYTESWAP_OFF:
+       case DSPCTL_IOCTL_MPUI_BYTESWAP_OFF:
                mpui_byteswap_off();
                break;
+#endif /* CONFIG_ARCH_OMAP1 */
+
+       case DSPCTL_IOCTL_TASKCNT:
+               ret = dsp_task_count();
+               break;
 
-       case OMAP_DSP_IOCTL_MBSEND:
+       case DSPCTL_IOCTL_MBSEND:
                {
                        struct omap_dsp_mailbox_cmd u_cmd;
-                       struct mbcmd_hw mb;
+                       mbx_msg_t msg;
                        if (copy_from_user(&u_cmd, (void *)arg, sizeof(u_cmd)))
                                return -EFAULT;
-                       mb.cmd  = u_cmd.cmd;
-                       mb.data = u_cmd.data;
-                       ret = dsp_mbcmd_send((struct mbcmd *)&mb);
+                       msg = (u_cmd.cmd << 16) | u_cmd.data;
+                       ret = dsp_mbcmd_send((struct mbcmd *)&msg);
                        break;
                }
 
-       case OMAP_DSP_IOCTL_SETVAR:
+       case DSPCTL_IOCTL_SETVAR:
                {
                        struct omap_dsp_varinfo var;
                        if (copy_from_user(&var, (void *)arg, sizeof(var)))
@@ -442,126 +572,119 @@ static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
                        break;
                }
 
-       case OMAP_DSP_IOCTL_RUNLEVEL:
-               dsp_runlevel(arg);
+       case DSPCTL_IOCTL_RUNLEVEL:
+               ret = dsp_set_runlevel(arg);
                break;
 
-       case OMAP_DSP_IOCTL_FBEN:
-               dsp_fbctl_enable();
-               return 0;
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+       case DSPCTL_IOCTL_FBEN:
+               ret = dsp_fbstat_request(FBSTAT_ENABLED);
+               break;
+#endif
 
        /*
         * command level 2: commands which need lock
         */
-       case OMAP_DSP_IOCTL_DSPCFG:
-               ret = dspcfg();
+       case DSPCTL_IOCTL_DSPCFG:
+               ret = dsp_cfgstat_request(CFGSTAT_READY);
                break;
 
-       case OMAP_DSP_IOCTL_DSPUNCFG:
-               ret = dspuncfg();
+       case DSPCTL_IOCTL_DSPUNCFG:
+               ret = dsp_cfgstat_request(CFGSTAT_CLEAN);
                break;
 
-       case OMAP_DSP_IOCTL_TASKCNT:
-               ret = dsp_task_count();
-               break;
-
-       case OMAP_DSP_IOCTL_POLL:
+       case DSPCTL_IOCTL_POLL:
                ret = dsp_poll();
                break;
 
-       case OMAP_DSP_IOCTL_FBDIS:
-               ret = dsp_fbctl_disable();
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+       case DSPCTL_IOCTL_FBDIS:
+               ret = dsp_fbstat_request(FBSTAT_DISABLED);
                break;
+#endif
 
-       /*
-        * FIXME: cpu status control for suspend - resume
-        */
-       case OMAP_DSP_IOCTL_SUSPEND:
-               if ((ret = dsp_suspend()) < 0)
+       case DSPCTL_IOCTL_SUSPEND:
+               if ((ret = dsp_cfgstat_request(CFGSTAT_SUSPEND)) < 0)
                        break;
                dsp_cpustat_request(CPUSTAT_RESET);
                break;
 
-       case OMAP_DSP_IOCTL_RESUME:
-               if ((ret = dsp_resume()) < 0)
+       case DSPCTL_IOCTL_RESUME:
+               if ((ret = dsp_cfgstat_request(CFGSTAT_RESUME)) < 0)
                        break;
                dsp_cpustat_request(CPUSTAT_RUN);
                break;
 
-       case OMAP_DSP_IOCTL_REGMEMR:
+       case DSPCTL_IOCTL_REGMEMR:
                {
                        struct omap_dsp_reginfo *u_reg = (void *)arg;
-                       unsigned short adr, val;
+                       u16 adr, val;
 
-                       if (copy_from_user(&adr, &u_reg->adr, sizeof(short)))
+                       if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
                                return -EFAULT;
-                       if ((ret = dsp_regread(OMAP_DSP_MBCMD_REGRW_MEMR,
-                                              adr, &val)) < 0)
+                       if ((ret = dsp_regread(SPACE_MEM, adr, &val)) < 0)
                                return ret;
-                       if (copy_to_user(&u_reg->val, &val, sizeof(short)))
+                       if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
                                return -EFAULT;
                        break;
                }
 
-       case OMAP_DSP_IOCTL_REGMEMW:
+       case DSPCTL_IOCTL_REGMEMW:
                {
                        struct omap_dsp_reginfo reg;
 
                        if (copy_from_user(&reg, (void *)arg, sizeof(reg)))
                                return -EFAULT;
-                       ret = dsp_regwrite(OMAP_DSP_MBCMD_REGRW_MEMW,
-                                          reg.adr, reg.val);
+                       ret = dsp_regwrite(SPACE_MEM, reg.adr, reg.val);
                        break;
                }
 
-       case OMAP_DSP_IOCTL_REGIOR:
+       case DSPCTL_IOCTL_REGIOR:
                {
                        struct omap_dsp_reginfo *u_reg = (void *)arg;
-                       unsigned short adr, val;
+                       u16 adr, val;
 
-                       if (copy_from_user(&adr, &u_reg->adr, sizeof(short)))
+                       if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
                                return -EFAULT;
-                       if ((ret = dsp_regread(OMAP_DSP_MBCMD_REGRW_IOR,
-                                              adr, &val)) < 0)
+                       if ((ret = dsp_regread(SPACE_IO, adr, &val)) < 0)
                                return ret;
-                       if (copy_to_user(&u_reg->val, &val, sizeof(short)))
+                       if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
                                return -EFAULT;
                        break;
                }
 
-       case OMAP_DSP_IOCTL_REGIOW:
+       case DSPCTL_IOCTL_REGIOW:
                {
                        struct omap_dsp_reginfo reg;
 
                        if (copy_from_user(&reg, (void *)arg, sizeof(reg)))
                                return -EFAULT;
-                       ret = dsp_regwrite(OMAP_DSP_MBCMD_REGRW_IOW,
-                                          reg.adr, reg.val);
+                       ret = dsp_regwrite(SPACE_IO, reg.adr, reg.val);
                        break;
                }
 
-       case OMAP_DSP_IOCTL_GETVAR:
+       case DSPCTL_IOCTL_GETVAR:
                {
                        struct omap_dsp_varinfo *u_var = (void *)arg;
-                       unsigned char varid;
-                       unsigned short val[5]; /* maximum */
+                       u8 varid;
+                       u16 val[5]; /* maximum */
                        int argc;
 
-                       if (copy_from_user(&varid, &u_var->varid, sizeof(char)))
+                       if (copy_from_user(&varid, &u_var->varid, sizeof(u8)))
                                return -EFAULT;
                        switch (varid) {
-                       case OMAP_DSP_MBCMD_VARID_ICRMASK:
+                       case VARID_ICRMASK:
                                argc = 1;
                                break;
-                       case OMAP_DSP_MBCMD_VARID_LOADINFO:
+                       case VARID_LOADINFO:
                                argc = 5;
                                break;
                        default:
                                return -EINVAL;
                        }
-                       if ((ret = dsp_getvar(varid, val, argc)) < 0)
+                       if ((ret = dsp_getvar(varid, val)) < 0)
                                return ret;
-                       if (copy_to_user(&u_var->val, val, sizeof(short) * argc))
+                       if (copy_to_user(&u_var->val, val, sizeof(u16) * argc))
                                return -EFAULT;
                        break;
                }
@@ -574,40 +697,31 @@ static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
 }
 
 /*
- * functions called from mailbox1 interrupt routine
+ * functions called from mailbox interrupt routine
  */
-void mbx1_suspend(struct mbcmd *mb)
+void mbx_suspend(struct mbcmd *mb)
+{
+       misc_mbcmd_response(mb, 0, 0);
+}
+
+void mbx_dspcfg(struct mbcmd *mb)
 {
-       if (!waitqueue_active(&ioctl_wait_q) ||
-           (ioctl_wait_cmd != MBCMD(SUSPEND))) {
+       u8 last   = mb->cmd_l & 0x80;
+       u8 cfgcmd = mb->cmd_l & 0x7f;
+       static dsp_long_t tmp_ipb_adr;
+
+       if (!waitqueue_active(&misc_mb_wait.wait_q) ||
+           (misc_mb_wait.cmd_h != MBX_CMD_DSP_DSPCFG)) {
                printk(KERN_WARNING
-                      "mbx: SUSPEND command received, "
+                      "mbx: DSPCFG command received, "
                       "but nobody is waiting for it...\n");
                return;
        }
 
-       ioctl_wait_cmd = 0;
-       wake_up_interruptible(&ioctl_wait_q);
-}
-
-void mbx1_dspcfg(struct mbcmd *mb)
-{
-       unsigned char last   = mb->cmd_l & 0x80;
-       unsigned char cfgcmd = mb->cmd_l & 0x7f;
-       static unsigned long tmp_ipb_adr;
-
        /* mailbox protocol check */
-       if (cfgcmd == OMAP_DSP_MBCMD_DSPCFG_PROTREV) {
-               if (!waitqueue_active(&ioctl_wait_q) ||
-                   (ioctl_wait_cmd != MBCMD(DSPCFG))) {
-                       printk(KERN_WARNING
-                              "mbx: DSPCFG command received, "
-                              "but nobody is waiting for it...\n");
-                       return;
-               }
-
+       if (cfgcmd == DSPCFG_PROTREV) {
                mbx_revision = mb->data;
-               if (mbx_revision == OMAP_DSP_MBPROT_REVISION)
+               if (mbx_revision == MBPROT_REVISION)
                        return;
 #ifdef OLD_BINARY_SUPPORT
                else if ((mbx_revision == MBREV_3_0) ||
@@ -622,7 +736,7 @@ void mbx1_dspcfg(struct mbcmd *mb)
                        printk(KERN_ERR
                               "mbx: protocol revision check error!\n"
                               "  expected=0x%04x, received=0x%04x\n",
-                              OMAP_DSP_MBPROT_REVISION, mb->data);
+                              MBPROT_REVISION, mb->data);
                        mbx_revision = -1;
                        goto abort1;
                }
@@ -639,24 +753,16 @@ void mbx1_dspcfg(struct mbcmd *mb)
                return;
        }
 
-       if (!waitqueue_active(&ioctl_wait_q) ||
-           (ioctl_wait_cmd != MBCMD(DSPCFG))) {
-               printk(KERN_WARNING
-                      "mbx: DSPCFG command received, "
-                      "but nobody is waiting for it...\n");
-               return;
-       }
-
        switch (cfgcmd) {
-       case OMAP_DSP_MBCMD_DSPCFG_SYSADRH:
-               tmp_ipb_adr = (unsigned long)mb->data << 16;
+       case DSPCFG_SYSADRH:
+               tmp_ipb_adr = (u32)mb->data << 16;
                break;
 
-       case OMAP_DSP_MBCMD_DSPCFG_SYSADRL:
+       case DSPCFG_SYSADRL:
                tmp_ipb_adr |= mb->data;
                break;
 
-       case OMAP_DSP_MBCMD_DSPCFG_ABORT:
+       case DSPCFG_ABORT:
                goto abort1;
 
        default:
@@ -668,21 +774,26 @@ void mbx1_dspcfg(struct mbcmd *mb)
 
        if (last) {
                void *badr;
-               unsigned short bln;
-               unsigned short bsz;
-               volatile unsigned short *buf;
+               u16 bln;
+               u16 bsz;
+               volatile u16 *buf;
                void *ipb_sys_da, *ipb_sys_ad;
-               void *mbseq;
+               void *mbseq;     /* FIXME: 3.4 obsolete */
                short *dbg_buf;
-               unsigned short dbg_buf_sz, dbg_line_sz;
+               u16 dbg_buf_sz, dbg_line_sz;
                struct mem_sync_struct mem_sync, *mem_syncp;
 
                ipb_sys_da = dspword_to_virt(tmp_ipb_adr);
                if (ipbuf_sys_config(ipb_sys_da, DIR_D2A) < 0)
                        goto abort1;
 
-               if (sync_with_dsp(&ipbuf_sys_da->s, OMAP_DSP_TID_ANON, 10) < 0) {
+               if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+                       printk(KERN_ERR "mbx: DSPCFG - ipbuf_sys_da read failed!\n");
+                       goto abort1;
+               }
+               if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
                        printk(KERN_ERR "mbx: DSPCFG - IPBUF sync failed!\n");
+                       dsp_mem_disable(ipbuf_sys_da);
                        goto abort1;
                }
                /*
@@ -690,7 +801,7 @@ void mbx1_dspcfg(struct mbcmd *mb)
                 * we must read with 16bit-access
                 */
 #ifdef OLD_BINARY_SUPPORT
-               if (mbx_revision == OMAP_DSP_MBPROT_REVISION) {
+               if (mbx_revision == MBPROT_REVISION) {
 #endif
                        buf = ipbuf_sys_da->d;
                        n_stask        = buf[0];
@@ -735,11 +846,14 @@ void mbx1_dspcfg(struct mbcmd *mb)
                        dbg_buf_sz  = 0;
                        dbg_line_sz = 0;
                        mem_syncp   = NULL;
-               } else /* should not occur */
+               } else { /* should not occur */
+                       dsp_mem_disable(ipbuf_sys_da);
                        goto abort1;
+               }
 #endif /* OLD_BINARY_SUPPORT */
 
                release_ipbuf_pvt(ipbuf_sys_da);
+               dsp_mem_disable(ipbuf_sys_da);
 
                /*
                 * following configurations need to be done before
@@ -749,56 +863,36 @@ void mbx1_dspcfg(struct mbcmd *mb)
                        goto abort1;
                if (ipbuf_config(bln, bsz, badr) < 0)
                        goto abort1;
-               if (dsp_mb_config(mbseq) < 0)
+               if (dsp_mbx_config(mbseq) < 0)
                        goto abort2;
                if (dsp_dbg_config(dbg_buf, dbg_buf_sz, dbg_line_sz) < 0)
                        goto abort2;
                if (dsp_mem_sync_config(mem_syncp) < 0)
                        goto abort2;
 
-               ioctl_wait_cmd = 0;
-               wake_up_interruptible(&ioctl_wait_q);
+               misc_mb_wait.cmd_h = 0;
+               wake_up_interruptible(&misc_mb_wait.wait_q);
        }
        return;
 
 abort2:
        ipbuf_stop();
 abort1:
-       wake_up_interruptible(&ioctl_wait_q);
+       wake_up_interruptible(&misc_mb_wait.wait_q);
        return;
 }
 
-void mbx1_poll(struct mbcmd *mb)
+void mbx_poll(struct mbcmd *mb)
 {
-       if (!waitqueue_active(&ioctl_wait_q) ||
-           (ioctl_wait_cmd != MBCMD(POLL))) {
-               printk(KERN_WARNING
-                      "mbx: POLL command received, "
-                      "but nobody is waiting for it...\n");
-               return;
-       }
-
-       ioctl_wait_cmd = 0;
-       wake_up_interruptible(&ioctl_wait_q);
+       misc_mbcmd_response(mb, 0, 0);
 }
 
-void mbx1_regrw(struct mbcmd *mb)
+void mbx_regrw(struct mbcmd *mb)
 {
-       if (!waitqueue_active(&ioctl_wait_q) ||
-           (ioctl_wait_cmd != MBCMD(REGRW))) {
-               printk(KERN_WARNING
-                      "mbx: REGRW command received, "
-                      "but nobody is waiting for it...\n");
-               return;
-       }
-
        switch (mb->cmd_l) {
-       case OMAP_DSP_MBCMD_REGRW_DATA:
-               ioctl_wait_cmd = 0;
-               varread_val[0] = mb->data;
-               wake_up_interruptible(&ioctl_wait_q);
-               return;
-
+       case REGRW_DATA:
+               misc_mbcmd_response(mb, 1, 0);
+               break;
        default:
                printk(KERN_ERR
                       "mbx: Illegal REGRW command: "
@@ -807,49 +901,38 @@ void mbx1_regrw(struct mbcmd *mb)
        }
 }
 
-void mbx1_getvar(struct mbcmd *mb)
+void mbx_getvar(struct mbcmd *mb)
 {
-       unsigned char varid = mb->cmd_l;
-       int i;
-       volatile unsigned short *buf;
-
-       if (!waitqueue_active(&ioctl_wait_q) ||
-           (ioctl_wait_cmd != MBCMD(GETVAR))) {
-               printk(KERN_WARNING
-                      "mbx: GETVAR command received, "
-                      "but nobody is waiting for it...\n");
-               return;
-       }
-
-       ioctl_wait_cmd = 0;
-       switch (varid) {
-       case OMAP_DSP_MBCMD_VARID_ICRMASK:
-               varread_val[0] = mb->data;
+       switch (mb->cmd_l) {
+       case VARID_ICRMASK:
+               misc_mbcmd_response(mb, 1, 1);
                break;
-       case OMAP_DSP_MBCMD_VARID_LOADINFO:
-               {
-                       if (sync_with_dsp(&ipbuf_sys_da->s, OMAP_DSP_TID_ANON, 10) < 0) {
-                               printk(KERN_ERR
-                                      "mbx: GETVAR - IPBUF sync failed!\n");
-                               return;
-                       }
-                       /* need word access. do not use memcpy. */
-                       buf = ipbuf_sys_da->d;
-                       for (i = 0; i < 5; i++) {
-                               varread_val[i] = buf[i];
-                       }
-                       release_ipbuf_pvt(ipbuf_sys_da);
-                       break;
-               }
+       case VARID_LOADINFO:
+               misc_mbcmd_response(mb, 5, 1);
+               break;
+       default:
+               printk(KERN_ERR
+                      "mbx: Illegal GETVAR command: "
+                      "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
+               return;
        }
-       wake_up_interruptible(&ioctl_wait_q);
+}
 
-       return;
+void mbx_fbctl_disable(struct mbcmd *mb)
+{
+       misc_mbcmd_response(mb, 0, 0);
 }
 
+struct file_operations dsp_ctl_fops = {
+       .owner   = THIS_MODULE,
+       .ioctl   = dsp_ctl_ioctl,
+};
+
 /*
  * sysfs files
  */
+
+/* ifver */
 static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
                          char *buf)
 {
@@ -861,9 +944,9 @@ static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
         * 3.2: sysfs / udev support
         *      KMEM_RESERVE / KMEM_RELEASE ioctls for mem device
         * 3.3: added following ioctls
-        *      OMAP_DSP_IOCTL_GBL_IDLE
-        *      OMAP_DSP_IOCTL_CPU_IDLE (instead of OMAP_DSP_IOCTL_IDLE)
-        *      OMAP_DSP_IOCTL_POLL
+        *      DSPCTL_IOCTL_GBL_IDLE
+        *      DSPCTL_IOCTL_CPU_IDLE (instead of DSPCTL_IOCTL_IDLE)
+        *      DSPCTL_IOCTL_POLL
         */
 
        /*
@@ -878,16 +961,23 @@ static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
        return len;
 }
 
-static struct device_attribute dev_attr_ifver = __ATTR_RO(ifver);
+/* cpustat */
+static char *cpustat_name[CPUSTAT_MAX] = {
+       [CPUSTAT_RESET]    = "reset",
+#ifdef CONFIG_ARCH_OMAP1
+       [CPUSTAT_GBL_IDLE] = "gbl_idle",
+       [CPUSTAT_CPU_IDLE] = "cpu_idle",
+#endif
+       [CPUSTAT_RUN]      = "run",
+};
 
 static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
                            char *buf)
 {
-       return sprintf(buf, "%s\n", cpustat_name(dsp_cpustat_get_stat()));
+       return sprintf(buf, "%s\n", cpustat_name[dsp_cpustat_get_stat()]);
 }
 
-static struct device_attribute dev_attr_cpustat = __ATTR_RO(cpustat);
-
+/* icrmask */
 static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
                            char *buf)
 {
@@ -897,38 +987,43 @@ static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
 static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
                             const char *buf, size_t count)
 {
-       unsigned short mask;
+       u16 mask;
        int ret;
 
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
        mask = simple_strtol(buf, NULL, 16);
        dsp_cpustat_set_icrmask(mask);
 
-       if (dsp_is_ready()) {
-               ret = dsp_setvar(OMAP_DSP_MBCMD_VARID_ICRMASK, mask);
+       if (dsp_cfgstat_get_stat() == CFGSTAT_READY) {
+               ret = dsp_setvar(VARID_ICRMASK, mask);
                if (ret < 0)
                        return ret;
        }
 
-       return strlen(buf);
+       return count;
 }
 
-static struct device_attribute dev_attr_icrmask = 
-       __ATTR(icrmask, S_IWUSR | S_IRUGO, icrmask_show, icrmask_store);
-
+/* loadinfo */
 static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
        int len;
        int ret;
-       static unsigned short val[5];
+       u16 val[5];
 
-       if ((ret = dsp_getvar(OMAP_DSP_MBCMD_VARID_LOADINFO, val, 5)) < 0)
+       if ((ret = dsp_getvar(VARID_LOADINFO, val)) < 0)
                return ret;
 
-       /* load info value range is 0(free) - 10000(busy) */
+       /*
+        * load info value range is 0(free) - 10000(busy):
+        * if CPU load is not measured on DSP, it sets 0xffff at val[0].
+        */
+
+       if (val[0] == 0xffff) {
+               len = sprintf(buf,
+                             "currently DSP load info is not available.\n");
+               goto out;
+       }
+
        len = sprintf(buf,
                      "DSP load info:\n"
                      "  10ms average = %3d.%02d%%\n"
@@ -937,72 +1032,15 @@ static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
                      val[0]/100, val[0]%100,
                      val[1]/100, val[1]%100, val[2]/100, val[2]%100,
                      val[3]/100, val[3]%100, val[4]/100, val[4]%100);
+out:
        return len;
 }
 
-/*
- * This is declared at the top of this file.
- *
- * static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
- */
-
-void mbx1_fbctl_disable(void)
-{
-       if (!waitqueue_active(&ioctl_wait_q) ||
-           (ioctl_wait_cmd != MBCMD(KFUNC))) {
-               printk(KERN_WARNING
-                      "mbx: KFUNC:FBCTL command received, "
-                      "but nobody is waiting for it...\n");
-               return;
-       }
-       ioctl_wait_cmd = 0;
-       wake_up_interruptible(&ioctl_wait_q);
-}
-
-#ifdef CONFIG_PROC_FS
-/* for backward compatibility */
-static int version_read_proc(char *page, char **start, off_t off, int count,
-                            int *eof, void *data)
-{
-       /*
-        * This entry is read by 3.1 tools only, so leave it as is.
-        * 3.2 and later will read from sysfs file.
-        */
-       return sprintf(page, "3.1\n");
-}
-
-static void __init dsp_ctl_create_proc(void)
-{
-       struct proc_dir_entry *ent;
-
-       /* version */
-       ent = create_proc_read_entry("version", 0, procdir_dsp,
-                                    version_read_proc, NULL);
-       if (ent == NULL) {
-               printk(KERN_ERR
-                      "omapdsp: failed to register proc device: version\n");
-       }
-}
-
-static void dsp_ctl_remove_proc(void)
-{
-       remove_proc_entry("version", procdir_dsp);
-}
-#endif /* CONFIG_PROC_FS */
-
-struct file_operations dsp_ctl_fops = {
-       .owner   = THIS_MODULE,
-       .ioctl   = dsp_ctl_ioctl,
-};
-
 void __init dsp_ctl_init(void)
 {
        device_create_file(&dsp_device.dev, &dev_attr_ifver);
        device_create_file(&dsp_device.dev, &dev_attr_cpustat);
        device_create_file(&dsp_device.dev, &dev_attr_icrmask);
-#ifdef CONFIG_PROC_FS
-       dsp_ctl_create_proc();
-#endif
 }
 
 void dsp_ctl_exit(void)
@@ -1010,7 +1048,4 @@ void dsp_ctl_exit(void)
        device_remove_file(&dsp_device.dev, &dev_attr_ifver);
        device_remove_file(&dsp_device.dev, &dev_attr_cpustat);
        device_remove_file(&dsp_device.dev, &dev_attr_icrmask);
-#ifdef CONFIG_PROC_FS
-       dsp_ctl_remove_proc();
-#endif
 }
index 8207441096b282725cf1dda5a9fce5cb732b1f0f..1d0168d51653341c948efb1a97544df842a26cb8 100644 (file)
@@ -1,36 +1,31 @@
 /*
- * linux/arch/arm/mach-omap/dsp/dsp_ctl_core.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * OMAP DSP control devices core driver
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2004,2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/07/26:  DSP Gateway version 3.3
  */
 
-#include <linux/module.h>
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/device.h>
 #include <linux/init.h>
-#include <asm/arch/dsp.h>
-#include "hardware_dsp.h"
+#include "dsp.h"
 
 #define CTL_MINOR      0
 #define MEM_MINOR      1
@@ -86,7 +81,6 @@ int __init dsp_ctl_core_init(void)
 {
        int retval;
        int i;
-       struct class_device *cdev;
 
        retval = register_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl",
                                 &dsp_ctl_core_fops);
@@ -99,7 +93,7 @@ int __init dsp_ctl_core_init(void)
 
        dsp_ctl_class = class_create(THIS_MODULE, "dspctl");
        for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
-               cdev = class_device_create(dsp_ctl_class, NULL,
+               class_device_create(dsp_ctl_class, NULL,
                                    MKDEV(OMAP_DSP_CTL_MAJOR,
                                          dev_list[i].minor),
                                    NULL, dev_list[i].devname);
diff --git a/arch/arm/plat-omap/dsp/dsp_mbcmd.h b/arch/arm/plat-omap/dsp/dsp_mbcmd.h
new file mode 100644 (file)
index 0000000..50cf778
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/*
+ * DSP mailbox protocol definitions
+ */
+#define MBPROT_REVISION        0x0019
+
+#define TCTL_TINIT             0x0000
+#define TCTL_TEN               0x0001
+#define TCTL_TDIS              0x0002
+#define TCTL_TCLR              0x0003
+#define TCTL_TCLR_FORCE                0x0004
+
+#define RUNLEVEL_USER          0x01
+#define RUNLEVEL_SUPER         0x0e
+#define RUNLEVEL_RECOVERY      0x10
+
+#define PM_DISABLE             0x00
+#define PM_ENABLE              0x01
+
+#define KFUNC_FBCTL            0x00
+#define KFUNC_AUDIO_PWR                0x01
+
+#define FBCTL_UPD              0x0000
+#define FBCTL_ENABLE           0x0002
+#define FBCTL_DISABLE          0x0003
+
+#define AUDIO_PWR_UP           0x0000
+#define AUDIO_PWR_DOWN1                0x0001
+#define AUDIO_PWR_DOWN2                0x0002
+
+#define TDEL_SAFE              0x0000
+#define TDEL_KILL              0x0001
+
+#define DSPCFG_REQ             0x00
+#define DSPCFG_SYSADRH         0x28
+#define DSPCFG_SYSADRL         0x29
+#define DSPCFG_PROTREV         0x70
+#define DSPCFG_ABORT           0x78
+#define DSPCFG_LAST            0x80
+
+#define REGRW_MEMR             0x00
+#define REGRW_MEMW             0x01
+#define REGRW_IOR              0x02
+#define REGRW_IOW              0x03
+#define REGRW_DATA             0x04
+
+#define VARID_ICRMASK          0x00
+#define VARID_LOADINFO         0x01
+
+#define TTYP_ARCV              0x0001
+#define TTYP_ASND              0x0002
+#define TTYP_BKMD              0x0004
+#define TTYP_BKDM              0x0008
+#define TTYP_PVMD              0x0010
+#define TTYP_PVDM              0x0020
+
+#define EID_BADTID             0x10
+#define EID_BADTCN             0x11
+#define EID_BADBID             0x20
+#define EID_BADCNT             0x21
+#define EID_NOTLOCKED          0x22
+#define EID_STVBUF             0x23
+#define EID_BADADR             0x24
+#define EID_BADTCTL            0x30
+#define EID_BADPARAM           0x50
+#define EID_FATAL              0x58
+#define EID_NOMEM              0xc0
+#define EID_NORES              0xc1
+#define EID_IPBFULL            0xc2
+#define EID_WDT                        0xd0
+#define EID_TASKNOTRDY         0xe0
+#define EID_TASKBSY            0xe1
+#define EID_TASKERR            0xef
+#define EID_BADCFGTYP          0xf0
+#define EID_DEBUG              0xf8
+#define EID_BADSEQ             0xfe
+#define EID_BADCMD             0xff
+
+#define TNM_LEN                        16
+
+#define TID_FREE               0xff
+#define TID_ANON               0xfe
+
+#define BID_NULL               0xffff
+#define BID_PVT                        0xfffe
index 6d2c8110a67d036dae5979c5322b8dc3be85c2ae..49f633c538a413cf65eafbe06352ae0beb2d7cae 100644 (file)
@@ -1,38 +1,32 @@
 /*
- * linux/arch/arm/mach-omap/dsp/dsp_mem.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * OMAP DSP memory driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
- *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
  * Conversion to mempool API and ARM MMU section mapping
  * by Paul Mundt <paul.mundt@nokia.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- * 2005/06/09:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/major.h>
 #include <linux/fs.h>
-#include <linux/bootmem.h>
 #include <linux/fb.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/ioctls.h>
 #include <asm/irq.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/arch/tc.h>
 #include <asm/arch/omapfb.h>
-#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
 #include <asm/arch/dsp_common.h>
 #include "uaccess_dsp.h"
-#include "ipbuf.h"
+#include "dsp_mbcmd.h"
+#include "../mailbox_hw.h"
 #include "dsp.h"
+#include "ioctl.h"
+
+#ifdef CONFIG_ARCH_OMAP2
+#define IOMAP_VAL      0x3f
+#endif
 
-#define SZ_1MB 0x100000
-#define SZ_64KB        0x10000
-#define SZ_4KB 0x1000
 #define SZ_1KB 0x400
+#define SZ_4KB 0x1000
+#define SZ_64KB        0x10000
+#define SZ_1MB 0x100000
+#define SZ_16MB        0x1000000
 #define is_aligned(adr,align)  (!((adr)&((align)-1)))
-#define ORDER_1MB      (20 - PAGE_SHIFT)
-#define ORDER_64KB     (16 - PAGE_SHIFT)
 #define ORDER_4KB      (12 - PAGE_SHIFT)
+#define ORDER_64KB     (16 - PAGE_SHIFT)
+#define ORDER_1MB      (20 - PAGE_SHIFT)
+
+/*
+ * absorb DSP MMU register size and location difference
+ */
+#if defined(CONFIG_ARCH_OMAP1)
+typedef u16 dsp_mmu_reg_t;
+#define dsp_mmu_read_reg(a)    omap_readw(a)
+#define dsp_mmu_write_reg(v,a) omap_writew(v,a)
+#elif defined(CONFIG_ARCH_OMAP2)
+typedef u32 dsp_mmu_reg_t;
+#define dsp_mmu_read_reg(a)    readl(a)
+#define dsp_mmu_write_reg(v,a) writel(v,a)
+#define dsp_ipi_read_reg(a)    readl(a)
+#define dsp_ipi_write_reg(v,a) writel(v,a)
+#endif
 
-#define PGDIR_MASK             (~(PGDIR_SIZE-1))
-#define PGDIR_ALIGN(addr)      (((addr)+PGDIR_SIZE-1)&(PGDIR_MASK))
+#if defined(CONFIG_ARCH_OMAP1)
 
 #define dsp_mmu_enable() \
        do { \
-               omap_writew(DSPMMU_CNTL_MMU_EN | DSPMMU_CNTL_RESET_SW, \
-                           DSPMMU_CNTL); \
+               dsp_mmu_write_reg(DSP_MMU_CNTL_MMU_EN | DSP_MMU_CNTL_RESET_SW, \
+                                 DSP_MMU_CNTL); \
        } while(0)
 #define dsp_mmu_disable() \
-       do { omap_writew(0, DSPMMU_CNTL); } while(0)
+       do { \
+               dsp_mmu_write_reg(0, DSP_MMU_CNTL); \
+       } while(0)
+#define __dsp_mmu_itack() \
+       do { \
+               dsp_mmu_write_reg(DSP_MMU_IT_ACK_IT_ACK, DSP_MMU_IT_ACK); \
+       } while(0)
+
+#elif defined(CONFIG_ARCH_OMAP2)
+
+#define dsp_mmu_enable() \
+       do { \
+               dsp_mmu_write_reg(DSP_MMU_CNTL_MMUENABLE, DSP_MMU_CNTL); \
+       } while(0)
+#define dsp_mmu_disable() \
+       do { \
+               dsp_mmu_write_reg(0, DSP_MMU_CNTL); \
+       } while(0)
+#define dsp_mmu_reset() \
+       do { \
+               dsp_mmu_write_reg(dsp_mmu_read_reg(DSP_MMU_SYSCONFIG) | \
+                                 DSP_MMU_SYSCONFIG_SOFTRESET, \
+                                 DSP_MMU_SYSCONFIG); \
+       } while(0)
+
+#endif /* CONFIG_ARCH_OMAP2 */
+
 #define dsp_mmu_flush() \
        do { \
-               omap_writew(DSPMMU_FLUSH_ENTRY_FLUSH_ENTRY, \
-                           DSPMMU_FLUSH_ENTRY); \
+               dsp_mmu_write_reg(DSP_MMU_FLUSH_ENTRY_FLUSH_ENTRY, \
+                                 DSP_MMU_FLUSH_ENTRY); \
        } while(0)
 #define __dsp_mmu_gflush() \
-       do { omap_writew(DSPMMU_GFLUSH_GFLUSH, DSPMMU_GFLUSH); } while(0)
-#define __dsp_mmu_itack() \
-       do { omap_writew(DSPMMU_IT_ACK_IT_ACK, DSPMMU_IT_ACK); } while(0)
+       do { \
+               dsp_mmu_write_reg(DSP_MMU_GFLUSH_GFLUSH, DSP_MMU_GFLUSH); \
+       } while(0)
 
+/*
+ * absorb register name difference
+ */
+#ifdef CONFIG_ARCH_OMAP1
+#define DSP_MMU_CAM_P                  DSP_MMU_CAM_L_P
+#define DSP_MMU_CAM_V                  DSP_MMU_CAM_L_V
+#define DSP_MMU_CAM_PAGESIZE_MASK      DSP_MMU_CAM_L_PAGESIZE_MASK
+#define DSP_MMU_CAM_PAGESIZE_1MB       DSP_MMU_CAM_L_PAGESIZE_1MB
+#define DSP_MMU_CAM_PAGESIZE_64KB      DSP_MMU_CAM_L_PAGESIZE_64KB
+#define DSP_MMU_CAM_PAGESIZE_4KB       DSP_MMU_CAM_L_PAGESIZE_4KB
+#define DSP_MMU_CAM_PAGESIZE_1KB       DSP_MMU_CAM_L_PAGESIZE_1KB
+#endif /* CONFIG_ARCH_OMAP1 */
+
+/*
+ * OMAP1 EMIFF access
+ */
+#ifdef CONFIG_ARCH_OMAP1
 #define EMIF_PRIO_LB_MASK      0x0000f000
 #define EMIF_PRIO_LB_SHIFT     12
 #define EMIF_PRIO_DMA_MASK     0x00000f00
 #define set_emiff_dma_prio(prio) \
        do { \
                omap_writel((omap_readl(OMAP_TC_OCPT1_PRIOR) & \
-       ~EMIF_PRIO_DMA_MASK) | \
+                            ~EMIF_PRIO_DMA_MASK) | \
                            ((prio) << EMIF_PRIO_DMA_SHIFT), \
                            OMAP_TC_OCPT1_PRIOR); \
        } while(0)
+#endif /* CONFIG_ARCH_OMAP1 */
 
-enum exmap_type {
+enum exmap_type_e {
        EXMAP_TYPE_MEM,
        EXMAP_TYPE_FB
 };
 
-struct exmap_tbl {
+struct exmap_tbl_entry {
        unsigned int valid:1;
-       unsigned int cntnu:1;   /* grouping */
+       unsigned int prsvd:1;   /* preserved */
        int usecount;           /* reference count by mmap */
-       enum exmap_type type;
+       enum exmap_type_e type;
        void *buf;              /* virtual address of the buffer,
                                 * i.e. 0xc0000000 - */
        void *vadr;             /* DSP shadow space,
                                 * i.e. 0xe0000000 - 0xe0ffffff */
        unsigned int order;
+       struct {
+               int prev;
+               int next;
+       } link;                 /* grouping */
 };
-#define DSPMMU_TLB_LINES       32
-static struct exmap_tbl exmap_tbl[DSPMMU_TLB_LINES];
+
+#define INIT_EXMAP_TBL_ENTRY(ent,b,v,typ,od) \
+       do {\
+               (ent)->buf       = (b); \
+               (ent)->vadr      = (v); \
+               (ent)->valid     = 1; \
+               (ent)->prsvd     = 0; \
+               (ent)->usecount  = 0; \
+               (ent)->type      = (typ); \
+               (ent)->order     = (od); \
+               (ent)->link.next = -1; \
+               (ent)->link.prev = -1; \
+       } while (0)
+
+#define INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(ent,b,v) \
+       do {\
+               (ent)->buf       = (b); \
+               (ent)->vadr      = (v); \
+               (ent)->valid     = 1; \
+               (ent)->prsvd     = 1; \
+               (ent)->usecount  = 0; \
+               (ent)->type      = EXMAP_TYPE_MEM; \
+               (ent)->order     = 0; \
+               (ent)->link.next = -1; \
+               (ent)->link.prev = -1; \
+       } while (0)
+
+#define DSP_MMU_TLB_LINES      32
+static struct exmap_tbl_entry exmap_tbl[DSP_MMU_TLB_LINES];
+static int exmap_preserved_cnt;
 static DECLARE_RWSEM(exmap_sem);
 
 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
@@ -123,23 +213,123 @@ static struct omapfb_notifier_block *omapfb_nb;
 static int omapfb_ready;
 #endif
 
-static int dsp_exunmap(unsigned long dspadr);
+struct cam_ram_regset {
+#if defined(CONFIG_ARCH_OMAP1)
+       dsp_mmu_reg_t cam_h;
+       dsp_mmu_reg_t cam_l;
+       dsp_mmu_reg_t ram_h;
+       dsp_mmu_reg_t ram_l;
+#elif defined(CONFIG_ARCH_OMAP2)
+       dsp_mmu_reg_t cam;
+       dsp_mmu_reg_t ram;
+#endif
+};
+
+struct tlb_entry {
+       dsp_long_t va;
+       unsigned long pa;
+       dsp_mmu_reg_t pgsz, prsvd, valid;
+#if defined(CONFIG_ARCH_OMAP1)
+       dsp_mmu_reg_t ap;
+#elif defined(CONFIG_ARCH_OMAP2)
+       dsp_mmu_reg_t endian, elsz, mixed;
+#endif
+};
+
+#if defined(CONFIG_ARCH_OMAP1)
+#define INIT_TLB_ENTRY(ent,v,p,ps) \
+       do { \
+               (ent)->va = (v); \
+               (ent)->pa = (p); \
+               (ent)->pgsz = (ps); \
+               (ent)->prsvd = 0; \
+               (ent)->ap = DSP_MMU_RAM_L_AP_FA; \
+       } while (0)
+#define INIT_TLB_ENTRY_4KB_PRESERVED(ent,v,p) \
+       do { \
+               (ent)->va = (v); \
+               (ent)->pa = (p); \
+               (ent)->pgsz = DSP_MMU_CAM_PAGESIZE_4KB; \
+               (ent)->prsvd = DSP_MMU_CAM_P; \
+               (ent)->ap = DSP_MMU_RAM_L_AP_FA; \
+       } while (0)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define INIT_TLB_ENTRY(ent,v,p,ps) \
+       do { \
+               (ent)->va = (v); \
+               (ent)->pa = (p); \
+               (ent)->pgsz = (ps); \
+               (ent)->prsvd = 0; \
+               (ent)->endian = DSP_MMU_RAM_ENDIANNESS_LITTLE; \
+               (ent)->elsz = DSP_MMU_RAM_ELEMENTSIZE_16; \
+               (ent)->mixed = 0; \
+       } while (0)
+#define INIT_TLB_ENTRY_4KB_PRESERVED(ent,v,p) \
+       do { \
+               (ent)->va = (v); \
+               (ent)->pa = (p); \
+               (ent)->pgsz = DSP_MMU_CAM_PAGESIZE_4KB; \
+               (ent)->prsvd = DSP_MMU_CAM_P; \
+               (ent)->endian = DSP_MMU_RAM_ENDIANNESS_LITTLE; \
+               (ent)->elsz = DSP_MMU_RAM_ELEMENTSIZE_16; \
+               (ent)->mixed = 0; \
+       } while (0)
+#define INIT_TLB_ENTRY_4KB_ES32_PRESERVED(ent,v,p) \
+       do { \
+               (ent)->va = (v); \
+               (ent)->pa = (p); \
+               (ent)->pgsz = DSP_MMU_CAM_PAGESIZE_4KB; \
+               (ent)->prsvd = DSP_MMU_CAM_P; \
+               (ent)->endian = DSP_MMU_RAM_ENDIANNESS_LITTLE; \
+               (ent)->elsz = DSP_MMU_RAM_ELEMENTSIZE_32; \
+               (ent)->mixed = 0; \
+       } while (0)
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1)
+#define cam_ram_valid(cr)      ((cr).cam_l & DSP_MMU_CAM_V)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define cam_ram_valid(cr)      ((cr).cam & DSP_MMU_CAM_V)
+#endif
+
+struct tlb_lock {
+       int base;
+       int victim;
+};
+
+static int dsp_exunmap(dsp_long_t dspadr);
 
 static void *dspvect_page;
-static unsigned long dsp_fault_adr;
+static u32 dsp_fault_adr;
 static struct mem_sync_struct mem_sync;
 
-static void *mempool_alloc_from_pool(mempool_t *pool,
-                                    unsigned int __nocast gfp_mask)
+static ssize_t mmu_show(struct device *dev, struct device_attribute *attr,
+                       char *buf);
+static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
+                         char *buf);
+static ssize_t mempool_show(struct device *dev, struct device_attribute *attr,
+                           char *buf);
+
+static struct device_attribute dev_attr_mmu =     __ATTR_RO(mmu);
+static struct device_attribute dev_attr_exmap =   __ATTR_RO(exmap);
+static struct device_attribute dev_attr_mempool = __ATTR_RO(mempool);
+
+/*
+ * special mempool function:
+ * hope this goes to mm/mempool.c
+ */
+static void *mempool_alloc_from_pool(mempool_t *pool, gfp_t gfp_mask)
 {
-       spin_lock_irq(&pool->lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&pool->lock, flags);
        if (likely(pool->curr_nr)) {
                void *element = pool->elements[--pool->curr_nr];
-               spin_unlock_irq(&pool->lock);
+               spin_unlock_irqrestore(&pool->lock, flags);
                return element;
        }
+       spin_unlock_irqrestore(&pool->lock, flags);
 
-       spin_unlock_irq(&pool->lock);
        return mempool_alloc(pool, gfp_mask);
 }
 
@@ -233,6 +423,7 @@ static int dsp_kmem_reserve(unsigned long size)
                       "omapdsp: size(0x%lx) is not multiple of 64KB.\n", size);
                return -EINVAL;
        }
+
        if (size > DSPSPACE_SIZE) {
                printk(KERN_ERR
                       "omapdsp: size(0x%lx) is larger than DSP memory space "
@@ -286,14 +477,12 @@ static void dsp_mem_free_pages(unsigned long buf, unsigned int order)
        for (page = ps; page < pe; page++)
                ClearPageReserved(page);
 
-       if (buf) {
-               if ((order == ORDER_64KB) && likely(kmem_pool_64K))
-                       mempool_free((void *)buf, kmem_pool_64K);
-               else if ((order == ORDER_1MB) && likely(kmem_pool_1M))
-                       mempool_free((void *)buf, kmem_pool_1M);
-               else
-                       free_pages(buf, order);
-       }
+       if ((order == ORDER_64KB) && likely(kmem_pool_64K))
+               mempool_free((void *)buf, kmem_pool_64K);
+       else if ((order == ORDER_1MB) && likely(kmem_pool_1M))
+               mempool_free((void *)buf, kmem_pool_1M);
+       else
+               free_pages(buf, order);
 }
 
 static inline void
@@ -321,6 +510,7 @@ exmap_alloc_pte(unsigned long virt, unsigned long phys, pgprot_t prot)
        set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
 }
 
+#if 0
 static inline int
 exmap_alloc_sect(unsigned long virt, unsigned long phys, int prot)
 {
@@ -344,6 +534,7 @@ exmap_alloc_sect(unsigned long virt, unsigned long phys, int prot)
 
        return 0;
 }
+#endif
 
 /*
  * ARM MMU operations
@@ -400,6 +591,11 @@ static int exmap_set_armmmu(unsigned long virt, unsigned long phys,
        return 0;
 }
 
+       /* XXX: T.Kobayashi
+        * A process can have old mappings. if we want to clear a pmd, 
+        * we need to do it for all proceeses that use the old mapping.
+        */
+#if 0
 static inline void
 exmap_clear_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end)
 {
@@ -457,14 +653,16 @@ exmap_clear_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end)
                exmap_clear_pmd_range(pud, addr, next);
        } while (pud++, addr = next, addr != end);
 }
+#endif
 
 static void exmap_clear_armmmu(unsigned long virt, unsigned long size)
 {
+#if 0
        unsigned long next, end;
        pgd_t *pgd;
 
        printk(KERN_DEBUG
-              "omapdsp: unmapping in ARM MMU, v=0x%08lx, sz=0x%lx\n",
+              "omapdsp: unmapping in ARM MMU, v=%#010lx, sz=%#lx\n",
               virt, size);
 
        pgd = pgd_offset_k(virt);
@@ -476,6 +674,29 @@ static void exmap_clear_armmmu(unsigned long virt, unsigned long size)
 
                exmap_clear_pud_range(pgd, virt, next);
        } while (pgd++, virt = next, virt != end);
+#else
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+
+       printk(KERN_DEBUG
+              "omapdsp: unmapping in ARM MMU, v=%#010lx, sz=%#lx\n",
+              virt, size);
+
+       while (size >= PAGE_SIZE) {
+               pgd = pgd_offset_k(virt);
+               pud = pud_offset(pgd, virt);
+               pmd = pmd_offset(pud, virt);
+               pte = pte_offset_kernel(pmd, virt);
+
+               pte_clear(&init_mm, virt, pte);
+               size -= PAGE_SIZE;
+               virt += PAGE_SIZE;
+       }
+
+       BUG_ON(size);
+#endif
 }
 
 static int exmap_valid(void *vadr, size_t len)
@@ -484,10 +705,10 @@ static int exmap_valid(void *vadr, size_t len)
        int i;
 
 start:
-       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+       for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
                void *mapadr;
                unsigned long mapsize;
-               struct exmap_tbl *ent = &exmap_tbl[i];
+               struct exmap_tbl_entry *ent = &exmap_tbl[i];
 
                if (!ent->valid)
                        continue;
@@ -576,18 +797,17 @@ void exmap_use(void *vadr, size_t len)
        int i;
 
        down_write(&exmap_sem);
-       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+       for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
                void *mapadr;
                unsigned long mapsize;
-               struct exmap_tbl *ent = &exmap_tbl[i];
+               struct exmap_tbl_entry *ent = &exmap_tbl[i];
 
                if (!ent->valid)
                        continue;
                mapadr = (void *)ent->vadr;
                mapsize = 1 << (ent->order + PAGE_SHIFT);
-               if ((vadr + len > mapadr) && (vadr < mapadr + mapsize)) {
+               if ((vadr + len > mapadr) && (vadr < mapadr + mapsize))
                        ent->usecount++;
-               }
        }
        up_write(&exmap_sem);
 }
@@ -597,18 +817,17 @@ void exmap_unuse(void *vadr, size_t len)
        int i;
 
        down_write(&exmap_sem);
-       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+       for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
                void *mapadr;
                unsigned long mapsize;
-               struct exmap_tbl *ent = &exmap_tbl[i];
+               struct exmap_tbl_entry *ent = &exmap_tbl[i];
 
                if (!ent->valid)
                        continue;
                mapadr = (void *)ent->vadr;
                mapsize = 1 << (ent->order + PAGE_SHIFT);
-               if ((vadr + len > mapadr) && (vadr < mapadr + mapsize)) {
+               if ((vadr + len > mapadr) && (vadr < mapadr + mapsize))
                        ent->usecount--;
-               }
        }
        up_write(&exmap_sem);
 }
@@ -628,10 +847,10 @@ unsigned long dsp_virt_to_phys(void *vadr, size_t *len)
        }
 
        /* EXRAM */
-       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+       for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
                void *mapadr;
                unsigned long mapsize;
-               struct exmap_tbl *ent = &exmap_tbl[i];
+               struct exmap_tbl_entry *ent = &exmap_tbl[i];
 
                if (!ent->valid)
                        continue;
@@ -650,151 +869,188 @@ unsigned long dsp_virt_to_phys(void *vadr, size_t *len)
 /*
  * DSP MMU operations
  */
-static __inline__ unsigned short get_cam_l_va_mask(unsigned short slst)
-{
-       switch (slst) {
-       case DSPMMU_CAM_L_SLST_1MB:
-               return DSPMMU_CAM_L_VA_TAG_L1_MASK |
-                      DSPMMU_CAM_L_VA_TAG_L2_MASK_1MB;
-       case DSPMMU_CAM_L_SLST_64KB:
-               return DSPMMU_CAM_L_VA_TAG_L1_MASK |
-                      DSPMMU_CAM_L_VA_TAG_L2_MASK_64KB;
-       case DSPMMU_CAM_L_SLST_4KB:
-               return DSPMMU_CAM_L_VA_TAG_L1_MASK |
-                      DSPMMU_CAM_L_VA_TAG_L2_MASK_4KB;
-       case DSPMMU_CAM_L_SLST_1KB:
-               return DSPMMU_CAM_L_VA_TAG_L1_MASK |
-                      DSPMMU_CAM_L_VA_TAG_L2_MASK_1KB;
+#ifdef CONFIG_ARCH_OMAP1
+static dsp_mmu_reg_t get_cam_l_va_mask(dsp_mmu_reg_t pgsz)
+{
+       switch (pgsz) {
+       case DSP_MMU_CAM_PAGESIZE_1MB:
+               return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
+                      DSP_MMU_CAM_L_VA_TAG_L2_MASK_1MB;
+       case DSP_MMU_CAM_PAGESIZE_64KB:
+               return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
+                      DSP_MMU_CAM_L_VA_TAG_L2_MASK_64KB;
+       case DSP_MMU_CAM_PAGESIZE_4KB:
+               return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
+                      DSP_MMU_CAM_L_VA_TAG_L2_MASK_4KB;
+       case DSP_MMU_CAM_PAGESIZE_1KB:
+               return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
+                      DSP_MMU_CAM_L_VA_TAG_L2_MASK_1KB;
        }
        return 0;
 }
+#endif /* CONFIG_ARCH_OMAP1 */
+
+#if defined(CONFIG_ARCH_OMAP1)
+#define get_cam_va_mask(pgsz) \
+       ((u32)DSP_MMU_CAM_H_VA_TAG_H_MASK << 22 | \
+        (u32)get_cam_l_va_mask(pgsz) << 6)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define get_cam_va_mask(pgsz) \
+       ((pgsz == DSP_MMU_CAM_PAGESIZE_16MB) ? 0xff000000 : \
+        (pgsz == DSP_MMU_CAM_PAGESIZE_1MB)  ? 0xfff00000 : \
+        (pgsz == DSP_MMU_CAM_PAGESIZE_64KB) ? 0xffff0000 : \
+        (pgsz == DSP_MMU_CAM_PAGESIZE_4KB)  ? 0xfffff000 : 0)
+#endif /* CONFIG_ARCH_OMAP2 */
 
-static __inline__ void get_tlb_lock(int *base, int *victim)
+static void get_tlb_lock(struct tlb_lock *tlb_lock)
 {
-       unsigned short lock = omap_readw(DSPMMU_LOCK);
-       if (base != NULL)
-               *base = (lock & DSPMMU_LOCK_BASE_MASK)
-                       >> DSPMMU_LOCK_BASE_SHIFT;
-       if (victim != NULL)
-               *victim = (lock & DSPMMU_LOCK_VICTIM_MASK)
-                         >> DSPMMU_LOCK_VICTIM_SHIFT;
+       dsp_mmu_reg_t lock = dsp_mmu_read_reg(DSP_MMU_LOCK);
+
+       tlb_lock->base = (lock & DSP_MMU_LOCK_BASE_MASK) >>
+                        DSP_MMU_LOCK_BASE_SHIFT;
+       tlb_lock->victim = (lock & DSP_MMU_LOCK_VICTIM_MASK) >>
+                          DSP_MMU_LOCK_VICTIM_SHIFT;
 }
 
-static __inline__ void set_tlb_lock(int base, int victim)
+static void set_tlb_lock(struct tlb_lock *tlb_lock)
 {
-       omap_writew((base   << DSPMMU_LOCK_BASE_SHIFT) |
-                   (victim << DSPMMU_LOCK_VICTIM_SHIFT), DSPMMU_LOCK);
+       dsp_mmu_write_reg((tlb_lock->base   << DSP_MMU_LOCK_BASE_SHIFT) |
+                         (tlb_lock->victim << DSP_MMU_LOCK_VICTIM_SHIFT),
+                         DSP_MMU_LOCK);
 }
 
-static __inline__ void __read_tlb(unsigned short lbase, unsigned short victim,
-                                 unsigned short *cam_h, unsigned short *cam_l,
-                                 unsigned short *ram_h, unsigned short *ram_l)
+static void __read_tlb(struct tlb_lock *tlb_lock, struct cam_ram_regset *cr)
 {
        /* set victim */
-       set_tlb_lock(lbase, victim);
+       set_tlb_lock(tlb_lock);
 
+#if defined(CONFIG_ARCH_OMAP1)
        /* read a TLB entry */
-       omap_writew(DSPMMU_LD_TLB_RD, DSPMMU_LD_TLB);
-
-       if (cam_h != NULL)
-               *cam_h = omap_readw(DSPMMU_READ_CAM_H);
-       if (cam_l != NULL)
-               *cam_l = omap_readw(DSPMMU_READ_CAM_L);
-       if (ram_h != NULL)
-               *ram_h = omap_readw(DSPMMU_READ_RAM_H);
-       if (ram_l != NULL)
-               *ram_l = omap_readw(DSPMMU_READ_RAM_L);
+       dsp_mmu_write_reg(DSP_MMU_LD_TLB_RD, DSP_MMU_LD_TLB);
+
+       cr->cam_h = dsp_mmu_read_reg(DSP_MMU_READ_CAM_H);
+       cr->cam_l = dsp_mmu_read_reg(DSP_MMU_READ_CAM_L);
+       cr->ram_h = dsp_mmu_read_reg(DSP_MMU_READ_RAM_H);
+       cr->ram_l = dsp_mmu_read_reg(DSP_MMU_READ_RAM_L);
+#elif defined(CONFIG_ARCH_OMAP2)
+       cr->cam = dsp_mmu_read_reg(DSP_MMU_READ_CAM);
+       cr->ram = dsp_mmu_read_reg(DSP_MMU_READ_RAM);
+#endif
 }
 
-static __inline__ void __load_tlb(unsigned short cam_h, unsigned short cam_l,
-                                 unsigned short ram_h, unsigned short ram_l)
+static void __load_tlb(struct cam_ram_regset *cr)
 {
-       omap_writew(cam_h, DSPMMU_CAM_H);
-       omap_writew(cam_l, DSPMMU_CAM_L);
-       omap_writew(ram_h, DSPMMU_RAM_H);
-       omap_writew(ram_l, DSPMMU_RAM_L);
+#if defined(CONFIG_ARCH_OMAP1)
+       dsp_mmu_write_reg(cr->cam_h, DSP_MMU_CAM_H);
+       dsp_mmu_write_reg(cr->cam_l, DSP_MMU_CAM_L);
+       dsp_mmu_write_reg(cr->ram_h, DSP_MMU_RAM_H);
+       dsp_mmu_write_reg(cr->ram_l, DSP_MMU_RAM_L);
+#elif defined(CONFIG_ARCH_OMAP2)
+       dsp_mmu_write_reg(cr->cam | DSP_MMU_CAM_V, DSP_MMU_CAM);
+       dsp_mmu_write_reg(cr->ram, DSP_MMU_RAM);
+#endif
 
        /* flush the entry */
        dsp_mmu_flush();
 
        /* load a TLB entry */
-       omap_writew(DSPMMU_LD_TLB_LD, DSPMMU_LD_TLB);
+       dsp_mmu_write_reg(DSP_MMU_LD_TLB_LD, DSP_MMU_LD_TLB);
 }
 
-static int dsp_mmu_load_tlb(unsigned long vadr, unsigned long padr,
-                           unsigned short slst, unsigned short prsvd,
-                           unsigned short ap)
+static int dsp_mmu_load_tlb(struct tlb_entry *tlb_ent)
 {
-       int lbase, victim;
-       unsigned short cam_l_va_mask;
+       struct tlb_lock tlb_lock;
+       struct cam_ram_regset cr;
 
+#ifdef CONFIG_ARCH_OMAP1
        clk_enable(dsp_ck_handle);
+       omap_dsp_request_mem();
+#endif
 
-       get_tlb_lock(&lbase, NULL);
-       for (victim = 0; victim < lbase; victim++) {
-               unsigned short cam_l;
+       get_tlb_lock(&tlb_lock);
+       for (tlb_lock.victim = 0;
+            tlb_lock.victim < tlb_lock.base;
+            tlb_lock.victim++) {
+               struct cam_ram_regset tmp_cr;
 
                /* read a TLB entry */
-               __read_tlb(lbase, victim, NULL, &cam_l, NULL, NULL);
-               if (!(cam_l & DSPMMU_CAM_L_V))
+               __read_tlb(&tlb_lock, &tmp_cr);
+               if (!cam_ram_valid(tmp_cr))
                        goto found_victim;
        }
-       set_tlb_lock(lbase, victim);
+       set_tlb_lock(&tlb_lock);
 
 found_victim:
        /* The last (31st) entry cannot be locked? */
-       if (victim == 31) {
+       if (tlb_lock.victim == 31) {
                printk(KERN_ERR "omapdsp: TLB is full.\n");
                return -EBUSY;
        }
 
-       cam_l_va_mask = get_cam_l_va_mask(slst);
-       if (vadr &
-           ~(DSPMMU_CAM_H_VA_TAG_H_MASK << 22 |
-             (unsigned long)cam_l_va_mask << 6)) {
+       if (tlb_ent->va & ~get_cam_va_mask(tlb_ent->pgsz)) {
                printk(KERN_ERR
-                      "omapdsp: mapping vadr (0x%06lx) is not "
-                      "aligned boundary\n", vadr);
+                      "omapdsp: mapping vadr (0x%06x) is not "
+                      "aligned boundary\n", tlb_ent->va);
                return -EINVAL;
        }
 
-       __load_tlb(vadr >> 22, (vadr >> 6 & cam_l_va_mask) | prsvd | slst,
-                  padr >> 16, (padr & DSPMMU_RAM_L_RAM_LSB_MASK) | ap);
+#if defined(CONFIG_ARCH_OMAP1)
+       cr.cam_h = tlb_ent->va >> 22;
+       cr.cam_l = (tlb_ent->va >> 6 & get_cam_l_va_mask(tlb_ent->pgsz)) |
+                  tlb_ent->prsvd | tlb_ent->pgsz;
+       cr.ram_h = tlb_ent->pa >> 16;
+       cr.ram_l = (tlb_ent->pa & DSP_MMU_RAM_L_RAM_LSB_MASK) | tlb_ent->ap;
+#elif defined(CONFIG_ARCH_OMAP2)
+       cr.cam = (tlb_ent->va & DSP_MMU_CAM_VATAG_MASK) |
+                tlb_ent->prsvd | tlb_ent->pgsz;
+       cr.ram = tlb_ent->pa | tlb_ent->endian | tlb_ent->elsz;
+#endif
+       __load_tlb(&cr);
 
        /* update lock base */
-       if (victim == lbase)
-               lbase++;
-       set_tlb_lock(lbase, lbase);
+       if (tlb_lock.victim == tlb_lock.base)
+               tlb_lock.base++;
+       tlb_lock.victim = tlb_lock.base;
+       set_tlb_lock(&tlb_lock);
 
+#ifdef CONFIG_ARCH_OMAP1
+       omap_dsp_release_mem();
        clk_disable(dsp_ck_handle);
+#endif
        return 0;
 }
 
-static int dsp_mmu_clear_tlb(unsigned long vadr)
+static int dsp_mmu_clear_tlb(dsp_long_t vadr)
 {
-       int lbase;
+       struct tlb_lock tlb_lock;
        int i;
        int max_valid = 0;
 
+#ifdef CONFIG_ARCH_OMAP1
        clk_enable(dsp_ck_handle);
+       omap_dsp_request_mem();
+#endif
 
-       get_tlb_lock(&lbase, NULL);
-       for (i = 0; i < lbase; i++) {
-               unsigned short cam_h, cam_l;
-               unsigned short cam_l_va_mask, cam_vld, slst;
-               unsigned long cam_va;
+       get_tlb_lock(&tlb_lock);
+       for (i = 0; i < tlb_lock.base; i++) {
+               struct cam_ram_regset cr;
+               dsp_long_t cam_va;
+               dsp_mmu_reg_t pgsz;
 
                /* read a TLB entry */
-               __read_tlb(lbase, i, &cam_h, &cam_l, NULL, NULL);
-
-               cam_vld = cam_l & DSPMMU_CAM_L_V;
-               if (!cam_vld)
+               tlb_lock.victim = i;
+               __read_tlb(&tlb_lock, &cr);
+               if (!cam_ram_valid(cr))
                        continue;
 
-               slst = cam_l & DSPMMU_CAM_L_SLST_MASK;
-               cam_l_va_mask = get_cam_l_va_mask(slst);
-               cam_va = (unsigned long)(cam_h & DSPMMU_CAM_H_VA_TAG_H_MASK) << 22 |
-                        (unsigned long)(cam_l & cam_l_va_mask) << 6;
+#if defined(CONFIG_ARCH_OMAP1)
+               pgsz = cr.cam_l & DSP_MMU_CAM_PAGESIZE_MASK;
+               cam_va = (u32)(cr.cam_h & DSP_MMU_CAM_H_VA_TAG_H_MASK) << 22 |
+                        (u32)(cr.cam_l & get_cam_l_va_mask(pgsz)) << 6;
+#elif defined(CONFIG_ARCH_OMAP2)
+               pgsz = cr.cam & DSP_MMU_CAM_PAGESIZE_MASK;
+               cam_va = cr.cam & get_cam_va_mask(pgsz);
+#endif
 
                if (cam_va == vadr)
                        /* flush the entry */
@@ -804,46 +1060,63 @@ static int dsp_mmu_clear_tlb(unsigned long vadr)
        }
 
        /* set new lock base */
-       set_tlb_lock(max_valid+1, max_valid+1);
+       tlb_lock.base   = max_valid + 1;
+       tlb_lock.victim = max_valid + 1;
+       set_tlb_lock(&tlb_lock);
 
+#ifdef CONFIG_ARCH_OMAP1
+       omap_dsp_release_mem();
        clk_disable(dsp_ck_handle);
+#endif
        return 0;
 }
 
 static void dsp_mmu_gflush(void)
 {
+       struct tlb_lock tlb_lock;
+
+#ifdef CONFIG_ARCH_OMAP1
        clk_enable(dsp_ck_handle);
+       omap_dsp_request_mem();
+#endif
 
        __dsp_mmu_gflush();
-       set_tlb_lock(1, 1);
+       tlb_lock.base   = exmap_preserved_cnt;
+       tlb_lock.victim = exmap_preserved_cnt;
+       set_tlb_lock(&tlb_lock);
 
+#ifdef CONFIG_ARCH_OMAP1
+       omap_dsp_release_mem();
        clk_disable(dsp_ck_handle);
+#endif
 }
 
 /*
  * dsp_exmap()
  *
- * OMAP_DSP_MEM_IOCTL_EXMAP ioctl calls this function with padr=0.
+ * MEM_IOCTL_EXMAP ioctl calls this function with padr=0.
  * In this case, the buffer for DSP is allocated in this routine,
  * then it is mapped.
  * On the other hand, for example - frame buffer sharing, calls
  * this function with padr set. It means some known address space
  * pointed with padr is going to be shared with DSP.
  */
-static int dsp_exmap(unsigned long dspadr, unsigned long padr,
-                    unsigned long size, enum exmap_type type)
+static int dsp_exmap(dsp_long_t dspadr, unsigned long padr, unsigned long size,
+                    enum exmap_type_e type)
 {
-       unsigned short slst;
+       dsp_mmu_reg_t pgsz;
        void *buf;
        unsigned int order = 0;
        unsigned long unit;
-       unsigned int cntnu = 0;
-       unsigned long _dspadr = dspadr;
+       int prev = -1;
+       dsp_long_t _dspadr = dspadr;
        unsigned long _padr = padr;
        void *_vadr = dspbyte_to_virt(dspadr);
        unsigned long _size = size;
-       struct exmap_tbl *exmap_ent;
+       struct tlb_entry tlb_ent;
+       struct exmap_tbl_entry *exmap_ent;
        int status;
+       int idx;
        int i;
 
 #define MINIMUM_PAGESZ SZ_4KB
@@ -857,7 +1130,7 @@ static int dsp_exmap(unsigned long dspadr, unsigned long padr,
        }
        if (!is_aligned(dspadr, MINIMUM_PAGESZ)) {
                printk(KERN_ERR
-                      "omapdsp: DSP address(0x%lx) is not aligned.\n", dspadr);
+                      "omapdsp: DSP address(0x%x) is not aligned.\n", dspadr);
                return -EINVAL;
        }
        if (!is_aligned(padr, MINIMUM_PAGESZ)) {
@@ -880,9 +1153,9 @@ static int dsp_exmap(unsigned long dspadr, unsigned long padr,
        down_write(&exmap_sem);
 
        /* overlap check */
-       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+       for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
                unsigned long mapsize;
-               struct exmap_tbl *tmp_ent = &exmap_tbl[i];
+               struct exmap_tbl_entry *tmp_ent = &exmap_tbl[i];
 
                if (!tmp_ent->valid)
                        continue;
@@ -898,8 +1171,8 @@ static int dsp_exmap(unsigned long dspadr, unsigned long padr,
 start:
        buf = NULL;
        /* Are there any free TLB lines?  */
-       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
-               if (!exmap_tbl[i].valid)
+       for (idx = 0; idx < DSP_MMU_TLB_LINES; idx++) {
+               if (!exmap_tbl[idx].valid)
                        goto found_free;
        }
        printk(KERN_ERR "omapdsp: DSP TLB is full.\n");
@@ -907,21 +1180,26 @@ start:
        goto fail;
 
 found_free:
-       exmap_ent = &exmap_tbl[i];
+       exmap_ent = &exmap_tbl[idx];
 
+       /*
+        * we don't use
+        * 1KB mapping in OMAP1,
+        * 16MB mapping in OMAP2.
+        */
        if ((_size >= SZ_1MB) &&
            (is_aligned(_padr, SZ_1MB) || (padr == 0)) &&
            is_aligned(_dspadr, SZ_1MB)) {
                unit = SZ_1MB;
-               slst = DSPMMU_CAM_L_SLST_1MB;
+               pgsz = DSP_MMU_CAM_PAGESIZE_1MB;
        } else if ((_size >= SZ_64KB) &&
                   (is_aligned(_padr, SZ_64KB) || (padr == 0)) &&
                   is_aligned(_dspadr, SZ_64KB)) {
                unit = SZ_64KB;
-               slst = DSPMMU_CAM_L_SLST_64KB;
+               pgsz = DSP_MMU_CAM_PAGESIZE_64KB;
        } else {
                unit = SZ_4KB;
-               slst = DSPMMU_CAM_L_SLST_4KB;
+               pgsz = DSP_MMU_CAM_PAGESIZE_4KB;
        }
 
        order = get_order(unit);
@@ -962,19 +1240,17 @@ found_free:
                goto fail;
 
        /* loading DSP TLB entry */
-       status = dsp_mmu_load_tlb(_dspadr, _padr, slst, 0, DSPMMU_RAM_L_AP_FA);
+       INIT_TLB_ENTRY(&tlb_ent, _dspadr, _padr, pgsz);
+       status = dsp_mmu_load_tlb(&tlb_ent);
        if (status < 0) {
                exmap_clear_armmmu((unsigned long)_vadr, unit);
                goto fail;
        }
 
-       exmap_ent->buf      = buf;
-       exmap_ent->vadr     = _vadr;
-       exmap_ent->order    = order;
-       exmap_ent->valid    = 1;
-       exmap_ent->cntnu    = cntnu;
-       exmap_ent->type     = type;
-       exmap_ent->usecount = 0;
+       INIT_EXMAP_TBL_ENTRY(exmap_ent, buf, _vadr, type, order);
+       exmap_ent->link.prev = prev;
+       if (prev >= 0)
+               exmap_tbl[prev].link.next = idx;
 
        if ((_size -= unit) == 0) {     /* normal completion */
                up_write(&exmap_sem);
@@ -984,7 +1260,7 @@ found_free:
        _dspadr += unit;
        _vadr   += unit;
        _padr = padr ? _padr + unit : 0;
-       cntnu = 1;
+       prev = idx;
        goto start;
 
 fail:
@@ -995,7 +1271,7 @@ fail:
        return status;
 }
 
-static unsigned long unmap_free_arm(struct exmap_tbl *ent)
+static unsigned long unmap_free_arm(struct exmap_tbl_entry *ent)
 {
        unsigned long size;
 
@@ -1031,26 +1307,26 @@ static unsigned long unmap_free_arm(struct exmap_tbl *ent)
        return size;
 }
 
-static int dsp_exunmap(unsigned long dspadr)
+static int dsp_exunmap(dsp_long_t dspadr)
 {
        void *vadr;
        unsigned long size;
        int total = 0;
-       struct exmap_tbl *ent;
+       struct exmap_tbl_entry *ent;
        int idx;
 
        vadr = dspbyte_to_virt(dspadr);
        down_write(&exmap_sem);
-       for (idx = 0; idx < DSPMMU_TLB_LINES; idx++) {
+       for (idx = 0; idx < DSP_MMU_TLB_LINES; idx++) {
                ent = &exmap_tbl[idx];
-               if (!ent->valid)
+               if ((!ent->valid) || ent->prsvd)
                        continue;
                if (ent->vadr == vadr)
                        goto found_map;
        }
        up_write(&exmap_sem);
        printk(KERN_WARNING
-              "omapdsp: address %06lx not found in exmap_tbl.\n", dspadr);
+              "omapdsp: address %06x not found in exmap_tbl.\n", dspadr);
        return -EINVAL;
 
 found_map:
@@ -1075,13 +1351,9 @@ found_map:
        /* flush TLB */
        flush_tlb_kernel_range((unsigned long)vadr, (unsigned long)vadr + size);
 
-       /* check if next mapping is in same group */
-       if (++idx == DSPMMU_TLB_LINES)
+       if ((idx = ent->link.next) < 0)
                goto up_out;    /* normal completion */
        ent = &exmap_tbl[idx];
-       if (!ent->valid || !ent->cntnu)
-               goto up_out;    /* normal completion */
-
        dspadr += size;
        vadr   += size;
        if (ent->vadr == vadr)
@@ -1101,7 +1373,7 @@ up_out:
 
 static void exmap_flush(void)
 {
-       struct exmap_tbl *ent;
+       struct exmap_tbl_entry *ent;
        int i;
 
        down_write(&exmap_sem);
@@ -1109,10 +1381,9 @@ static void exmap_flush(void)
        /* clearing DSP TLB entry */
        dsp_mmu_gflush();
 
-       /* exmap_tbl[0] should be preserved */
-       for (i = 1; i < DSPMMU_TLB_LINES; i++) {
+       for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
                ent = &exmap_tbl[i];
-               if (ent->valid) {
+               if (ent->valid && (!ent->prsvd)) {
                        unmap_free_arm(ent);
                        ent->valid = 0;
                }
@@ -1145,9 +1416,9 @@ static int omapfb_notifier_cb(struct omapfb_notifier_block *omapfb_nb,
 }
 #endif
 
-static int dsp_fbexport(unsigned long *dspadr)
+static int dsp_fbexport(dsp_long_t *dspadr)
 {
-       unsigned long dspadr_actual;
+       dsp_long_t dspadr_actual;
        unsigned long padr_sys, padr, fbsz_sys, fbsz;
        int cnt;
 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
@@ -1196,7 +1467,7 @@ static int dsp_fbexport(unsigned long *dspadr)
                /* (fbsz > SZ_4KB) ? */ *dspadr;
        if (dspadr_actual != *dspadr)
                printk(KERN_DEBUG
-                      "omapdsp: actual dspadr for FBEXPORT = %08lx\n",
+                      "omapdsp: actual dspadr for FBEXPORT = %08x\n",
                       dspadr_actual);
        *dspadr = dspadr_actual;
 
@@ -1218,8 +1489,10 @@ static int dsp_fbexport(unsigned long *dspadr)
                       padr_sys, fbsz_sys, padr, fbsz);
        }
 
+#ifdef CONFIG_ARCH_OMAP1
        /* increase the DMA priority */
        set_emiff_dma_prio(15);
+#endif
 
 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
        omapfb_nb = kmalloc(sizeof(struct omapfb_notifier_block), GFP_KERNEL);
@@ -1241,7 +1514,7 @@ static int dsp_fbexport(unsigned long *dspadr)
 
 #else /* CONFIG_OMAP_DSP_FBEXPORT */
 
-static int dsp_fbexport(unsigned long *dspadr)
+static int dsp_fbexport(dsp_long_t *dspadr)
 {
        printk(KERN_ERR "omapdsp: FBEXPORT function is not enabled.\n");
        return -EINVAL;
@@ -1249,64 +1522,176 @@ static int dsp_fbexport(unsigned long *dspadr)
 
 #endif /* CONFIG_OMAP_DSP_FBEXPORT */
 
+static void exmap_setup_preserved_mem_page(void *buf, dsp_long_t dspadr,
+                                          int exmap_idx)
+{
+       unsigned long phys;
+       void *virt;
+       struct tlb_entry tlb_ent;
+
+       phys = __pa(buf);
+       virt = dspbyte_to_virt(dspadr);
+       exmap_set_armmmu((unsigned long)virt, phys, PAGE_SIZE);
+       INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(&exmap_tbl[exmap_idx], buf, virt);
+       INIT_TLB_ENTRY_4KB_PRESERVED(&tlb_ent, dspadr, phys);
+       dsp_mmu_load_tlb(&tlb_ent);
+}
+
+static void exmap_clear_mem_page(dsp_long_t dspadr)
+{
+       void *virt;
+
+       virt = dspbyte_to_virt(dspadr);
+       exmap_clear_armmmu((unsigned long)virt, PAGE_SIZE);
+       /* DSP MMU is shutting down. not handled here. */
+}
+
+#ifdef CONFIG_ARCH_OMAP2
+static void exmap_setup_iomap_page(unsigned long phys, unsigned long dsp_io_adr,
+                                  int exmap_idx)
+{
+       dsp_long_t dspadr;
+       void *virt;
+       struct tlb_entry tlb_ent;
+
+       dspadr = (IOMAP_VAL << 18) + (dsp_io_adr << 1);
+       virt = dspbyte_to_virt(dspadr);
+       exmap_set_armmmu((unsigned long)virt, phys, PAGE_SIZE);
+       INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(&exmap_tbl[exmap_idx], NULL, virt);
+       INIT_TLB_ENTRY_4KB_ES32_PRESERVED(&tlb_ent, dspadr, phys);
+       dsp_mmu_load_tlb(&tlb_ent);
+}
+
+static void exmap_clear_iomap_page(unsigned long dsp_io_adr)
+{
+       dsp_long_t dspadr;
+       void *virt;
+
+       dspadr = (IOMAP_VAL << 18) + (dsp_io_adr << 1);
+       virt = dspbyte_to_virt(dspadr);
+       exmap_clear_armmmu((unsigned long)virt, PAGE_SIZE);
+       /* DSP MMU is shutting down. not handled here. */
+}
+#endif /* CONFIG_ARCH_OMAP2 */
+
+#define OMAP2420_GPT5_BASE     (L4_24XX_BASE + 0x7c000)
+#define OMAP2420_GPT6_BASE     (L4_24XX_BASE + 0x7e000)
+#define OMAP2420_GPT7_BASE     (L4_24XX_BASE + 0x80000)
+#define OMAP2420_GPT8_BASE     (L4_24XX_BASE + 0x82000)
+#define OMAP24XX_EAC_BASE      (L4_24XX_BASE + 0x90000)
+
+static int exmap_setup_preserved_entries(void)
+{
+       int n = 0;
+
+       exmap_setup_preserved_mem_page(dspvect_page, DSP_INIT_PAGE, n++);
+#ifdef CONFIG_ARCH_OMAP2
+       exmap_setup_iomap_page(OMAP24XX_PRCM_BASE,     0x7000, n++);
+#ifdef CONFIG_ARCH_OMAP2420
+       exmap_setup_iomap_page(OMAP2420_GPT5_BASE,     0xe000, n++);
+       exmap_setup_iomap_page(OMAP2420_GPT6_BASE,     0xe800, n++);
+       exmap_setup_iomap_page(OMAP2420_GPT7_BASE,     0xf000, n++);
+       exmap_setup_iomap_page(OMAP2420_GPT8_BASE,     0xf800, n++);
+#endif /* CONFIG_ARCH_OMAP2420 */
+       exmap_setup_iomap_page(OMAP24XX_EAC_BASE,     0x10000, n++);
+       exmap_setup_iomap_page(OMAP24XX_MAILBOX_BASE, 0x11000, n++);
+#endif /* CONFIG_ARCH_OMAP2 */
+
+       return n;
+}
+
+static void exmap_clear_preserved_entries(void)
+{
+       exmap_clear_mem_page(DSP_INIT_PAGE);
+#ifdef CONFIG_ARCH_OMAP2
+       exmap_clear_iomap_page(0x7000);         /* PRCM */
+#ifdef CONFIG_ARCH_OMAP2420
+       exmap_clear_iomap_page(0xe000);         /* GPT5 */
+       exmap_clear_iomap_page(0xe800);         /* GPT6 */
+       exmap_clear_iomap_page(0xf000);         /* GPT7 */
+       exmap_clear_iomap_page(0xf800);         /* GPT8 */
+#endif /* CONFIG_ARCH_OMAP2420 */
+       exmap_clear_iomap_page(0x10000);        /* EAC */
+       exmap_clear_iomap_page(0x11000);        /* MAILBOX */
+#endif /* CONFIG_ARCH_OMAP2 */
+}
+
+#ifdef CONFIG_ARCH_OMAP1
 static int dsp_mmu_itack(void)
 {
        unsigned long dspadr;
 
        printk(KERN_INFO "omapdsp: sending DSP MMU interrupt ack.\n");
-       if (!dsp_err_mmu_isset()) {
+       if (!dsp_err_isset(ERRCODE_MMU)) {
                printk(KERN_ERR "omapdsp: DSP MMU error has not been set.\n");
                return -EINVAL;
        }
        dspadr = dsp_fault_adr & ~(SZ_4K-1);
        dsp_exmap(dspadr, 0, SZ_4K, EXMAP_TYPE_MEM);    /* FIXME: reserve TLB entry for this */
        printk(KERN_INFO "omapdsp: falling into recovery runlevel...\n");
-       dsp_runlevel(OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY);
+       dsp_set_runlevel(RUNLEVEL_RECOVERY);
        __dsp_mmu_itack();
        udelay(100);
        dsp_exunmap(dspadr);
-       dsp_err_mmu_clear();
+       dsp_err_clear(ERRCODE_MMU);
        return 0;
 }
+#endif /* CONFIG_ARCH_OMAP1 */
+
+#ifdef CONFIG_ARCH_OMAP2
+#define MMU_IRQ_MASK \
+       (DSP_MMU_IRQ_MULTIHITFAULT | \
+        DSP_MMU_IRQ_TABLEWALKFAULT | \
+        DSP_MMU_IRQ_EMUMISS | \
+        DSP_MMU_IRQ_TRANSLATIONFAULT | \
+        DSP_MMU_IRQ_TLBMISS)
+#endif
 
 static void dsp_mmu_init(void)
 {
-       unsigned long phys;
-       void *virt;
+       struct tlb_lock tlb_lock;
 
+#ifdef CONFIG_ARCH_OMAP1
        clk_enable(dsp_ck_handle);
+       omap_dsp_request_mem();
+#endif
        down_write(&exmap_sem);
 
+#if defined(CONFIG_ARCH_OMAP1)
        dsp_mmu_disable();      /* clear all */
        udelay(100);
+#elif defined(CONFIG_ARCH_OMAP2)
+       dsp_mmu_reset();
+#endif
        dsp_mmu_enable();
 
-       /* mapping for ARM MMU */
-       phys = __pa(dspvect_page);
-       virt = dspbyte_to_virt(DSP_INIT_PAGE);  /* 0xe0fff000 */
-       exmap_set_armmmu((unsigned long)virt, phys, PAGE_SIZE);
-       exmap_tbl[0].buf      = dspvect_page;
-       exmap_tbl[0].vadr     = virt;
-       exmap_tbl[0].usecount = 0;
-       exmap_tbl[0].order    = 0;
-       exmap_tbl[0].valid    = 1;
-       exmap_tbl[0].cntnu    = 0;
-
        /* DSP TLB initialization */
-       set_tlb_lock(0, 0);
-       /* preserved, full access */
-       dsp_mmu_load_tlb(DSP_INIT_PAGE, phys, DSPMMU_CAM_L_SLST_4KB,
-                        DSPMMU_CAM_L_P, DSPMMU_RAM_L_AP_FA);
+       tlb_lock.base   = 0;
+       tlb_lock.victim = 0;
+       set_tlb_lock(&tlb_lock);
+
+       exmap_preserved_cnt = exmap_setup_preserved_entries();
+
+#ifdef CONFIG_ARCH_OMAP2
+       /* MMU IRQ mask setup */
+       dsp_mmu_write_reg(MMU_IRQ_MASK, DSP_MMU_IRQENABLE);
+#endif
+
        up_write(&exmap_sem);
+#ifdef CONFIG_ARCH_OMAP1
+       omap_dsp_release_mem();
        clk_disable(dsp_ck_handle);
+#endif
 }
 
 static void dsp_mmu_shutdown(void)
 {
        exmap_flush();
-       dsp_mmu_disable();      /* clear all */
+       exmap_clear_preserved_entries();
+       dsp_mmu_disable();
 }
 
+#ifdef CONFIG_ARCH_OMAP1
 /*
  * intmem_enable() / disable():
  * if the address is in DSP internal memories,
@@ -1317,31 +1702,34 @@ static int intmem_enable(void)
 {
        int ret = 0;
 
-       if (dsp_is_ready())
-               ret = dsp_mbsend(MBCMD(PM), OMAP_DSP_MBCMD_PM_ENABLE,
-                                DSPREG_ICR_DMA_IDLE_DOMAIN);
+       if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
+               ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA);
 
        return ret;
 }
 
 static void intmem_disable(void) {
-       if (dsp_is_ready())
-               dsp_mbsend(MBCMD(PM), OMAP_DSP_MBCMD_PM_DISABLE,
-                          DSPREG_ICR_DMA_IDLE_DOMAIN);
+       if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
+               mbcompose_send(PM, PM_DISABLE, DSPREG_ICR_DMA);
 }
+#endif /* CONFIG_ARCH_OMAP1 */
 
 /*
  * dsp_mem_enable() / disable()
  */
+#ifdef CONFIG_ARCH_OMAP1
 int intmem_usecount;
+#endif
 
 int dsp_mem_enable(void *adr)
 {
        int ret = 0;
 
        if (is_dsp_internal_mem(adr)) {
+#ifdef CONFIG_ARCH_OMAP1
                if (intmem_usecount++ == 0)
                        ret = omap_dsp_request_mem();
+#endif
        } else
                down_read(&exmap_sem);
 
@@ -1351,13 +1739,16 @@ int dsp_mem_enable(void *adr)
 void dsp_mem_disable(void *adr)
 {
        if (is_dsp_internal_mem(adr)) {
+#ifdef CONFIG_ARCH_OMAP1
                if (--intmem_usecount == 0)
                        omap_dsp_release_mem();
+#endif
        } else
                up_read(&exmap_sem);
 }
 
 /* for safety */
+#ifdef CONFIG_ARCH_OMAP1
 void dsp_mem_usecount_clear(void)
 {
        if (intmem_usecount != 0) {
@@ -1369,6 +1760,7 @@ void dsp_mem_usecount_clear(void)
                omap_dsp_release_mem();
        }
 }
+#endif /* CONFIG_ARCH_OMAP1 */
 
 /*
  * dsp_mem file operations
@@ -1394,7 +1786,7 @@ static loff_t dsp_mem_lseek(struct file *file, loff_t offset, int orig)
        return ret;
 }
 
-static ssize_t intmem_read(struct file *file, char *buf, size_t count,
+static ssize_t intmem_read(struct file *file, char __user *buf, size_t count,
                           loff_t *ppos)
 {
        unsigned long p = *ppos;
@@ -1404,7 +1796,9 @@ static ssize_t intmem_read(struct file *file, char *buf, size_t count,
 
        if (p >= size)
                return 0;
+#ifdef CONFIG_ARCH_OMAP1
        clk_enable(api_ck_handle);
+#endif
        read = count;
        if (count > size - p)
                read = size - p;
@@ -1414,11 +1808,13 @@ static ssize_t intmem_read(struct file *file, char *buf, size_t count,
        }
        *ppos += read;
 out:
+#ifdef CONFIG_ARCH_OMAP1
        clk_disable(api_ck_handle);
+#endif
        return read;
 }
 
-static ssize_t exmem_read(struct file *file, char *buf, size_t count,
+static ssize_t exmem_read(struct file *file, char __user *buf, size_t count,
                          loff_t *ppos)
 {
        unsigned long p = *ppos;
@@ -1439,7 +1835,7 @@ static ssize_t exmem_read(struct file *file, char *buf, size_t count,
        return count;
 }
 
-static ssize_t dsp_mem_read(struct file *file, char *buf, size_t count,
+static ssize_t dsp_mem_read(struct file *file, char __user *buf, size_t count,
                            loff_t *ppos)
 {
        int ret;
@@ -1456,8 +1852,8 @@ static ssize_t dsp_mem_read(struct file *file, char *buf, size_t count,
        return ret;
 }
 
-static ssize_t intmem_write(struct file *file, const char *buf, size_t count,
-                           loff_t *ppos)
+static ssize_t intmem_write(struct file *file, const char __user *buf,
+                           size_t count, loff_t *ppos)
 {
        unsigned long p = *ppos;
        void *vadr = dspbyte_to_virt(p);
@@ -1466,7 +1862,9 @@ static ssize_t intmem_write(struct file *file, const char *buf, size_t count,
 
        if (p >= size)
                return 0;
+#ifdef CONFIG_ARCH_OMAP1
        clk_enable(api_ck_handle);
+#endif
        written = count;
        if (count > size - p)
                written = size - p;
@@ -1476,12 +1874,14 @@ static ssize_t intmem_write(struct file *file, const char *buf, size_t count,
        }
        *ppos += written;
 out:
+#ifdef CONFIG_ARCH_OMAP1
        clk_disable(api_ck_handle);
+#endif
        return written;
 }
 
-static ssize_t exmem_write(struct file *file, const char *buf, size_t count,
-                          loff_t *ppos)
+static ssize_t exmem_write(struct file *file, const char __user *buf,
+                          size_t count, loff_t *ppos)
 {
        unsigned long p = *ppos;
        void *vadr = dspbyte_to_virt(p);
@@ -1501,8 +1901,8 @@ static ssize_t exmem_write(struct file *file, const char *buf, size_t count,
        return count;
 }
 
-static ssize_t dsp_mem_write(struct file *file, const char *buf, size_t count,
-                            loff_t *ppos)
+static ssize_t dsp_mem_write(struct file *file, const char __user *buf,
+                            size_t count, loff_t *ppos)
 {
        int ret;
        void *vadr = dspbyte_to_virt(*(unsigned long *)ppos);
@@ -1522,51 +1922,56 @@ static int dsp_mem_ioctl(struct inode *inode, struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
        switch (cmd) {
-       case OMAP_DSP_MEM_IOCTL_MMUINIT:
+       case MEM_IOCTL_MMUINIT:
                dsp_mmu_init();
                return 0;
 
-       case OMAP_DSP_MEM_IOCTL_EXMAP:
+       case MEM_IOCTL_EXMAP:
                {
                        struct omap_dsp_mapinfo mapinfo;
-                       if (copy_from_user(&mapinfo, (void *)arg,
+                       if (copy_from_user(&mapinfo, (void __user *)arg,
                                           sizeof(mapinfo)))
                                return -EFAULT;
                        return dsp_exmap(mapinfo.dspadr, 0, mapinfo.size,
                                         EXMAP_TYPE_MEM);
                }
 
-       case OMAP_DSP_MEM_IOCTL_EXUNMAP:
+       case MEM_IOCTL_EXUNMAP:
                return dsp_exunmap((unsigned long)arg);
 
-       case OMAP_DSP_MEM_IOCTL_EXMAP_FLUSH:
+       case MEM_IOCTL_EXMAP_FLUSH:
                exmap_flush();
                return 0;
 
-       case OMAP_DSP_MEM_IOCTL_FBEXPORT:
+       case MEM_IOCTL_FBEXPORT:
                {
-                       unsigned long dspadr;
+                       dsp_long_t dspadr;
                        int ret;
-                       if (copy_from_user(&dspadr, (void *)arg, sizeof(long)))
+                       if (copy_from_user(&dspadr, (void __user *)arg,
+                                          sizeof(dsp_long_t)))
                                return -EFAULT;
                        ret = dsp_fbexport(&dspadr);
-                       if (copy_to_user((void *)arg, &dspadr, sizeof(long)))
+                       if (copy_to_user((void __user *)arg, &dspadr,
+                                        sizeof(dsp_long_t)))
                                return -EFAULT;
                        return ret;
                }
 
-       case OMAP_DSP_MEM_IOCTL_MMUITACK:
+#ifdef CONFIG_ARCH_OMAP1
+       case MEM_IOCTL_MMUITACK:
                return dsp_mmu_itack();
+#endif
 
-       case OMAP_DSP_MEM_IOCTL_KMEM_RESERVE:
+       case MEM_IOCTL_KMEM_RESERVE:
                {
-                       unsigned long size;
-                       if (copy_from_user(&size, (void *)arg, sizeof(long)))
+                       __u32 size;
+                       if (copy_from_user(&size, (void __user *)arg,
+                                          sizeof(__u32)))
                                return -EFAULT;
                        return dsp_kmem_reserve(size);
                }
 
-       case OMAP_DSP_MEM_IOCTL_KMEM_RELEASE:
+       case MEM_IOCTL_KMEM_RELEASE:
                dsp_kmem_release();
                return 0;
 
@@ -1591,17 +1996,12 @@ static int dsp_mem_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int dsp_mem_release(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-
 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
 /*
  * fb update functions:
  * fbupd_response() is executed by the workqueue.
  * fbupd_cb() is called when fb update is done, in interrupt context.
- * mbx1_fbupd() is called when KFUNC:FBCTL:UPD is received from DSP.
+ * mbx_fbupd() is called when KFUNC:FBCTL:UPD is received from DSP.
  */
 static void fbupd_response(void *arg)
 {
@@ -1625,7 +2025,7 @@ static void fbupd_cb(void *arg)
        schedule_work(&fbupd_response_work);
 }
 
-void mbx1_fbctl_upd(void)
+void mbx_fbctl_upd(void)
 {
        struct omapfb_update_window win;
        volatile unsigned short *buf = ipbuf_sys_da->d;
@@ -1653,7 +2053,7 @@ void mbx1_fbctl_upd(void)
 
 #else /* CONFIG_FB_OMAP_LCDC_EXTERNAL */
 
-void mbx1_fbctl_upd(void)
+void mbx_fbctl_upd(void)
 {
 }
 #endif /* CONFIG_FB_OMAP_LCDC_EXTERNAL */
@@ -1661,72 +2061,130 @@ void mbx1_fbctl_upd(void)
 /*
  * sysfs files
  */
+
+/* mmu */
 static ssize_t mmu_show(struct device *dev, struct device_attribute *attr,
                        char *buf)
 {
        int len;
-       int lbase, victim;
+       struct tlb_lock tlb_lock_org;
        int i;
 
+#ifdef CONFIG_ARCH_OMAP1
        clk_enable(dsp_ck_handle);
+       omap_dsp_request_mem();
+#endif
        down_read(&exmap_sem);
 
-       get_tlb_lock(&lbase, &victim);
-
-       len = sprintf(buf, "p: preserved,  v: valid\n"
-                          "ety       cam_va     ram_pa   sz ap\n");
-                       /* 00: p v 0x300000 0x10171800 64KB FA */
-       for (i = 0; i < 32; i++) {
-               unsigned short cam_h, cam_l, ram_h, ram_l;
-               unsigned short cam_l_va_mask, prsvd, cam_vld, slst;
-               unsigned long cam_va;
-               unsigned short ram_l_ap;
-               unsigned long ram_pa;
+       get_tlb_lock(&tlb_lock_org);
+
+#if defined(CONFIG_ARCH_OMAP1)
+       len = sprintf(buf, "P: preserved, V: valid\n"
+                          "ety P V size   cam_va     ram_pa ap\n");
+                        /* 00: P V  4KB 0x300000 0x10171800 FA */
+#elif defined(CONFIG_ARCH_OMAP2)
+       len = sprintf(buf, "P: preserved, V: valid\n"
+                          "B: big endian, L:little endian, "
+                          "M: mixed page attribute\n"
+                          "ety P V size   cam_va     ram_pa E ES M\n");
+                        /* 00: P V  4KB 0x300000 0x10171800 B 16 M */
+#endif
+
+       for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
+               struct cam_ram_regset cr;
+               struct tlb_lock tlb_lock_tmp;
+               struct tlb_entry ent;
+#if defined(CONFIG_ARCH_OMAP1)
                char *pgsz_str, *ap_str;
+#elif defined(CONFIG_ARCH_OMAP2)
+               char *pgsz_str, *elsz_str;
+#endif
 
                /* read a TLB entry */
-               __read_tlb(lbase, i, &cam_h, &cam_l, &ram_h, &ram_l);
-
-               slst = cam_l & DSPMMU_CAM_L_SLST_MASK;
-               cam_l_va_mask = get_cam_l_va_mask(slst);
-               pgsz_str = (slst == DSPMMU_CAM_L_SLST_1MB) ? " 1MB":
-                          (slst == DSPMMU_CAM_L_SLST_64KB)? "64KB":
-                          (slst == DSPMMU_CAM_L_SLST_4KB) ? " 4KB":
-                                                            " 1KB";
-               prsvd    = cam_l & DSPMMU_CAM_L_P;
-               cam_vld  = cam_l & DSPMMU_CAM_L_V;
-               ram_l_ap = ram_l & DSPMMU_RAM_L_AP_MASK;
-               ap_str = (ram_l_ap == DSPMMU_RAM_L_AP_RO) ? "RO":
-                        (ram_l_ap == DSPMMU_RAM_L_AP_FA) ? "FA":
-                                                           "NA";
-               cam_va = (unsigned long)(cam_h & DSPMMU_CAM_H_VA_TAG_H_MASK) << 22 |
-                        (unsigned long)(cam_l & cam_l_va_mask) << 6;
-               ram_pa = (unsigned long)ram_h << 16 |
-                        (ram_l & DSPMMU_RAM_L_RAM_LSB_MASK);
-
-               if (i == lbase)
-                       len += sprintf(buf + len, "lock base = %d\n", lbase);
-               if (i == victim)
-                       len += sprintf(buf + len, "victim    = %d\n", victim);
-               /* 00: p v 0x300000 0x10171800 64KB FA */
+               tlb_lock_tmp.base   = tlb_lock_org.base;
+               tlb_lock_tmp.victim = i;
+               __read_tlb(&tlb_lock_tmp, &cr);
+
+#if defined(CONFIG_ARCH_OMAP1)
+               ent.pgsz  = cr.cam_l & DSP_MMU_CAM_PAGESIZE_MASK;
+               ent.prsvd = cr.cam_l & DSP_MMU_CAM_P;
+               ent.valid = cr.cam_l & DSP_MMU_CAM_V;
+               ent.ap    = cr.ram_l & DSP_MMU_RAM_L_AP_MASK;
+               ent.va = (u32)(cr.cam_h & DSP_MMU_CAM_H_VA_TAG_H_MASK) << 22 |
+                        (u32)(cr.cam_l & get_cam_l_va_mask(ent.pgsz)) << 6;
+               ent.pa = (unsigned long)cr.ram_h << 16 |
+                        (cr.ram_l & DSP_MMU_RAM_L_RAM_LSB_MASK);
+
+               pgsz_str = (ent.pgsz == DSP_MMU_CAM_PAGESIZE_1MB)  ? " 1MB":
+                          (ent.pgsz == DSP_MMU_CAM_PAGESIZE_64KB) ? "64KB":
+                          (ent.pgsz == DSP_MMU_CAM_PAGESIZE_4KB)  ? " 4KB":
+                          (ent.pgsz == DSP_MMU_CAM_PAGESIZE_1KB)  ? " 1KB":
+                                                                    " ???";
+               ap_str = (ent.ap == DSP_MMU_RAM_L_AP_RO) ? "RO":
+                        (ent.ap == DSP_MMU_RAM_L_AP_FA) ? "FA":
+                        (ent.ap == DSP_MMU_RAM_L_AP_NA) ? "NA":
+                                                          "??";
+#elif defined(CONFIG_ARCH_OMAP2)
+               ent.pgsz   = cr.cam & DSP_MMU_CAM_PAGESIZE_MASK;
+               ent.prsvd  = cr.cam & DSP_MMU_CAM_P;
+               ent.valid  = cr.cam & DSP_MMU_CAM_V;
+               ent.va     = cr.cam & DSP_MMU_CAM_VATAG_MASK;
+               ent.endian = cr.ram & DSP_MMU_RAM_ENDIANNESS;
+               ent.elsz   = cr.ram & DSP_MMU_RAM_ELEMENTSIZE_MASK;
+               ent.pa     = cr.ram & DSP_MMU_RAM_PADDR_MASK;
+               ent.mixed  = cr.ram & DSP_MMU_RAM_MIXED;
+
+               pgsz_str = (ent.pgsz == DSP_MMU_CAM_PAGESIZE_16MB) ? "64MB":
+                          (ent.pgsz == DSP_MMU_CAM_PAGESIZE_1MB)  ? " 1MB":
+                          (ent.pgsz == DSP_MMU_CAM_PAGESIZE_64KB) ? "64KB":
+                          (ent.pgsz == DSP_MMU_CAM_PAGESIZE_4KB)  ? " 4KB":
+                                                                    " ???";
+               elsz_str = (ent.elsz == DSP_MMU_RAM_ELEMENTSIZE_8)  ? " 8":
+                          (ent.elsz == DSP_MMU_RAM_ELEMENTSIZE_16) ? "16":
+                          (ent.elsz == DSP_MMU_RAM_ELEMENTSIZE_32) ? "32":
+                                                                     "??";
+#endif
+
+               if (i == tlb_lock_org.base)
+                       len += sprintf(buf + len, "lock base = %d\n",
+                                      tlb_lock_org.base);
+               if (i == tlb_lock_org.victim)
+                       len += sprintf(buf + len, "victim    = %d\n",
+                                      tlb_lock_org.victim);
+#if defined(CONFIG_ARCH_OMAP1)
+               len += sprintf(buf + len,
+                              /* 00: P V  4KB 0x300000 0x10171800 FA */
+                              "%02d: %c %c %s 0x%06x 0x%08lx %s\n",
+                              i,
+                              ent.prsvd ? 'P' : ' ',
+                              ent.valid ? 'V' : ' ',
+                              pgsz_str, ent.va, ent.pa, ap_str);
+#elif defined(CONFIG_ARCH_OMAP2)
                len += sprintf(buf + len,
-                              "%02d: %c %c 0x%06lx 0x%08lx %s %s\n",
+                              /* 00: P V  4KB 0x300000 0x10171800 B 16 M */
+                              "%02d: %c %c %s 0x%06x 0x%08lx %c %s %c\n",
                               i,
-                              prsvd   ? 'p' : ' ',
-                              cam_vld ? 'v' : ' ',
-                              cam_va, ram_pa, pgsz_str, ap_str);
+                              ent.prsvd ? 'P' : ' ',
+                              ent.valid ? 'V' : ' ',
+                              pgsz_str, ent.va, ent.pa,
+                              ent.endian ? 'B' : 'L',
+                              elsz_str,
+                              ent.mixed ? 'M' : ' ');
+#endif /* CONFIG_ARCH_OMAP2 */
        }
 
        /* restore victim entry */
-       set_tlb_lock(lbase, victim);
+       set_tlb_lock(&tlb_lock_org);
 
        up_read(&exmap_sem);
+#ifdef CONFIG_ARCH_OMAP1
+       omap_dsp_release_mem();
        clk_disable(dsp_ck_handle);
+#endif
        return len;
 }
 
-static struct device_attribute dev_attr_mmu = __ATTR_RO(mmu);
-
+/* exmap */
 static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
                          char *buf)
 {
@@ -1734,128 +2192,208 @@ static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
        int i;
 
        down_read(&exmap_sem);
-       len = sprintf(buf, "v: valid,  c: cntnu\n"
-                          "ety           vadr        buf od uc\n");
-                        /* 00: v c 0xe0300000 0xc0171800  0 */
-       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
-               struct exmap_tbl *ent = &exmap_tbl[i];
-               /* 00: v c 0xe0300000 0xc0171800  0 */
-               len += sprintf(buf + len, "%02d: %c %c 0x%8p 0x%8p %2d %2d\n",
-                              i,
-                              ent->valid ? 'v' : ' ',
-                              ent->cntnu ? 'c' : ' ',
-                              ent->vadr, ent->buf, ent->order, ent->usecount);
+       len = sprintf(buf, "  dspadr     size         buf     size uc\n");
+                        /* 0x300000 0x123000  0xc0171000 0x100000  0*/
+       for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
+               struct exmap_tbl_entry *ent = &exmap_tbl[i];
+               void *vadr;
+               unsigned long size;
+               enum exmap_type_e type;
+               int idx;
+
+               /* find a top of link */
+               if (!ent->valid || (ent->link.prev >= 0))
+                       continue;
+
+               vadr = ent->vadr;
+               type = ent->type;
+               size = 0;
+               idx = i;
+               do {
+                       ent = &exmap_tbl[idx];
+                       size += PAGE_SIZE << ent->order;
+               } while ((idx = ent->link.next) >= 0);
+
+               len += sprintf(buf + len, "0x%06x %#8lx",
+                              virt_to_dspbyte(vadr), size);
+
+               if (type == EXMAP_TYPE_FB) {
+                       len += sprintf(buf + len, "    framebuf\n");
+               } else {
+                       len += sprintf(buf + len, "\n");
+                       idx = i;
+                       do {
+                               ent = &exmap_tbl[idx];
+                               len += sprintf(buf + len,
+                                              /* 0xc0171000 0x100000  0*/
+                                              "%19s0x%8p %#8lx %2d\n",
+                                              "", ent->buf,
+                                              PAGE_SIZE << ent->order,
+                                              ent->usecount);
+                       } while ((idx = ent->link.next) >= 0);
+               }
        }
 
        up_read(&exmap_sem);
        return len;
 }
 
-static struct device_attribute dev_attr_exmap = __ATTR_RO(exmap);
-
-static ssize_t kmem_pool_show(struct device *dev,
-                             struct device_attribute *attr, char *buf)
+/* mempool */
+static ssize_t mempool_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
 {
-       int nr_1M, nr_64K, total;
+       int min_nr_1M = 0, curr_nr_1M = 0;
+       int min_nr_64K = 0, curr_nr_64K = 0;
+       int total = 0;
 
-       nr_1M = kmem_pool_1M->min_nr;
-       nr_64K = kmem_pool_64K->min_nr;
-       total = nr_1M * SZ_1MB + nr_64K * SZ_64KB;
+       if (likely(kmem_pool_1M)) {
+               min_nr_1M  = kmem_pool_1M->min_nr;
+               curr_nr_1M = kmem_pool_1M->curr_nr;
+               total += min_nr_1M * SZ_1MB;
+       }
+       if (likely(kmem_pool_64K)) {
+               min_nr_64K  = kmem_pool_64K->min_nr;
+               curr_nr_64K = kmem_pool_64K->curr_nr;
+               total += min_nr_64K * SZ_64KB;
+       }
 
-       return sprintf(buf, "0x%x %d %d\n", total, nr_1M, nr_64K);
+       return sprintf(buf,
+                      "0x%x\n"
+                      "1M  buffer: %d (%d free)\n"
+                      "64K buffer: %d (%d free)\n",
+                      total, min_nr_1M, curr_nr_1M, min_nr_64K, curr_nr_64K);
 }
 
-static struct device_attribute dev_attr_kmem_pool = __ATTR_RO(kmem_pool);
-
 /*
- * DSP MMU interrupt handler
+ * workqueue for mmu int
  */
-
+#ifdef CONFIG_ARCH_OMAP1
 /*
  * MMU fault mask:
  * We ignore prefetch err.
  */
 #define MMUFAULT_MASK \
-       (DSPMMU_FAULT_ST_PERM |\
-        DSPMMU_FAULT_ST_TLB_MISS |\
-        DSPMMU_FAULT_ST_TRANS)
-irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       unsigned short status;
-       unsigned short adh, adl;
-       unsigned short dp;
-
-       status = omap_readw(DSPMMU_FAULT_ST);
-       adh = omap_readw(DSPMMU_FAULT_AD_H);
-       adl = omap_readw(DSPMMU_FAULT_AD_L);
-       dp = adh & DSPMMU_FAULT_AD_H_DP;
-       dsp_fault_adr = MKLONG(adh & DSPMMU_FAULT_AD_H_ADR_MASK, adl);
+       (DSP_MMU_FAULT_ST_PERM |\
+        DSP_MMU_FAULT_ST_TLB_MISS |\
+        DSP_MMU_FAULT_ST_TRANS)
+#endif /* CONFIG_ARCH_OMAP1 */
+
+static void do_mmu_int(void)
+{
+#if defined(CONFIG_ARCH_OMAP1)
+
+       dsp_mmu_reg_t status;
+       dsp_mmu_reg_t adh, adl;
+       dsp_mmu_reg_t dp;
+
+       status = dsp_mmu_read_reg(DSP_MMU_FAULT_ST);
+       adh = dsp_mmu_read_reg(DSP_MMU_FAULT_AD_H);
+       adl = dsp_mmu_read_reg(DSP_MMU_FAULT_AD_L);
+       dp = adh & DSP_MMU_FAULT_AD_H_DP;
+       dsp_fault_adr = MK32(adh & DSP_MMU_FAULT_AD_H_ADR_MASK, adl);
+
        /* if the fault is masked, nothing to do */
        if ((status & MMUFAULT_MASK) == 0) {
                printk(KERN_DEBUG "DSP MMU interrupt, but ignoring.\n");
                /*
                 * note: in OMAP1710,
                 * when CACHE + DMA domain gets out of idle in DSP,
-                * MMU interrupt occurs but DSPMMU_FAULT_ST is not set.
+                * MMU interrupt occurs but DSP_MMU_FAULT_ST is not set.
                 * in this case, we just ignore the interrupt.
                 */
                if (status) {
                        printk(KERN_DEBUG "%s%s%s%s\n",
-                              (status & DSPMMU_FAULT_ST_PREF)?
+                              (status & DSP_MMU_FAULT_ST_PREF)?
                                        "  (prefetch err)" : "",
-                              (status & DSPMMU_FAULT_ST_PERM)?
+                              (status & DSP_MMU_FAULT_ST_PERM)?
                                        "  (permission fault)" : "",
-                              (status & DSPMMU_FAULT_ST_TLB_MISS)?
+                              (status & DSP_MMU_FAULT_ST_TLB_MISS)?
                                        "  (TLB miss)" : "",
-                              (status & DSPMMU_FAULT_ST_TRANS) ?
+                              (status & DSP_MMU_FAULT_ST_TRANS) ?
                                        "  (translation fault)": "");
-                       printk(KERN_DEBUG
-                              "fault address = %s: 0x%06lx\n",
-                              dp ? "DATA" : "PROGRAM",
+                       printk(KERN_DEBUG "fault address = %#08x\n",
                               dsp_fault_adr);
                }
-               return IRQ_HANDLED;
+               enable_irq(INT_DSP_MMU);
+               return;
        }
 
+#elif defined(CONFIG_ARCH_OMAP2)
+
+       dsp_mmu_reg_t status;
+
+       status = dsp_mmu_read_reg(DSP_MMU_IRQSTATUS);
+       dsp_fault_adr = dsp_mmu_read_reg(DSP_MMU_FAULT_AD);
+
+#endif /* CONFIG_ARCH_OMAP2 */
+
        printk(KERN_INFO "DSP MMU interrupt!\n");
+
+#if defined(CONFIG_ARCH_OMAP1)
+
        printk(KERN_INFO "%s%s%s%s\n",
-              (status & DSPMMU_FAULT_ST_PREF)?
-                       (MMUFAULT_MASK & DSPMMU_FAULT_ST_PREF)?
+              (status & DSP_MMU_FAULT_ST_PREF)?
+                       (MMUFAULT_MASK & DSP_MMU_FAULT_ST_PREF)?
                                "  prefetch err":
                                "  (prefetch err)":
                                "",
-              (status & DSPMMU_FAULT_ST_PERM)?
-                       (MMUFAULT_MASK & DSPMMU_FAULT_ST_PERM)?
+              (status & DSP_MMU_FAULT_ST_PERM)?
+                       (MMUFAULT_MASK & DSP_MMU_FAULT_ST_PERM)?
                                "  permission fault":
                                "  (permission fault)":
                                "",
-              (status & DSPMMU_FAULT_ST_TLB_MISS)?
-                       (MMUFAULT_MASK & DSPMMU_FAULT_ST_TLB_MISS)?
+              (status & DSP_MMU_FAULT_ST_TLB_MISS)?
+                       (MMUFAULT_MASK & DSP_MMU_FAULT_ST_TLB_MISS)?
                                "  TLB miss":
                                "  (TLB miss)":
                                "",
-              (status & DSPMMU_FAULT_ST_TRANS)?
-                       (MMUFAULT_MASK & DSPMMU_FAULT_ST_TRANS)?
+              (status & DSP_MMU_FAULT_ST_TRANS)?
+                       (MMUFAULT_MASK & DSP_MMU_FAULT_ST_TRANS)?
                                "  translation fault":
                                "  (translation fault)":
                                "");
-       printk(KERN_INFO "fault address = %s: 0x%06lx\n",
-              dp ? "DATA" : "PROGRAM",
-              dsp_fault_adr);
 
-       if (dsp_is_ready()) {
-               /*
-                * If we call dsp_exmap() here,
-                * "kernel BUG at slab.c" occurs.
-                */
-               /* FIXME */
-               dsp_err_mmu_set(dsp_fault_adr);
-       } else {
-               disable_irq(INT_DSP_MMU);
+#elif defined(CONFIG_ARCH_OMAP2)
+
+       printk(KERN_INFO "%s%s%s%s%s\n",
+              (status & DSP_MMU_IRQ_MULTIHITFAULT)?
+                       (MMU_IRQ_MASK & DSP_MMU_IRQ_MULTIHITFAULT)?
+                               "  multi hit":
+                               "  (multi hit)":
+                               "",
+              (status & DSP_MMU_IRQ_TABLEWALKFAULT)?
+                       (MMU_IRQ_MASK & DSP_MMU_IRQ_TABLEWALKFAULT)?
+                               "  table walk fault":
+                               "  (table walk fault)":
+                               "",
+              (status & DSP_MMU_IRQ_EMUMISS)?
+                       (MMU_IRQ_MASK & DSP_MMU_IRQ_EMUMISS)?
+                               "  EMU miss":
+                               "  (EMU miss)":
+                               "",
+              (status & DSP_MMU_IRQ_TRANSLATIONFAULT)?
+                       (MMU_IRQ_MASK & DSP_MMU_IRQ_TRANSLATIONFAULT)?
+                               "  translation fault":
+                               "  (translation fault)":
+                               "",
+              (status & DSP_MMU_IRQ_TLBMISS)?
+                       (MMU_IRQ_MASK & DSP_MMU_IRQ_TLBMISS)?
+                               "  TLB miss":
+                               "  (TLB miss)":
+                               "");
+
+#endif /* CONFIG_ARCH_OMAP2 */
+
+       printk(KERN_INFO "fault address = %#08x\n", dsp_fault_adr);
+
+       if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
+               dsp_err_set(ERRCODE_MMU, (unsigned long)dsp_fault_adr);
+       else {
+#ifdef CONFIG_ARCH_OMAP1
                __dsp_mmu_itack();
+#endif
                printk(KERN_INFO "Resetting DSP...\n");
                dsp_cpustat_request(CPUSTAT_RESET);
-               enable_irq(INT_DSP_MMU);
                /*
                 * if we enable followings, semaphore lock should be avoided.
                 *
@@ -1865,6 +2403,26 @@ irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                 */
        }
 
+#ifdef CONFIG_ARCH_OMAP2
+       dsp_mmu_disable();
+       dsp_mmu_write_reg(status, DSP_MMU_IRQSTATUS);
+       dsp_mmu_enable();
+#endif
+
+       enable_irq(INT_DSP_MMU);
+}
+
+static DECLARE_WORK(mmu_int_work, (void (*)(void *))do_mmu_int, NULL);
+
+/*
+ * DSP MMU interrupt handler
+ */
+
+static irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id,
+                                    struct pt_regs *regs)
+{
+       disable_irq(INT_DSP_MMU);
+       schedule_work(&mmu_int_work);
        return IRQ_HANDLED;
 }
 
@@ -1879,27 +2437,44 @@ struct file_operations dsp_mem_fops = {
        .ioctl   = dsp_mem_ioctl,
        .mmap    = dsp_mem_mmap,
        .open    = dsp_mem_open,
-       .release = dsp_mem_release,
 };
 
 void dsp_mem_start(void)
 {
+#ifdef CONFIG_ARCH_OMAP1
        dsp_register_mem_cb(intmem_enable, intmem_disable);
+#endif
 }
 
 void dsp_mem_stop(void)
 {
        memset(&mem_sync, 0, sizeof(struct mem_sync_struct));
+#ifdef CONFIG_ARCH_OMAP1
        dsp_unregister_mem_cb();
+#endif
 }
 
+static char devid_mmu;
+
 int __init dsp_mem_init(void)
 {
        int i;
+       int ret = 0;
+#ifdef CONFIG_ARCH_OMAP2
+       int dspmem_pg_count;
 
-       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
-               exmap_tbl[i].valid = 0;
+       dspmem_pg_count = dspmem_size >> 12;
+       for (i = 0; i < dspmem_pg_count; i++) {
+               dsp_ipi_write_reg(i, DSP_IPI_INDEX);
+               dsp_ipi_write_reg(DSP_IPI_ENTRY_ELMSIZEVALUE_16, DSP_IPI_ENTRY);
        }
+       dsp_ipi_write_reg(1, DSP_IPI_ENABLE);
+
+       dsp_ipi_write_reg(IOMAP_VAL, DSP_IPI_IOMAP);
+#endif
+
+       for (i = 0; i < DSP_MMU_TLB_LINES; i++)
+               exmap_tbl[i].valid = 0;
 
        dspvect_page = (void *)__get_dma_pages(GFP_KERNEL, 0);
        if (dspvect_page == NULL) {
@@ -1909,34 +2484,59 @@ int __init dsp_mem_init(void)
                return -ENOMEM;
        }
        dsp_mmu_init();
+#ifdef CONFIG_ARCH_OMAP1
        dsp_set_idle_boot_base(IDLEPG_BASE, IDLEPG_SIZE);
+#endif
+
+       /*
+        * DSP MMU interrupt setup
+        */
+       ret = request_irq(INT_DSP_MMU, dsp_mmu_interrupt, SA_INTERRUPT, "dsp",
+                         &devid_mmu);
+       if (ret) {
+               printk(KERN_ERR
+                      "failed to register DSP MMU interrupt: %d\n", ret);
+               goto fail;
+       }
+
+       /* MMU interrupt is not enabled until DSP runs */
+       disable_irq(INT_DSP_MMU);
 
        device_create_file(&dsp_device.dev, &dev_attr_mmu);
        device_create_file(&dsp_device.dev, &dev_attr_exmap);
-       device_create_file(&dsp_device.dev, &dev_attr_kmem_pool);
+       device_create_file(&dsp_device.dev, &dev_attr_mempool);
 
        return 0;
+
+fail:
+#ifdef CONFIG_ARCH_OMAP1
+       dsp_reset_idle_boot_base();
+#endif
+       dsp_mmu_shutdown();
+       free_page((unsigned long)dspvect_page);
+       dspvect_page = NULL;
+       return ret;
 }
 
 void dsp_mem_exit(void)
 {
+       free_irq(INT_DSP_MMU, &devid_mmu);
+
+       /* recover disable_depth */
+       enable_irq(INT_DSP_MMU);
+
+#ifdef CONFIG_ARCH_OMAP1
+       dsp_reset_idle_boot_base();
+#endif
        dsp_mmu_shutdown();
        dsp_kmem_release();
 
        if (dspvect_page != NULL) {
-               unsigned long virt;
-
-               down_read(&exmap_sem);
-
-               virt = (unsigned long)dspbyte_to_virt(DSP_INIT_PAGE);
-               flush_tlb_kernel_range(virt, virt + PAGE_SIZE);
                free_page((unsigned long)dspvect_page);
                dspvect_page = NULL;
-
-               up_read(&exmap_sem);
        }
 
        device_remove_file(&dsp_device.dev, &dev_attr_mmu);
        device_remove_file(&dsp_device.dev, &dev_attr_exmap);
-       device_remove_file(&dsp_device.dev, &dev_attr_kmem_pool);
+       device_remove_file(&dsp_device.dev, &dev_attr_mempool);
 }
index dd7d7c4594bcbabdcf75e59c0191e706e2cdc6cb..0213218d96e12b2cda60bdc727b705300b9db225 100644 (file)
@@ -1,52 +1,51 @@
 /*
- * linux/arch/arm/mach-omap/dsp/error.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * OMAP DSP error detection I/F device driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/03/11:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/ioctls.h>
-#include <asm/arch/dsp.h>
+#include "dsp_mbcmd.h"
 #include "dsp.h"
 
+/*
+ * value seen through read()
+ */
+#define DSP_ERR_WDT    0x00000001
+#define DSP_ERR_MMU    0x00000002
+static unsigned long errval;
+
 static DECLARE_WAIT_QUEUE_HEAD(err_wait_q);
-static unsigned long errcode;
 static int errcnt;
-static unsigned short wdtval;  /* FIXME: read through ioctl */
-static unsigned long mmu_fadr; /* FIXME: read through ioctl */
+static u16 wdtval;     /* FIXME: read through ioctl */
+static u32 mmu_fadr;   /* FIXME: read through ioctl */
 
 /*
  * DSP error detection device file operations
  */
-static ssize_t dsp_err_read(struct file *file, char *buf, size_t count,
+static ssize_t dsp_err_read(struct file *file, char __user *buf, size_t count,
                            loff_t *ppos)
 {
        unsigned long flags;
@@ -71,7 +70,7 @@ static ssize_t dsp_err_read(struct file *file, char *buf, size_t count,
        }
 
        local_irq_save(flags);
-       status = copy_to_user(buf, &errcode, 4);
+       status = copy_to_user(buf, &errval, 4);
        if (status) {
                local_irq_restore(flags);
                return -EFAULT;
@@ -100,68 +99,86 @@ struct file_operations dsp_err_fops = {
 };
 
 /*
- * DSP MMU
+ * set / clear functions
  */
-void dsp_err_mmu_set(unsigned long adr)
+
+/* DSP MMU */
+static void dsp_err_mmu_set(unsigned long arg)
 {
        disable_irq(INT_DSP_MMU);
-       errcode |= OMAP_DSP_ERRDT_MMU;
-       errcnt++;
-       mmu_fadr = adr;
-       wake_up_interruptible(&err_wait_q);
+       mmu_fadr = (u32)arg;
 }
 
-void dsp_err_mmu_clear(void)
+static void dsp_err_mmu_clr(void)
 {
-       errcode &= ~OMAP_DSP_ERRDT_MMU;
        enable_irq(INT_DSP_MMU);
 }
 
-int dsp_err_mmu_isset(void)
+/* WDT */
+static void dsp_err_wdt_set(unsigned long arg)
 {
-       return (errcode & OMAP_DSP_ERRDT_MMU) ? 1 : 0;
+       wdtval = (u16)arg;
 }
 
 /*
- * WDT
+ * error code handler
  */
-void dsp_err_wdt_clear(void)
+static struct {
+       unsigned long val;
+       void (*set)(unsigned long arg);
+       void (*clr)(void);
+} dsp_err_desc[ERRCODE_MAX] = {
+       [ERRCODE_MMU] = { DSP_ERR_MMU, dsp_err_mmu_set, dsp_err_mmu_clr },
+       [ERRCODE_WDT] = { DSP_ERR_WDT, dsp_err_wdt_set, NULL },
+};
+
+void dsp_err_set(enum errcode_e code, unsigned long arg)
 {
-       errcode &= ~OMAP_DSP_ERRDT_WDT;
+       if (dsp_err_desc[code].set != NULL)
+               dsp_err_desc[code].set(arg);
+
+       errval |= dsp_err_desc[code].val;
+       errcnt++;
+       wake_up_interruptible(&err_wait_q);
+}
+
+void dsp_err_clear(enum errcode_e code)
+{
+       errval &= ~dsp_err_desc[code].val;
+
+       if (dsp_err_desc[code].clr != NULL)
+               dsp_err_desc[code].clr();
 }
 
-int dsp_err_wdt_isset(void)
+int dsp_err_isset(enum errcode_e code)
 {
-       return (errcode & OMAP_DSP_ERRDT_WDT) ? 1 : 0;
+       return (errval & dsp_err_desc[code].val) ? 1 : 0;
 }
 
 /*
- * functions called from mailbox1 interrupt routine
+ * functions called from mailbox interrupt routine
  */
-static void mbx1_err_wdt(unsigned short data)
+static void mbx_err_wdt(u16 data)
 {
-       errcode |= OMAP_DSP_ERRDT_WDT;
-       errcnt++;
-       wdtval = data;
-       wake_up_interruptible(&err_wait_q);
+       dsp_err_set(DSP_ERR_WDT, (unsigned long)data);
 }
 
 #ifdef OLD_BINARY_SUPPORT
 /* v3.3 obsolete */
-void mbx1_wdt(struct mbcmd *mb)
+void mbx_wdt(struct mbcmd *mb)
 {
-       mbx1_err_wdt(mb->data);
+       mbx_err_wdt(mb->data);
 }
 #endif
 
-extern void mbx1_err_ipbfull(void);
-extern void mbx1_err_fatal(unsigned char tid);
+extern void mbx_err_ipbfull(void);
+extern void mbx_err_fatal(u8 tid);
 
-void mbx1_err(struct mbcmd *mb)
+void mbx_err(struct mbcmd *mb)
 {
-       unsigned char eid = mb->cmd_l;
+       u8 eid = mb->cmd_l;
        char *eidnm = subcmd_name(mb);
-       unsigned char tid;
+       u8 tid;
 
        if (eidnm) {
                printk(KERN_WARNING
@@ -173,17 +190,17 @@ void mbx1_err(struct mbcmd *mb)
        }
 
        switch (eid) {
-       case OMAP_DSP_EID_IPBFULL:
-               mbx1_err_ipbfull();
+       case EID_IPBFULL:
+               mbx_err_ipbfull();
                break;
 
-       case OMAP_DSP_EID_FATAL:
+       case EID_FATAL:
                tid = mb->data & 0x00ff;
-               mbx1_err_fatal(tid);
+               mbx_err_fatal(tid);
                break;
 
-       case OMAP_DSP_EID_WDT:
-               mbx1_err_wdt(mb->data);
+       case EID_WDT:
+               mbx_err_wdt(mb->data);
                break;
        }
 }
@@ -193,11 +210,14 @@ void mbx1_err(struct mbcmd *mb)
  */
 void dsp_err_start(void)
 {
+       enum errcode_e i;
+
+       for (i = 0; i < ERRCODE_MAX; i++) {
+               if (dsp_err_isset(i))
+                       dsp_err_clear(i);
+       }
+
        errcnt = 0;
-       if (dsp_err_wdt_isset())
-               dsp_err_wdt_clear();
-       if (dsp_err_mmu_isset())
-               dsp_err_mmu_clear();
 }
 
 void dsp_err_stop(void)
index 46fc33ccc80ae45a56170d64a07cf0abe4794e47..7fb7c1c9535a3065e94bc7634904026096f57313 100644 (file)
@@ -1,27 +1,24 @@
 /*
- * linux/arch/arm/mach-omap/dsp/fifo.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * FIFO buffer operators
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/02/24:  DSP Gateway version 3.3
  */
 
 struct fifo_struct {
@@ -53,8 +50,10 @@ static inline int init_fifo(struct fifo_struct *fifo, size_t sz)
 static inline void free_fifo(struct fifo_struct *fifo)
 {
        spin_lock(&fifo->lock);
-       if (fifo->buf == NULL)
+       if (fifo->buf == NULL) {
+               spin_unlock(&fifo->lock);
                return;
+       }
 
        kfree(fifo->buf);
        fifo->buf = NULL;
@@ -87,25 +86,17 @@ static inline int realloc_fifo(struct fifo_struct *fifo, size_t sz)
                kfree(fifo->buf);
 
        /* alloc */
-       if ((fifo->buf = kmalloc(sz, GFP_KERNEL)) == NULL) {
-               fifo->sz = 0;
-               ret = -ENOMEM;
-               goto out;
-       }
-       fifo->sz = sz;
-       fifo->cnt = 0;
-       fifo->wp = 0;
+       ret = alloc_fifo(fifo, sz);
 
 out:
        spin_unlock(&fifo->lock);
        return ret;
 }
 
-static inline void write_word_to_fifo(struct fifo_struct *fifo,
-                                     unsigned short word)
+static inline void write_word_to_fifo(struct fifo_struct *fifo, u16 word)
 {
        spin_lock(&fifo->lock);
-       *(unsigned short *)&fifo->buf[fifo->wp] = word;
+       *(u16 *)&fifo->buf[fifo->wp] = word;
        if ((fifo->wp += 2) == fifo->sz)
                fifo->wp = 0;
        if ((fifo->cnt += 2) > fifo->sz)
index 1308e5305439adc781b1e55603e7963b53855917..11efd3016904ef26821a19caa7f075c94ae17914 100644 (file)
 /*
- * linux/arch/arm/mach-omap/dsp/hardware_dsp.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * Register bit definitions for DSP driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/05/30:  DSP Gateway version 3.3
  */
 
 #ifndef __OMAP_DSP_HARDWARE_DSP_H
 #define __OMAP_DSP_HARDWARE_DSP_H
 
-#ifdef CONFIG_ARCH_OMAP15XX
-#define OMAP1510_DARAM_BASE    0xe0000000
-#define OMAP1510_DARAM_SIZE    0x10000
-#define OMAP1510_SARAM_BASE    0xe0010000
-#define OMAP1510_SARAM_SIZE    0x18000
+#ifdef CONFIG_ARCH_OMAP1
+#include "omap1_dsp.h"
 #endif
-#ifdef CONFIG_ARCH_OMAP16XX
-#define OMAP16XX_DARAM_BASE    0xe0000000
-#define OMAP16XX_DARAM_SIZE    0x10000
-#define OMAP16XX_SARAM_BASE    0xe0010000
-#define OMAP16XX_SARAM_SIZE    0x18000
+#ifdef CONFIG_ARCH_OMAP2
+#include "omap2_dsp.h"
 #endif
 
-/*
- * MAJOR device number: !! allocated arbitrary !!
- */
-#define OMAP_DSP_CTL_MAJOR             96
-#define OMAP_DSP_TASK_MAJOR            97
-
-/*
- * Reset Control
- */
-#define ARM_RSTCT1_SW_RST              0x0008
-#define ARM_RSTCT1_DSP_RST             0x0004
-#define ARM_RSTCT1_DSP_EN              0x0002
-#define ARM_RSTCT1_ARM_RST             0x0001
-
-/*
- * MPUI
- */
-#define MPUI_CTRL_WORDSWAP_MASK                0x00600000
-#define MPUI_CTRL_WORDSWAP_ALL         0x00000000
-#define MPUI_CTRL_WORDSWAP_NONAPI      0x00200000
-#define MPUI_CTRL_WORDSWAP_API         0x00400000
-#define MPUI_CTRL_WORDSWAP_NONE                0x00600000
-#define MPUI_CTRL_AP_MASK              0x001c0000
-#define MPUI_CTRL_AP_MDH               0x00000000
-#define MPUI_CTRL_AP_MHD               0x00040000
-#define MPUI_CTRL_AP_DMH               0x00080000
-#define MPUI_CTRL_AP_HMD               0x000c0000
-#define MPUI_CTRL_AP_DHM               0x00100000
-#define MPUI_CTRL_AP_HDM               0x00140000
-#define MPUI_CTRL_BYTESWAP_MASK                0x00030000
-#define MPUI_CTRL_BYTESWAP_NONE                0x00000000
-#define MPUI_CTRL_BYTESWAP_NONAPI      0x00010000
-#define MPUI_CTRL_BYTESWAP_ALL         0x00020000
-#define MPUI_CTRL_BYTESWAP_API         0x00030000
-#define MPUI_CTRL_TIMEOUT_MASK         0x0000ff00
-#define MPUI_CTRL_APIF_HNSTB_DIV_MASK  0x000000f0
-#define MPUI_CTRL_S_NABORT_GL          0x00000008
-#define MPUI_CTRL_S_NABORT_32BIT       0x00000004
-#define MPUI_CTRL_EN_TIMEOUT           0x00000002
-#define MPUI_CTRL_HF_MCUCLK            0x00000001
-#define MPUI_DSP_BOOT_CONFIG_DIRECT    0x00000000
-#define MPUI_DSP_BOOT_CONFIG_PSD_DIRECT        0x00000001
-#define MPUI_DSP_BOOT_CONFIG_IDLE      0x00000002
-#define MPUI_DSP_BOOT_CONFIG_DL16      0x00000003
-#define MPUI_DSP_BOOT_CONFIG_DL32      0x00000004
-#define MPUI_DSP_BOOT_CONFIG_MPUI      0x00000005
-#define MPUI_DSP_BOOT_CONFIG_INTERNAL  0x00000006
-
-/*
- * DSP boot mode
- *   direct:        0xffff00
- *   pseudo direct: 0x080000
- *   MPUI:          branch 0x010000
- *   internel:      branch 0x024000
- */
-#define DSP_BOOT_ADR_DIRECT            0xffff00
-#define DSP_BOOT_ADR_PSD_DIRECT                0x080000
-#define DSP_BOOT_ADR_MPUI              0x010000
-#define DSP_BOOT_ADR_INTERNAL          0x024000
-
-/*
- * TC
- */
-#define TC_ENDIANISM_SWAP              0x00000002
-#define TC_ENDIANISM_SWAP_WORD         0x00000002
-#define TC_ENDIANISM_SWAP_BYTE         0x00000000
-#define TC_ENDIANISM_EN                        0x00000001
-
-/*
- * DSP MMU
- */
-#define DSPMMU_BASE                    (0xfffed200)
-#define DSPMMU_PREFETCH                        (DSPMMU_BASE + 0x00)
-#define DSPMMU_WALKING_ST              (DSPMMU_BASE + 0x04)
-#define DSPMMU_CNTL                    (DSPMMU_BASE + 0x08)
-#define DSPMMU_FAULT_AD_H              (DSPMMU_BASE + 0x0c)
-#define DSPMMU_FAULT_AD_L              (DSPMMU_BASE + 0x10)
-#define DSPMMU_FAULT_ST                        (DSPMMU_BASE + 0x14)
-#define DSPMMU_IT_ACK                  (DSPMMU_BASE + 0x18)
-#define DSPMMU_TTB_H                   (DSPMMU_BASE + 0x1c)
-#define DSPMMU_TTB_L                   (DSPMMU_BASE + 0x20)
-#define DSPMMU_LOCK                    (DSPMMU_BASE + 0x24)
-#define DSPMMU_LD_TLB                  (DSPMMU_BASE + 0x28)
-#define DSPMMU_CAM_H                   (DSPMMU_BASE + 0x2c)
-#define DSPMMU_CAM_L                   (DSPMMU_BASE + 0x30)
-#define DSPMMU_RAM_H                   (DSPMMU_BASE + 0x34)
-#define DSPMMU_RAM_L                   (DSPMMU_BASE + 0x38)
-#define DSPMMU_GFLUSH                  (DSPMMU_BASE + 0x3c)
-#define DSPMMU_FLUSH_ENTRY             (DSPMMU_BASE + 0x40)
-#define DSPMMU_READ_CAM_H              (DSPMMU_BASE + 0x44)
-#define DSPMMU_READ_CAM_L              (DSPMMU_BASE + 0x48)
-#define DSPMMU_READ_RAM_H              (DSPMMU_BASE + 0x4c)
-#define DSPMMU_READ_RAM_L              (DSPMMU_BASE + 0x50)
-
-#define DSPMMU_CNTL_BURST_16MNGT_EN    0x0020
-#define DSPMMU_CNTL_WTL_EN             0x0004
-#define DSPMMU_CNTL_MMU_EN             0x0002
-#define DSPMMU_CNTL_RESET_SW           0x0001
-
-#define DSPMMU_FAULT_AD_H_DP           0x0100
-#define DSPMMU_FAULT_AD_H_ADR_MASK     0x00ff
-
-#define DSPMMU_FAULT_ST_PREF           0x0008
-#define DSPMMU_FAULT_ST_PERM           0x0004
-#define DSPMMU_FAULT_ST_TLB_MISS       0x0002
-#define DSPMMU_FAULT_ST_TRANS          0x0001
-
-#define DSPMMU_IT_ACK_IT_ACK           0x0001
-
-#define DSPMMU_LOCK_BASE_MASK          0xfc00
-#define DSPMMU_LOCK_BASE_SHIFT         10
-#define DSPMMU_LOCK_VICTIM_MASK                0x03f0
-#define DSPMMU_LOCK_VICTIM_SHIFT       4
-
-#define DSPMMU_CAM_H_VA_TAG_H_MASK             0x0003
-
-#define DSPMMU_CAM_L_VA_TAG_L1_MASK            0xc000
-#define DSPMMU_CAM_L_VA_TAG_L2_MASK_1MB                0x0000
-#define DSPMMU_CAM_L_VA_TAG_L2_MASK_64KB       0x3c00
-#define DSPMMU_CAM_L_VA_TAG_L2_MASK_4KB                0x3fc0
-#define DSPMMU_CAM_L_VA_TAG_L2_MASK_1KB                0x3ff0
-#define DSPMMU_CAM_L_P                         0x0008
-#define DSPMMU_CAM_L_V                         0x0004
-#define DSPMMU_CAM_L_SLST_MASK                 0x0003
-#define DSPMMU_CAM_L_SLST_1MB                  0x0000
-#define DSPMMU_CAM_L_SLST_64KB                 0x0001
-#define DSPMMU_CAM_L_SLST_4KB                  0x0002
-#define DSPMMU_CAM_L_SLST_1KB                  0x0003
-
-#define DSPMMU_RAM_L_RAM_LSB_MASK      0xfc00
-#define DSPMMU_RAM_L_AP_MASK           0x0300
-#define DSPMMU_RAM_L_AP_NA             0x0000
-#define DSPMMU_RAM_L_AP_RO             0x0200
-#define DSPMMU_RAM_L_AP_FA             0x0300
-
-#define DSPMMU_GFLUSH_GFLUSH           0x0001
-
-#define DSPMMU_FLUSH_ENTRY_FLUSH_ENTRY 0x0001
-
-#define DSPMMU_LD_TLB_RD               0x0002
-#define DSPMMU_LD_TLB_LD               0x0001
-
-/*
- * Mailbox
- */
-#define MAILBOX_BASE                   (0xfffcf000)
-#define MAILBOX_ARM2DSP1               (MAILBOX_BASE + 0x00)
-#define MAILBOX_ARM2DSP1b              (MAILBOX_BASE + 0x04)
-#define MAILBOX_DSP2ARM1               (MAILBOX_BASE + 0x08)
-#define MAILBOX_DSP2ARM1b              (MAILBOX_BASE + 0x0c)
-#define MAILBOX_DSP2ARM2               (MAILBOX_BASE + 0x10)
-#define MAILBOX_DSP2ARM2b              (MAILBOX_BASE + 0x14)
-#define MAILBOX_ARM2DSP1_Flag          (MAILBOX_BASE + 0x18)
-#define MAILBOX_DSP2ARM1_Flag          (MAILBOX_BASE + 0x1c)
-#define MAILBOX_DSP2ARM2_Flag          (MAILBOX_BASE + 0x20)
-
-/*
- * DSP ICR
- */
-#define DSPREG_ICR_RESERVED_BITS       0xffc0
-#define DSPREG_ICR_EMIF_IDLE_DOMAIN    0x0020
-#define DSPREG_ICR_DPLL_IDLE_DOMAIN    0x0010
-#define DSPREG_ICR_PER_IDLE_DOMAIN     0x0008
-#define DSPREG_ICR_CACHE_IDLE_DOMAIN   0x0004
-#define DSPREG_ICR_DMA_IDLE_DOMAIN     0x0002
-#define DSPREG_ICR_CPU_IDLE_DOMAIN     0x0001
-
 #endif /* __OMAP_DSP_HARDWARE_DSP_H */
diff --git a/arch/arm/plat-omap/dsp/ioctl.h b/arch/arm/plat-omap/dsp/ioctl.h
new file mode 100644 (file)
index 0000000..f31dbd1
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/*
+ * for /dev/dspctl/ctl
+ */
+#define DSPCTL_IOCTL_RESET             1
+#define DSPCTL_IOCTL_RUN               2
+#define DSPCTL_IOCTL_SETRSTVECT                3
+#ifdef CONFIG_ARCH_OMAP1
+#define DSPCTL_IOCTL_CPU_IDLE          4
+#define DSPCTL_IOCTL_MPUI_WORDSWAP_ON  5
+#define DSPCTL_IOCTL_MPUI_WORDSWAP_OFF 6
+#define DSPCTL_IOCTL_MPUI_BYTESWAP_ON  7
+#define DSPCTL_IOCTL_MPUI_BYTESWAP_OFF 8
+#define DSPCTL_IOCTL_GBL_IDLE          9
+#endif /* CONFIG_ARCH_OMAP1 */
+#define DSPCTL_IOCTL_DSPCFG            10
+#define DSPCTL_IOCTL_DSPUNCFG          11
+#define DSPCTL_IOCTL_TASKCNT           12
+#define DSPCTL_IOCTL_POLL              13
+#define DSPCTL_IOCTL_REGMEMR           40
+#define DSPCTL_IOCTL_REGMEMW           41
+#define DSPCTL_IOCTL_REGIOR            42
+#define DSPCTL_IOCTL_REGIOW            43
+#define DSPCTL_IOCTL_GETVAR            44
+#define DSPCTL_IOCTL_SETVAR            45
+#define DSPCTL_IOCTL_RUNLEVEL          50
+#define DSPCTL_IOCTL_SUSPEND           51
+#define DSPCTL_IOCTL_RESUME            52
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+#define DSPCTL_IOCTL_FBEN              53
+#define DSPCTL_IOCTL_FBDIS             54
+#endif /* CONFIG_OMAP_DSP_FBEXPORT */
+#define DSPCTL_IOCTL_MBSEND            99
+
+struct omap_dsp_mailbox_cmd {
+       __u16 cmd;
+       __u16 data;
+};
+
+struct omap_dsp_reginfo {
+       __u16 adr;
+       __u16 val;
+};
+
+struct omap_dsp_varinfo {
+       __u8 varid;
+       __u16 val[0];
+};
+
+/*
+ * for taskdev
+ * (ioctls below should be >= 0x10000)
+ */
+#define TASK_IOCTL_BFLSH       0x10000
+#define TASK_IOCTL_SETBSZ      0x10001
+#define TASK_IOCTL_LOCK                0x10002
+#define TASK_IOCTL_UNLOCK      0x10003
+#define TASK_IOCTL_GETNAME     0x10004
+
+/*
+ * for /dev/dspctl/mem
+ */
+#define MEM_IOCTL_EXMAP                1
+#define MEM_IOCTL_EXUNMAP      2
+#define MEM_IOCTL_EXMAP_FLUSH  3
+#define MEM_IOCTL_FBEXPORT     5
+#ifdef CONFIG_ARCH_OMAP1
+#define MEM_IOCTL_MMUITACK     7
+#endif
+#define MEM_IOCTL_MMUINIT      9
+#define MEM_IOCTL_KMEM_RESERVE 11
+#define MEM_IOCTL_KMEM_RELEASE 12
+
+struct omap_dsp_mapinfo {
+       __u32 dspadr;
+       __u32 size;
+};
+
+/*
+ * for /dev/dspctl/twch
+ */
+#define TWCH_IOCTL_MKDEV       1
+#define TWCH_IOCTL_RMDEV       2
+#define TWCH_IOCTL_TADD                11
+#define TWCH_IOCTL_TDEL                12
+#define TWCH_IOCTL_TKILL       13
+
+struct omap_dsp_taddinfo {
+       __u8 minor;
+       __u32 taskadr;
+};
+
+#define TADD_ABORTADR  0xffffffff
index ebb482b05f04d467665952fa0eabbfba44170ee2..b2c870982b6c88f41e2b456dbf44629ecddf5d0d 100644 (file)
@@ -1,57 +1,57 @@
 /*
- * linux/arch/arm/mach-omap/dsp/ipbuf.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * IPBUF handler
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/06/06:  DSP Gateway version 3.3
  */
 
-#include <linux/init.h>
 #include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
 #include <linux/device.h>
-#include <asm/signal.h>
-#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
+#include "dsp_mbcmd.h"
 #include "dsp.h"
 #include "ipbuf.h"
 
-struct ipbuf **ipbuf;
+static struct ipbuf_head *g_ipbuf;
 struct ipbcfg ipbcfg;
 struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
 static struct ipblink ipb_free = IPBLINK_INIT;
 static int ipbuf_sys_hold_mem_active;
 
+static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
+                         char *buf);
+static struct device_attribute dev_attr_ipbuf = __ATTR_RO(ipbuf);
+
 void ipbuf_stop(void)
 {
        int i;
 
+       device_remove_file(&dsp_device.dev, &dev_attr_ipbuf);
+
        spin_lock(&ipb_free.lock);
-       INIT_IPBLINK(&ipb_free);
+       RESET_IPBLINK(&ipb_free);
        spin_unlock(&ipb_free.lock);
 
        ipbcfg.ln = 0;
-       if (ipbuf) {
-               kfree(ipbuf);
-               ipbuf = NULL;
+       if (g_ipbuf) {
+               kfree(g_ipbuf);
+               g_ipbuf = NULL;
        }
        for (i = 0; i < ipbuf_sys_hold_mem_active; i++) {
                dsp_mem_disable((void *)daram_base);
@@ -59,9 +59,9 @@ void ipbuf_stop(void)
        ipbuf_sys_hold_mem_active = 0;
 }
 
-int ipbuf_config(unsigned short ln, unsigned short lsz, void *base)
+int ipbuf_config(u16 ln, u16 lsz, void *base)
 {
-       unsigned long lsz_byte = ((unsigned long)lsz) << 1;
+       size_t lsz_byte = ((size_t)lsz) << 1;
        size_t size;
        int ret = 0;
        int i;
@@ -79,8 +79,8 @@ int ipbuf_config(unsigned short ln, unsigned short lsz, void *base)
        if (dsp_address_validate(base, size, "global ipbuf") < 0)
                return -EINVAL;
 
-       ipbuf = kmalloc(sizeof(void *) * ln, GFP_KERNEL);
-       if (ipbuf == NULL) {
+       g_ipbuf = kmalloc(sizeof(struct ipbuf_head) * ln, GFP_KERNEL);
+       if (g_ipbuf == NULL) {
                printk(KERN_ERR
                       "omapdsp: memory allocation for ipbuf failed.\n");
                return -ENOMEM;
@@ -90,7 +90,8 @@ int ipbuf_config(unsigned short ln, unsigned short lsz, void *base)
 
                top = base + (sizeof(struct ipbuf) + lsz_byte) * i;
                btm = base + (sizeof(struct ipbuf) + lsz_byte) * (i+1) - 1;
-               ipbuf[i] = (struct ipbuf *)top;
+               g_ipbuf[i].p = (struct ipbuf *)top;
+               g_ipbuf[i].bid = i;
                if (((unsigned long)top & 0xfffe0000) !=
                    ((unsigned long)btm & 0xfffe0000)) {
                        /*
@@ -99,7 +100,7 @@ int ipbuf_config(unsigned short ln, unsigned short lsz, void *base)
                         */
                        printk(KERN_ERR
                               "omapdsp: ipbuf[%d] crosses 64k-word boundary!\n"
-                              "  @0x%p, size=0x%08lx\n", i, top, lsz_byte);
+                              "  @0x%p, size=0x%08x\n", i, top, lsz_byte);
                        ret = -EINVAL;
                        goto free_out;
                }
@@ -115,15 +116,17 @@ int ipbuf_config(unsigned short ln, unsigned short lsz, void *base)
               "           %d words * %d lines at 0x%p.\n",
               ipbcfg.lsz, ipbcfg.ln, ipbcfg.base);
 
+       device_create_file(&dsp_device.dev, &dev_attr_ipbuf);
+
        return ret;
 
 free_out:
-       kfree(ipbuf);
-       ipbuf = NULL;
+       kfree(g_ipbuf);
+       g_ipbuf = NULL;
        return ret;
 }
 
-int ipbuf_sys_config(void *p, enum arm_dsp_dir dir)
+int ipbuf_sys_config(void *p, enum arm_dsp_dir_e dir)
 {
        char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D";
 
@@ -158,7 +161,7 @@ int ipbuf_sys_config(void *p, enum arm_dsp_dir dir)
        return 0;
 }
 
-int ipbuf_p_validate(void *p, enum arm_dsp_dir dir)
+int ipbuf_p_validate(void *p, enum arm_dsp_dir_e dir)
 {
        char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D";
 
@@ -175,57 +178,60 @@ int ipbuf_p_validate(void *p, enum arm_dsp_dir dir)
 /*
  * Global IPBUF operations
  */
-unsigned short get_free_ipbuf(unsigned char tid)
+struct ipbuf_head *bid_to_ipbuf(u16 bid)
 {
-       unsigned short bid;
+       return &g_ipbuf[bid];
+}
+
+struct ipbuf_head *get_free_ipbuf(u8 tid)
+{
+       struct ipbuf_head *ipb_h;
 
        if (dsp_mem_enable_ipbuf() < 0)
-               return OMAP_DSP_BID_NULL;
+               return NULL;
 
        spin_lock(&ipb_free.lock);
 
        if (ipblink_empty(&ipb_free)) {
                /* FIXME: wait on queue when not available.  */
-               bid = OMAP_DSP_BID_NULL;
+               ipb_h = NULL;
                goto out;
        }
-       bid = ipb_free.top;
-       ipbuf[bid]->la = tid;   /* lock */
-       ipblink_del_top(&ipb_free, ipbuf);
+       ipb_h = &g_ipbuf[ipb_free.top];
+       ipb_h->p->la = tid;     /* lock */
+       __ipblink_del_top(&ipb_free);
 out:
        spin_unlock(&ipb_free.lock);
        dsp_mem_disable_ipbuf();
 
-       return bid;
+       return ipb_h;
 }
 
-void release_ipbuf(unsigned short bid)
+void release_ipbuf(struct ipbuf_head *ipb_h)
 {
-       if (ipbuf[bid]->la == OMAP_DSP_TID_FREE) {
+       if (ipb_h->p->la == TID_FREE) {
                printk(KERN_WARNING
                       "omapdsp: attempt to release unlocked IPBUF[%d].\n",
-                      bid);
+                      ipb_h->bid);
                /*
                 * FIXME: re-calc bsycnt
                 */
                return;
        }
-       ipbuf[bid]->la = OMAP_DSP_TID_FREE;
-       ipbuf[bid]->sa = OMAP_DSP_TID_FREE;
-       spin_lock(&ipb_free.lock);
-       ipblink_add_tail(&ipb_free, bid, ipbuf);
-       spin_unlock(&ipb_free.lock);
+       ipb_h->p->la = TID_FREE;
+       ipb_h->p->sa = TID_FREE;
+       ipblink_add_tail(&ipb_free, ipb_h->bid);
 }
 
-static int try_yld(unsigned short bid)
+static int try_yld(struct ipbuf_head *ipb_h)
 {
        int status;
 
-       ipbuf[bid]->sa = OMAP_DSP_TID_ANON;
-       status = dsp_mbsend(MBCMD(BKYLD), 0, bid);
+       ipb_h->p->sa = TID_ANON;
+       status = mbcompose_send(BKYLD, 0, ipb_h->bid);
        if (status < 0) {
                /* DSP is busy and ARM keeps this line. */
-               release_ipbuf(bid);
+               release_ipbuf(ipb_h);
                return status;
        }
 
@@ -239,12 +245,11 @@ static int try_yld(unsigned short bid)
 static void do_balance_ipbuf(void)
 {
        while (ipbcfg.bsycnt <= ipbcfg.ln / 4) {
-               unsigned short bid;
+               struct ipbuf_head *ipb_h;
 
-               bid = get_free_ipbuf(OMAP_DSP_TID_ANON);
-               if (bid == OMAP_DSP_BID_NULL)
+               if ((ipb_h = get_free_ipbuf(TID_ANON)) == NULL)
                        return;
-               if (try_yld(bid) < 0)
+               if (try_yld(ipb_h) < 0)
                        return;
        }
 }
@@ -258,31 +263,31 @@ void balance_ipbuf(void)
 }
 
 /* for process context */
-void unuse_ipbuf(unsigned short bid)
+void unuse_ipbuf(struct ipbuf_head *ipb_h)
 {
        if (ipbcfg.bsycnt > ipbcfg.ln / 4) {
                /* we don't have enough IPBUF lines. let's keep it. */
-               release_ipbuf(bid);
+               release_ipbuf(ipb_h);
        } else {
                /* we have enough IPBUF lines. let's return this line to DSP. */
-               ipbuf[bid]->la = OMAP_DSP_TID_ANON;
-               try_yld(bid);
+               ipb_h->p->la = TID_ANON;
+               try_yld(ipb_h);
                balance_ipbuf();
        }
 }
 
 /* for interrupt context */
-void unuse_ipbuf_nowait(unsigned short bid)
+void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h)
 {
-       release_ipbuf(bid);
+       release_ipbuf(ipb_h);
        balance_ipbuf();
 }
 
 /*
- * functions called from mailbox1 interrupt routine
+ * functions called from mailbox interrupt routine
  */
 
-void mbx1_err_ipbfull(void)
+void mbx_err_ipbfull(void)
 {
        ipbcfg.cnt_full++;
 }
@@ -294,12 +299,13 @@ static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
                          char *buf)
 {
        int len = 0;
-       unsigned short bid;
+       u16 bid;
 
        for (bid = 0; bid < ipbcfg.ln; bid++) {
-               unsigned short la = ipbuf[bid]->la;
-               unsigned short ld = ipbuf[bid]->ld;
-               unsigned short c  = ipbuf[bid]->c;
+               struct ipbuf_head *ipb_h = &g_ipbuf[bid];
+               u16 la = ipb_h->p->la;
+               u16 ld = ipb_h->p->ld;
+               u16 c  = ipb_h->p->c;
 
                if (len > PAGE_SIZE - 100) {
                        len += sprintf(buf + len, "out of buffer.\n");
@@ -307,13 +313,13 @@ static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
                }
 
                len += sprintf(buf + len, "ipbuf[%d]: adr = 0x%p\n",
-                              bid, ipbuf[bid]);
-               if (la == OMAP_DSP_TID_FREE) {
+                              bid, ipb_h->p);
+               if (la == TID_FREE) {
                        len += sprintf(buf + len,
                                       "  DSPtask[%d]->Linux "
                                       "(already read and now free for Linux)\n",
                                       ld);
-               } else if (ld == OMAP_DSP_TID_FREE) {
+               } else if (ld == TID_FREE) {
                        len += sprintf(buf + len,
                                       "  Linux->DSPtask[%d] "
                                       "(already read and now free for DSP)\n",
@@ -333,7 +339,7 @@ static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
 
        len += sprintf(buf + len, "\nFree IPBUF link: ");
        spin_lock(&ipb_free.lock);
-       ipblink_for_each(bid, &ipb_free, ipbuf) {
+       ipblink_for_each(bid, &ipb_free) {
                len += sprintf(buf + len, "%d ", bid);
        }
        spin_unlock(&ipb_free.lock);
@@ -344,5 +350,3 @@ static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
 finish:
        return len;
 }
-
-struct device_attribute dev_attr_ipbuf = __ATTR_RO(ipbuf);
index 77826f443d2cda5482c85f2529e52956a4d9b271..9a6e3db103cd034ae6b34befc7db1ef8c9a17189 100644 (file)
@@ -1,75 +1,78 @@
 /*
- * linux/arch/arm/mach-omap/dsp/ipbuf.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * Header for IPBUF
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/05/17:  DSP Gateway version 3.3
  */
 
 struct ipbuf {
-       unsigned short c;       /* count */
-       unsigned short next;    /* link */
-       unsigned short la;      /* lock owner (ARM side) */
-       unsigned short sa;      /* sync word (ARM->DSP) */
-       unsigned short ld;      /* lock owner (DSP side) */
-       unsigned short sd;      /* sync word (DSP->ARM) */
+       u16 c;                  /* count */
+       u16 next;               /* link */
+       u16 la;                 /* lock owner (ARM side) */
+       u16 sa;                 /* sync word (ARM->DSP) */
+       u16 ld;                 /* lock owner (DSP side) */
+       u16 sd;                 /* sync word (DSP->ARM) */
        unsigned char d[0];     /* data */
 };
 
 struct ipbuf_p {
-       unsigned short c;       /* count */
-       unsigned short s;       /* sync word */
-       unsigned short al;      /* data address lower */
-       unsigned short ah;      /* data address upper */
+       u16 c;          /* count */
+       u16 s;          /* sync word */
+       u16 al;         /* data address lower */
+       u16 ah;         /* data address upper */
 };
 
+#define IPBUF_SYS_DLEN 31
+
 struct ipbuf_sys {
-       unsigned short s;       /* sync word */
-       unsigned short d[31];   /* data */
+       u16 s;                  /* sync word */
+       u16 d[IPBUF_SYS_DLEN];  /* data */
 };
 
 struct ipbcfg {
-       unsigned short ln;
-       unsigned short lsz;
+       u16 ln;
+       u16 lsz;
        void *base;
-       unsigned short bsycnt;
+       u16 bsycnt;
        unsigned long cnt_full; /* count of IPBFULL error */
 };
 
-extern struct ipbuf **ipbuf;
+struct ipbuf_head {
+       u16 bid;
+       struct ipbuf *p;
+};
+
 extern struct ipbcfg ipbcfg;
 extern struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
 
 #define ipb_bsycnt_inc(ipbcfg) \
        do { \
-               disable_irq(INT_D2A_MB1); \
+               disable_mbx_irq(mbx_dsp); \
                (ipbcfg)->bsycnt++; \
-               enable_irq(INT_D2A_MB1); \
+               enable_mbx_irq(mbx_dsp); \
        } while(0)
 
 #define ipb_bsycnt_dec(ipbcfg) \
        do { \
-               disable_irq(INT_D2A_MB1); \
+               disable_mbx_irq(mbx_dsp); \
                (ipbcfg)->bsycnt--; \
-               enable_irq(INT_D2A_MB1); \
+               enable_mbx_irq(mbx_dsp); \
        } while(0)
 
 #define dsp_mem_enable_ipbuf() dsp_mem_enable(ipbcfg.base)
@@ -77,58 +80,120 @@ extern struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
 
 struct ipblink {
        spinlock_t lock;
-       unsigned short top;
-       unsigned short tail;
+       u16 top;
+       u16 tail;
 };
 
 #define IPBLINK_INIT { \
                .lock = SPIN_LOCK_UNLOCKED, \
-               .top  = OMAP_DSP_BID_NULL, \
-               .tail = OMAP_DSP_BID_NULL, \
+               .top  = BID_NULL, \
+               .tail = BID_NULL, \
        }
 
 #define INIT_IPBLINK(link) \
        do { \
                spin_lock_init(&(link)->lock); \
-               (link)->top  = OMAP_DSP_BID_NULL; \
-               (link)->tail = OMAP_DSP_BID_NULL; \
+               (link)->top  = BID_NULL; \
+               (link)->tail = BID_NULL; \
        } while(0)
 
-#define ipblink_empty(link)    ((link)->top == OMAP_DSP_BID_NULL)
+#define RESET_IPBLINK(link) \
+       do { \
+               (link)->top  = BID_NULL; \
+               (link)->tail = BID_NULL; \
+       } while(0)
+
+#define ipblink_empty(link)    ((link)->top == BID_NULL)
 
-static __inline__ void ipblink_del_top(struct ipblink *link,
-                                      struct ipbuf **ipbuf)
+static __inline__ void __ipblink_del_top(struct ipblink *link)
 {
-       struct ipbuf *bufp = ipbuf[link->top];
+       struct ipbuf_head *ipb_h = bid_to_ipbuf(link->top);
 
-       if ((link->top = bufp->next) == OMAP_DSP_BID_NULL)
-               link->tail = OMAP_DSP_BID_NULL;
+       if ((link->top = ipb_h->p->next) == BID_NULL)
+               link->tail = BID_NULL;
        else
-               bufp->next = OMAP_DSP_BID_NULL;
+               ipb_h->p->next = BID_NULL;
 }
 
-static __inline__ void ipblink_add_tail(struct ipblink *link,
-                                       unsigned short bid,
-                                       struct ipbuf **ipbuf)
+static __inline__ void ipblink_del_top(struct ipblink *link)
+{
+       spin_lock(&link->lock);
+       __ipblink_del_top(link);
+       spin_unlock(&link->lock);
+}
+
+static __inline__ void __ipblink_add_tail(struct ipblink *link, u16 bid)
 {
        if (ipblink_empty(link))
                link->top = bid;
        else
-               ipbuf[link->tail]->next = bid;
+               bid_to_ipbuf(link->tail)->p->next = bid;
        link->tail = bid;
 }
 
+static __inline__ void ipblink_add_tail(struct ipblink *link, u16 bid)
+{
+       spin_lock(&link->lock);
+       __ipblink_add_tail(link, bid);
+       spin_unlock(&link->lock);
+}
+
+static __inline__ void __ipblink_flush(struct ipblink *link)
+{
+       u16 bid;
+
+       while (!ipblink_empty(link)) {
+               bid = link->top;
+               __ipblink_del_top(link);
+               unuse_ipbuf(bid_to_ipbuf(bid));
+       }
+}
+
+static __inline__ void ipblink_flush(struct ipblink *link)
+{
+       spin_lock(&link->lock);
+       __ipblink_flush(link);
+       spin_unlock(&link->lock);
+}
+
+static __inline__ void __ipblink_add_pvt(struct ipblink *link)
+{
+       link->top  = BID_PVT;
+       link->tail = BID_PVT;
+}
+
 static __inline__ void ipblink_add_pvt(struct ipblink *link)
 {
-       link->top  = OMAP_DSP_BID_PVT;
-       link->tail = OMAP_DSP_BID_PVT;
+       spin_lock(&link->lock);
+       __ipblink_add_pvt(link);
+       spin_unlock(&link->lock);
+}
+
+static __inline__ void __ipblink_del_pvt(struct ipblink *link)
+{
+       link->top  = BID_NULL;
+       link->tail = BID_NULL;
 }
 
 static __inline__ void ipblink_del_pvt(struct ipblink *link)
 {
-       link->top  = OMAP_DSP_BID_NULL;
-       link->tail = OMAP_DSP_BID_NULL;
+       spin_lock(&link->lock);
+       __ipblink_del_pvt(link);
+       spin_unlock(&link->lock);
+}
+
+static __inline__ void __ipblink_flush_pvt(struct ipblink *link)
+{
+       if (!ipblink_empty(link))
+               ipblink_del_pvt(link);
+}
+
+static __inline__ void ipblink_flush_pvt(struct ipblink *link)
+{
+       spin_lock(&link->lock);
+       __ipblink_flush_pvt(link);
+       spin_unlock(&link->lock);
 }
 
-#define ipblink_for_each(bid, link, ipbuf) \
-       for (bid = (link)->top; bid != OMAP_DSP_BID_NULL; bid = ipbuf[bid]->next)
+#define ipblink_for_each(bid, link) \
+       for (bid = (link)->top; bid != BID_NULL; bid = bid_to_ipbuf(bid)->p->next)
index 3298976602028ee7cc779d5145510783464c3487..4a4152dc9290d63818f5f3c8ebae420f9d4c7f5e 100644 (file)
 /*
- * linux/arch/arm/mach-omap/dsp/mblog.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * OMAP DSP driver Mailbox log module
+ * Copyright (C) 2003-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2003-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/05/18:  DSP Gateway version 3.3
  */
 
-#include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
-#include <asm/irq.h>
-#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
+#include "dsp_mbcmd.h"
 #include "dsp.h"
 
-#define RLCMD(nm)      OMAP_DSP_MBCMD_RUNLEVEL_##nm
-#define KFUNCCMD(nm)   OMAP_DSP_MBCMD_KFUNC_##nm
-#define PMCMD(nm)      OMAP_DSP_MBCMD_PM_##nm
-#define CFGCMD(nm)     OMAP_DSP_MBCMD_DSPCFG_##nm
-#define REGCMD(nm)     OMAP_DSP_MBCMD_REGRW_##nm
-#define VICMD(nm)      OMAP_DSP_MBCMD_VARID_##nm
-#define EID(nm)                OMAP_DSP_EID_##nm
-
 char *subcmd_name(struct mbcmd *mb)
 {
-       unsigned char cmd_h = mb->cmd_h;
-       unsigned char cmd_l = mb->cmd_l;
+       u8 cmd_h = mb->cmd_h;
+       u8 cmd_l = mb->cmd_l;
        char *s;
 
        switch (cmd_h) {
-       case MBCMD(RUNLEVEL):
-               s = (cmd_l == RLCMD(USER))     ? "USER":
-                   (cmd_l == RLCMD(SUPER))    ? "SUPER":
-                   (cmd_l == RLCMD(RECOVERY)) ? "RECOVERY":
+       case MBX_CMD_DSP_RUNLEVEL:
+               s = (cmd_l == RUNLEVEL_USER)     ? "USER":
+                   (cmd_l == RUNLEVEL_SUPER)    ? "SUPER":
+                   (cmd_l == RUNLEVEL_RECOVERY) ? "RECOVERY":
                    NULL;
                break;
-       case MBCMD(PM):
-               s = (cmd_l == PMCMD(DISABLE)) ? "DISABLE":
-                   (cmd_l == PMCMD(ENABLE))  ? "ENABLE":
+       case MBX_CMD_DSP_PM:
+               s = (cmd_l == PM_DISABLE) ? "DISABLE":
+                   (cmd_l == PM_ENABLE)  ? "ENABLE":
                    NULL;
                break;
-       case MBCMD(KFUNC):
-               s = (cmd_l == KFUNCCMD(FBCTL))     ? "FBCTL":
-                   (cmd_l == KFUNCCMD(AUDIO_PWR)) ? "AUDIO_PWR":
+       case MBX_CMD_DSP_KFUNC:
+               s = (cmd_l == KFUNC_FBCTL) ? "FBCTL":
                    NULL;
                break;
-       case MBCMD(DSPCFG):
+       case MBX_CMD_DSP_DSPCFG:
                {
-                       unsigned char cfgc = cmd_l & 0x7f;
-                       s = (cfgc == CFGCMD(REQ))     ? "REQ":
-                           (cfgc == CFGCMD(SYSADRH)) ? "SYSADRH":
-                           (cfgc == CFGCMD(SYSADRL)) ? "SYSADRL":
-                           (cfgc == CFGCMD(ABORT))   ? "ABORT":
-                           (cfgc == CFGCMD(PROTREV)) ? "PROTREV":
+                       u8 cfgc = cmd_l & 0x7f;
+                       s = (cfgc == DSPCFG_REQ)     ? "REQ":
+                           (cfgc == DSPCFG_SYSADRH) ? "SYSADRH":
+                           (cfgc == DSPCFG_SYSADRL) ? "SYSADRL":
+                           (cfgc == DSPCFG_ABORT)   ? "ABORT":
+                           (cfgc == DSPCFG_PROTREV) ? "PROTREV":
                            NULL;
                        break;
                }
-       case MBCMD(REGRW):
-               s = (cmd_l == REGCMD(MEMR)) ? "MEMR":
-                   (cmd_l == REGCMD(MEMW)) ? "MEMW":
-                   (cmd_l == REGCMD(IOR))  ? "IOR":
-                   (cmd_l == REGCMD(IOW))  ? "IOW":
-                   (cmd_l == REGCMD(DATA)) ? "DATA":
+       case MBX_CMD_DSP_REGRW:
+               s = (cmd_l == REGRW_MEMR) ? "MEMR":
+                   (cmd_l == REGRW_MEMW) ? "MEMW":
+                   (cmd_l == REGRW_IOR)  ? "IOR":
+                   (cmd_l == REGRW_IOW)  ? "IOW":
+                   (cmd_l == REGRW_DATA) ? "DATA":
                    NULL;
                break;
-       case MBCMD(GETVAR):
-       case MBCMD(SETVAR):
-               s = (cmd_l == VICMD(ICRMASK))  ? "ICRMASK":
-                   (cmd_l == VICMD(LOADINFO)) ? "LOADINFO":
+       case MBX_CMD_DSP_GETVAR:
+       case MBX_CMD_DSP_SETVAR:
+               s = (cmd_l == VARID_ICRMASK)  ? "ICRMASK":
+                   (cmd_l == VARID_LOADINFO) ? "LOADINFO":
                    NULL;
                break;
-       case MBCMD(ERR):
-               s = (cmd_l == EID(BADTID))     ? "BADTID":
-                   (cmd_l == EID(BADTCN))     ? "BADTCN":
-                   (cmd_l == EID(BADBID))     ? "BADBID":
-                   (cmd_l == EID(BADCNT))     ? "BADCNT":
-                   (cmd_l == EID(NOTLOCKED))  ? "NOTLOCKED":
-                   (cmd_l == EID(STVBUF))     ? "STVBUF":
-                   (cmd_l == EID(BADADR))     ? "BADADR":
-                   (cmd_l == EID(BADTCTL))    ? "BADTCTL":
-                   (cmd_l == EID(BADPARAM))   ? "BADPARAM":
-                   (cmd_l == EID(FATAL))      ? "FATAL":
-                   (cmd_l == EID(WDT))        ? "WDT":
-                   (cmd_l == EID(NOMEM))      ? "NOMEM":
-                   (cmd_l == EID(NORES))      ? "NORES":
-                   (cmd_l == EID(IPBFULL))    ? "IPBFULL":
-                   (cmd_l == EID(TASKNOTRDY)) ? "TASKNOTRDY":
-                   (cmd_l == EID(TASKBSY))    ? "TASKBSY":
-                   (cmd_l == EID(TASKERR))    ? "TASKERR":
-                   (cmd_l == EID(BADCFGTYP))  ? "BADCFGTYP":
-                   (cmd_l == EID(DEBUG))      ? "DEBUG":
-                   (cmd_l == EID(BADSEQ))     ? "BADSEQ":
-                   (cmd_l == EID(BADCMD))     ? "BADCMD":
+       case MBX_CMD_DSP_ERR:
+               s = (cmd_l == EID_BADTID)     ? "BADTID":
+                   (cmd_l == EID_BADTCN)     ? "BADTCN":
+                   (cmd_l == EID_BADBID)     ? "BADBID":
+                   (cmd_l == EID_BADCNT)     ? "BADCNT":
+                   (cmd_l == EID_NOTLOCKED)  ? "NOTLOCKED":
+                   (cmd_l == EID_STVBUF)     ? "STVBUF":
+                   (cmd_l == EID_BADADR)     ? "BADADR":
+                   (cmd_l == EID_BADTCTL)    ? "BADTCTL":
+                   (cmd_l == EID_BADPARAM)   ? "BADPARAM":
+                   (cmd_l == EID_FATAL)      ? "FATAL":
+                   (cmd_l == EID_WDT)        ? "WDT":
+                   (cmd_l == EID_NOMEM)      ? "NOMEM":
+                   (cmd_l == EID_NORES)      ? "NORES":
+                   (cmd_l == EID_IPBFULL)    ? "IPBFULL":
+                   (cmd_l == EID_TASKNOTRDY) ? "TASKNOTRDY":
+                   (cmd_l == EID_TASKBSY)    ? "TASKBSY":
+                   (cmd_l == EID_TASKERR)    ? "TASKERR":
+                   (cmd_l == EID_BADCFGTYP)  ? "BADCFGTYP":
+                   (cmd_l == EID_DEBUG)      ? "DEBUG":
+                   (cmd_l == EID_BADSEQ)     ? "BADSEQ":
+                   (cmd_l == EID_BADCMD)     ? "BADCMD":
                    NULL;
                break;
        default:
@@ -124,9 +110,8 @@ char *subcmd_name(struct mbcmd *mb)
 
 struct mblogent {
        unsigned long jiffies;
-       unsigned short cmd;
-       unsigned short data;
-       enum arm_dsp_dir dir;
+       mbx_msg_t msg;
+       enum arm_dsp_dir_e dir;
 };
 
 static struct {
@@ -134,19 +119,19 @@ static struct {
        int wp;
        unsigned long cnt, cnt_ad, cnt_da;
        struct mblogent ent[MBLOG_DEPTH];
-} mblog;
+} mblog = {
+       .lock = SPIN_LOCK_UNLOCKED,
+};
 
-void mblog_add(struct mbcmd *mb, enum arm_dsp_dir dir)
+void mblog_add(struct mbcmd *mb, enum arm_dsp_dir_e dir)
 {
-       struct mbcmd_hw *mb_hw = (struct mbcmd_hw *)mb;
        struct mblogent *ent;
 
        spin_lock(&mblog.lock);
        ent = &mblog.ent[mblog.wp];
        ent->jiffies = jiffies;
-       ent->cmd     = mb_hw->cmd;
-       ent->data    = mb_hw->data;
-       ent->dir     = dir;
+       ent->msg = *(mbx_msg_t *)mb;
+       ent->dir = dir;
        if (mblog.cnt < 0xffffffff)
                mblog.cnt++;
        switch (dir) {
@@ -183,36 +168,39 @@ static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
        if (mblog.cnt == 0)
                goto done;
 
-       len += sprintf(buf + len, "          ARM -> DSP   ARM <- DSP\n");
-       len += sprintf(buf + len, "jiffies  q cmd  data q cmd  data\n");
+       len += sprintf(buf + len, "           ARM->DSP   ARM<-DSP\n");
+       len += sprintf(buf + len, " jiffies  cmd  data  cmd  data\n");
        i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0;
        do {
                struct mblogent *ent = &mblog.ent[i];
-               union {
-                       struct mbcmd sw;
-                       struct mbcmd_hw hw;
-               } mb = {
-                       .hw.cmd  = ent->cmd,
-                       .hw.data = ent->data
-               };
+               struct mbcmd *mb = (struct mbcmd *)&ent->msg;
                char *subname;
-               const struct cmdinfo *ci = cmdinfo[mb.sw.cmd_h];
+               struct cmdinfo ci_null = {
+                       .name = "Unknown",
+                       .cmd_l_type = CMD_L_TYPE_NULL,
+               };
+               const struct cmdinfo *ci;
 
                len += sprintf(buf + len,
                               (ent->dir == DIR_A2D) ?
-                               "%08lx %d %04x %04x             ":
-                               "%08lx             %d %04x %04x ",
-                              ent->jiffies, mb.sw.seq, ent->cmd, ent->data);
+                               "%08lx  %04x %04x            ":
+                               "%08lx             %04x %04x ",
+                              ent->jiffies,
+                              (ent->msg >> 16) & 0x7fff, ent->msg & 0xffff);
+
+               if ((ci = cmdinfo[mb->cmd_h]) == NULL)
+                       ci = &ci_null;
+
                switch (ci->cmd_l_type) {
                case CMD_L_TYPE_SUBCMD:
-                       if ((subname = subcmd_name(&mb.sw)) == NULL)
+                       if ((subname = subcmd_name(mb)) == NULL)
                                subname = "Unknown";
                        len += sprintf(buf + len, "%s:%s\n",
                                       ci->name, subname);
                        break;
                case CMD_L_TYPE_TID:
                        len += sprintf(buf + len, "%s:task %d\n",
-                                      ci->name, mb.sw.cmd_l);
+                                      ci->name, mb->cmd_l);
                        break;
                case CMD_L_TYPE_NULL:
                        len += sprintf(buf + len, "%s\n", ci->name);
@@ -232,33 +220,40 @@ done:
 static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
 
 #ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
-void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir dir)
+void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir_e dir)
 {
-       const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
+       struct cmdinfo ci_null = {
+               .name = "Unknown",
+               .cmd_l_type = CMD_L_TYPE_NULL,
+       };
+       const struct cmdinfo *ci;
        char *dir_str;
        char *subname;
 
        dir_str = (dir == DIR_A2D) ? "sending" : "receiving";
+
+       if ((ci = cmdinfo[mb->cmd_h]) == NULL)
+               ci = &ci_null;
+
        switch (ci->cmd_l_type) {
        case CMD_L_TYPE_SUBCMD:
                if ((subname = subcmd_name(mb)) == NULL)
                        subname = "Unknown";
                printk(KERN_DEBUG
-                      "mbx: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n",
-                      dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
+                      "mbx: %s cmd=%02x:%02x(%s:%s), data=%04x\n",
+                      dir_str, mb->cmd_h, mb->cmd_l,
                       ci->name, subname, mb->data);
                break;
        case CMD_L_TYPE_TID:
                printk(KERN_DEBUG
-                      "mbx: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n",
-                      dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
+                      "mbx: %s cmd=%02x:%02x(%s:task %d), data=%04x\n",
+                      dir_str, mb->cmd_h, mb->cmd_l,
                       ci->name, mb->cmd_l, mb->data);
                break;
        case CMD_L_TYPE_NULL:
                printk(KERN_DEBUG
-                      "mbx: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n",
-                      dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
-                      ci->name, mb->data);
+                      "mbx: %s cmd=%02x:%02x(%s), data=%04x\n",
+                      dir_str, mb->cmd_h, mb->cmd_l, ci->name, mb->data);
                break;
        }
 }
@@ -266,7 +261,6 @@ void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir dir)
 
 void __init mblog_init(void)
 {
-       spin_lock_init(&mblog.lock);
        device_create_file(&dsp_device.dev, &dev_attr_mblog);
 }
 
diff --git a/arch/arm/plat-omap/dsp/omap1_dsp.h b/arch/arm/plat-omap/dsp/omap1_dsp.h
new file mode 100644 (file)
index 0000000..06a66fa
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_DSP_OMAP1_DSP_H
+#define __OMAP_DSP_OMAP1_DSP_H
+
+#ifdef CONFIG_ARCH_OMAP15XX
+#define OMAP1510_DARAM_BASE    (OMAP1510_DSP_BASE + 0x0)
+#define OMAP1510_DARAM_SIZE    0x10000
+#define OMAP1510_SARAM_BASE    (OMAP1510_DSP_BASE + 0x10000)
+#define OMAP1510_SARAM_SIZE    0x18000
+#endif
+
+#ifdef CONFIG_ARCH_OMAP16XX
+#define OMAP16XX_DARAM_BASE    (OMAP16XX_DSP_BASE + 0x0)
+#define OMAP16XX_DARAM_SIZE    0x10000
+#define OMAP16XX_SARAM_BASE    (OMAP16XX_DSP_BASE + 0x10000)
+#define OMAP16XX_SARAM_SIZE    0x18000
+#endif
+
+/*
+ * Reset Control
+ */
+#define ARM_RSTCT1_SW_RST              0x0008
+#define ARM_RSTCT1_DSP_RST             0x0004
+#define ARM_RSTCT1_DSP_EN              0x0002
+#define ARM_RSTCT1_ARM_RST             0x0001
+
+/*
+ * MPUI
+ */
+#define MPUI_CTRL_WORDSWAP_MASK                0x00600000
+#define MPUI_CTRL_WORDSWAP_ALL         0x00000000
+#define MPUI_CTRL_WORDSWAP_NONAPI      0x00200000
+#define MPUI_CTRL_WORDSWAP_API         0x00400000
+#define MPUI_CTRL_WORDSWAP_NONE                0x00600000
+#define MPUI_CTRL_AP_MASK              0x001c0000
+#define MPUI_CTRL_AP_MDH               0x00000000
+#define MPUI_CTRL_AP_MHD               0x00040000
+#define MPUI_CTRL_AP_DMH               0x00080000
+#define MPUI_CTRL_AP_HMD               0x000c0000
+#define MPUI_CTRL_AP_DHM               0x00100000
+#define MPUI_CTRL_AP_HDM               0x00140000
+#define MPUI_CTRL_BYTESWAP_MASK                0x00030000
+#define MPUI_CTRL_BYTESWAP_NONE                0x00000000
+#define MPUI_CTRL_BYTESWAP_NONAPI      0x00010000
+#define MPUI_CTRL_BYTESWAP_ALL         0x00020000
+#define MPUI_CTRL_BYTESWAP_API         0x00030000
+#define MPUI_CTRL_TIMEOUT_MASK         0x0000ff00
+#define MPUI_CTRL_APIF_HNSTB_DIV_MASK  0x000000f0
+#define MPUI_CTRL_S_NABORT_GL          0x00000008
+#define MPUI_CTRL_S_NABORT_32BIT       0x00000004
+#define MPUI_CTRL_EN_TIMEOUT           0x00000002
+#define MPUI_CTRL_HF_MCUCLK            0x00000001
+#define DSP_BOOT_CONFIG_DIRECT         0x00000000
+#define DSP_BOOT_CONFIG_PSD_DIRECT     0x00000001
+#define DSP_BOOT_CONFIG_IDLE           0x00000002
+#define DSP_BOOT_CONFIG_DL16           0x00000003
+#define DSP_BOOT_CONFIG_DL32           0x00000004
+#define DSP_BOOT_CONFIG_MPUI           0x00000005
+#define DSP_BOOT_CONFIG_INTERNAL       0x00000006
+
+/*
+ * DSP boot mode
+ *   direct:        0xffff00
+ *   pseudo direct: 0x080000
+ *   MPUI:          branch 0x010000
+ *   internel:      branch 0x024000
+ */
+#define DSP_BOOT_ADR_DIRECT            0xffff00
+#define DSP_BOOT_ADR_PSD_DIRECT                0x080000
+#define DSP_BOOT_ADR_MPUI              0x010000
+#define DSP_BOOT_ADR_INTERNAL          0x024000
+
+/*
+ * TC
+ */
+#define TC_ENDIANISM_SWAP              0x00000002
+#define TC_ENDIANISM_SWAP_WORD         0x00000002
+#define TC_ENDIANISM_SWAP_BYTE         0x00000000
+#define TC_ENDIANISM_EN                        0x00000001
+
+/*
+ * DSP MMU
+ */
+#define DSP_MMU_BASE                   (0xfffed200)
+#define DSP_MMU_PREFETCH               (DSP_MMU_BASE + 0x00)
+#define DSP_MMU_WALKING_ST             (DSP_MMU_BASE + 0x04)
+#define DSP_MMU_CNTL                   (DSP_MMU_BASE + 0x08)
+#define DSP_MMU_FAULT_AD_H             (DSP_MMU_BASE + 0x0c)
+#define DSP_MMU_FAULT_AD_L             (DSP_MMU_BASE + 0x10)
+#define DSP_MMU_FAULT_ST               (DSP_MMU_BASE + 0x14)
+#define DSP_MMU_IT_ACK                 (DSP_MMU_BASE + 0x18)
+#define DSP_MMU_TTB_H                  (DSP_MMU_BASE + 0x1c)
+#define DSP_MMU_TTB_L                  (DSP_MMU_BASE + 0x20)
+#define DSP_MMU_LOCK                   (DSP_MMU_BASE + 0x24)
+#define DSP_MMU_LD_TLB                 (DSP_MMU_BASE + 0x28)
+#define DSP_MMU_CAM_H                  (DSP_MMU_BASE + 0x2c)
+#define DSP_MMU_CAM_L                  (DSP_MMU_BASE + 0x30)
+#define DSP_MMU_RAM_H                  (DSP_MMU_BASE + 0x34)
+#define DSP_MMU_RAM_L                  (DSP_MMU_BASE + 0x38)
+#define DSP_MMU_GFLUSH                 (DSP_MMU_BASE + 0x3c)
+#define DSP_MMU_FLUSH_ENTRY            (DSP_MMU_BASE + 0x40)
+#define DSP_MMU_READ_CAM_H             (DSP_MMU_BASE + 0x44)
+#define DSP_MMU_READ_CAM_L             (DSP_MMU_BASE + 0x48)
+#define DSP_MMU_READ_RAM_H             (DSP_MMU_BASE + 0x4c)
+#define DSP_MMU_READ_RAM_L             (DSP_MMU_BASE + 0x50)
+
+#define DSP_MMU_CNTL_BURST_16MNGT_EN   0x0020
+#define DSP_MMU_CNTL_WTL_EN            0x0004
+#define DSP_MMU_CNTL_MMU_EN            0x0002
+#define DSP_MMU_CNTL_RESET_SW          0x0001
+
+#define DSP_MMU_FAULT_AD_H_DP          0x0100
+#define DSP_MMU_FAULT_AD_H_ADR_MASK    0x00ff
+
+#define DSP_MMU_FAULT_ST_PREF          0x0008
+#define DSP_MMU_FAULT_ST_PERM          0x0004
+#define DSP_MMU_FAULT_ST_TLB_MISS      0x0002
+#define DSP_MMU_FAULT_ST_TRANS         0x0001
+
+#define DSP_MMU_IT_ACK_IT_ACK          0x0001
+
+#define DSP_MMU_LOCK_BASE_MASK         0xfc00
+#define DSP_MMU_LOCK_BASE_SHIFT                10
+#define DSP_MMU_LOCK_VICTIM_MASK       0x03f0
+#define DSP_MMU_LOCK_VICTIM_SHIFT      4
+
+#define DSP_MMU_CAM_H_VA_TAG_H_MASK            0x0003
+
+#define DSP_MMU_CAM_L_VA_TAG_L1_MASK           0xc000
+#define DSP_MMU_CAM_L_VA_TAG_L2_MASK_1MB       0x0000
+#define DSP_MMU_CAM_L_VA_TAG_L2_MASK_64KB      0x3c00
+#define DSP_MMU_CAM_L_VA_TAG_L2_MASK_4KB       0x3fc0
+#define DSP_MMU_CAM_L_VA_TAG_L2_MASK_1KB       0x3ff0
+#define DSP_MMU_CAM_L_P                                0x0008
+#define DSP_MMU_CAM_L_V                                0x0004
+#define DSP_MMU_CAM_L_PAGESIZE_MASK            0x0003
+#define DSP_MMU_CAM_L_PAGESIZE_1MB             0x0000
+#define DSP_MMU_CAM_L_PAGESIZE_64KB            0x0001
+#define DSP_MMU_CAM_L_PAGESIZE_4KB             0x0002
+#define DSP_MMU_CAM_L_PAGESIZE_1KB             0x0003
+
+#define DSP_MMU_RAM_L_RAM_LSB_MASK     0xfc00
+#define DSP_MMU_RAM_L_AP_MASK          0x0300
+#define DSP_MMU_RAM_L_AP_NA            0x0000
+#define DSP_MMU_RAM_L_AP_RO            0x0200
+#define DSP_MMU_RAM_L_AP_FA            0x0300
+
+#define DSP_MMU_GFLUSH_GFLUSH          0x0001
+
+#define DSP_MMU_FLUSH_ENTRY_FLUSH_ENTRY        0x0001
+
+#define DSP_MMU_LD_TLB_RD              0x0002
+#define DSP_MMU_LD_TLB_LD              0x0001
+
+/*
+ * DSP ICR
+ */
+#define DSPREG_ICR_RESERVED_BITS       0xffc0
+#define DSPREG_ICR_EMIF                        0x0020
+#define DSPREG_ICR_DPLL                        0x0010
+#define DSPREG_ICR_PER                 0x0008
+#define DSPREG_ICR_CACHE               0x0004
+#define DSPREG_ICR_DMA                 0x0002
+#define DSPREG_ICR_CPU                 0x0001
+
+#endif /* __OMAP_DSP_OMAP1_DSP_H */
diff --git a/arch/arm/plat-omap/dsp/omap2_dsp.h b/arch/arm/plat-omap/dsp/omap2_dsp.h
new file mode 100644 (file)
index 0000000..3adf2b9
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_DSP_OMAP2_DSP_H
+#define __OMAP_DSP_OMAP2_DSP_H
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define OMAP24XX_DARAM_BASE    (DSP_MEM_24XX_VIRT + 0x0)
+#define OMAP24XX_DARAM_SIZE    0x10000
+#define OMAP24XX_SARAM_BASE    (DSP_MEM_24XX_VIRT + 0x10000)
+#define OMAP24XX_SARAM_SIZE    0x18000
+#endif
+
+#include <asm/arch/hardware.h>
+#include "../../mach-omap2/prcm-regs.h"
+
+/*
+ * DSP IPI registers: mapped to 0xe1000000 -- use readX(), writeX()
+ */
+#define DSP_IPI_BASE                   DSP_IPI_24XX_VIRT
+#define DSP_IPI_REVISION               (DSP_IPI_BASE + 0x00)
+#define DSP_IPI_SYSCONFIG              (DSP_IPI_BASE + 0x10)
+#define DSP_IPI_INDEX                  (DSP_IPI_BASE + 0x40)
+#define DSP_IPI_ENTRY                  (DSP_IPI_BASE + 0x44)
+#define DSP_IPI_ENABLE                 (DSP_IPI_BASE + 0x48)
+#define DSP_IPI_IOMAP                  (DSP_IPI_BASE + 0x4c)
+#define DSP_IPI_DSPBOOTCONFIG          (DSP_IPI_BASE + 0x50)
+
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_MASK        0x00000003
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_8   0x00000000
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_16  0x00000001
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_32  0x00000002
+
+#define DSP_BOOT_CONFIG_DIRECT         0x00000000
+#define DSP_BOOT_CONFIG_PSD_DIRECT     0x00000001
+#define DSP_BOOT_CONFIG_IDLE           0x00000002
+#define DSP_BOOT_CONFIG_DL16           0x00000003
+#define DSP_BOOT_CONFIG_DL32           0x00000004
+#define DSP_BOOT_CONFIG_API            0x00000005
+#define DSP_BOOT_CONFIG_INTERNAL       0x00000006
+
+/*
+ * DSP boot mode
+ *   direct:        0xffff00
+ *   pseudo direct: 0x080000
+ *   API:           branch 0x010000
+ *   internel:      branch 0x024000
+ */
+#define DSP_BOOT_ADR_DIRECT            0xffff00
+#define DSP_BOOT_ADR_PSD_DIRECT                0x080000
+#define DSP_BOOT_ADR_API               0x010000
+#define DSP_BOOT_ADR_INTERNAL          0x024000
+
+/*
+ * DSP MMU: mapped to 0xe2000000 -- use readX(), writeX()
+ */
+#define DSP_MMU_BASE                   DSP_MMU_24XX_VIRT
+#define DSP_MMU_REVISION               (DSP_MMU_BASE + 0x00)
+#define DSP_MMU_SYSCONFIG              (DSP_MMU_BASE + 0x10)
+#define DSP_MMU_SYSSTATUS              (DSP_MMU_BASE + 0x14)
+#define DSP_MMU_IRQSTATUS              (DSP_MMU_BASE + 0x18)
+#define DSP_MMU_IRQENABLE              (DSP_MMU_BASE + 0x1c)
+#define DSP_MMU_WALKING_ST             (DSP_MMU_BASE + 0x40)
+#define DSP_MMU_CNTL                   (DSP_MMU_BASE + 0x44)
+#define DSP_MMU_FAULT_AD               (DSP_MMU_BASE + 0x48)
+#define DSP_MMU_TTB                    (DSP_MMU_BASE + 0x4c)
+#define DSP_MMU_LOCK                   (DSP_MMU_BASE + 0x50)
+#define DSP_MMU_LD_TLB                 (DSP_MMU_BASE + 0x54)
+#define DSP_MMU_CAM                    (DSP_MMU_BASE + 0x58)
+#define DSP_MMU_RAM                    (DSP_MMU_BASE + 0x5c)
+#define DSP_MMU_GFLUSH                 (DSP_MMU_BASE + 0x60)
+#define DSP_MMU_FLUSH_ENTRY            (DSP_MMU_BASE + 0x64)
+#define DSP_MMU_READ_CAM               (DSP_MMU_BASE + 0x68)
+#define DSP_MMU_READ_RAM               (DSP_MMU_BASE + 0x6c)
+#define DSP_MMU_EMU_FAULT_AD           (DSP_MMU_BASE + 0x70)
+
+#define DSP_MMU_SYSCONFIG_CLOCKACTIVITY_MASK   0x00000300
+#define DSP_MMU_SYSCONFIG_IDLEMODE_MASK                0x00000018
+#define DSP_MMU_SYSCONFIG_SOFTRESET            0x00000002
+#define DSP_MMU_SYSCONFIG_AUTOIDLE             0x00000001
+
+#define DSP_MMU_IRQ_MULTIHITFAULT      0x00000010
+#define DSP_MMU_IRQ_TABLEWALKFAULT     0x00000008
+#define DSP_MMU_IRQ_EMUMISS            0x00000004
+#define DSP_MMU_IRQ_TRANSLATIONFAULT   0x00000002
+#define DSP_MMU_IRQ_TLBMISS            0x00000001
+
+#define DSP_MMU_CNTL_EMUTLBUPDATE      0x00000008
+#define DSP_MMU_CNTL_TWLENABLE         0x00000004
+#define DSP_MMU_CNTL_MMUENABLE         0x00000002
+
+#define DSP_MMU_LOCK_BASE_MASK         0x00007c00
+#define DSP_MMU_LOCK_BASE_SHIFT                10
+#define DSP_MMU_LOCK_VICTIM_MASK       0x000001f0
+#define DSP_MMU_LOCK_VICTIM_SHIFT      4
+
+#define DSP_MMU_CAM_VATAG_MASK         0xfffff000
+#define DSP_MMU_CAM_P                  0x00000008
+#define DSP_MMU_CAM_V                  0x00000004
+#define DSP_MMU_CAM_PAGESIZE_MASK      0x00000003
+#define DSP_MMU_CAM_PAGESIZE_1MB       0x00000000
+#define DSP_MMU_CAM_PAGESIZE_64KB      0x00000001
+#define DSP_MMU_CAM_PAGESIZE_4KB       0x00000002
+#define DSP_MMU_CAM_PAGESIZE_16MB      0x00000003
+
+#define DSP_MMU_RAM_PADDR_MASK         0xfffff000
+#define DSP_MMU_RAM_ENDIANNESS         0x00000200
+#define DSP_MMU_RAM_ENDIANNESS_BIG     0x00000200
+#define DSP_MMU_RAM_ENDIANNESS_LITTLE  0x00000000
+#define DSP_MMU_RAM_ELEMENTSIZE_MASK   0x00000180
+#define DSP_MMU_RAM_ELEMENTSIZE_8      0x00000000
+#define DSP_MMU_RAM_ELEMENTSIZE_16     0x00000080
+#define DSP_MMU_RAM_ELEMENTSIZE_32     0x00000100
+#define DSP_MMU_RAM_ELEMENTSIZE_NONE   0x00000180
+#define DSP_MMU_RAM_MIXED              0x00000040
+
+#define DSP_MMU_GFLUSH_GFLUSH          0x00000001
+
+#define DSP_MMU_FLUSH_ENTRY_FLUSH_ENTRY        0x00000001
+
+#define DSP_MMU_LD_TLB_LD              0x00000001
+
+/*
+ * DSP ICR
+ */
+#define DSPREG_ICR_RESERVED_BITS       0xfc00
+#define DSPREG_ICR_HWA                 0x0200
+#define DSPREG_ICR_IPORT               0x0100
+#define DSPREG_ICR_MPORT               0x0080
+#define DSPREG_ICR_XPORT               0x0040
+#define DSPREG_ICR_DPORT               0x0020
+#define DSPREG_ICR_DPLL                        0x0010
+#define DSPREG_ICR_PER                 0x0008
+#define DSPREG_ICR_CACHE               0x0004
+#define DSPREG_ICR_DMA                 0x0002
+#define DSPREG_ICR_CPU                 0x0001
+
+#endif /* __OMAP_DSP_OMAP2_DSP_H */
index 7265ea0fd4ffde6967ba41cbab1f63372998cd5e..bf16b7c3f49fc0550a4850089a43f5fccf15f722 100644 (file)
@@ -1,97 +1,78 @@
 /*
- * linux/arch/arm/mach-omap/dsp/proclist.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * Linux task list handler
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2004,2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2004/11/22:  DSP Gateway version 3.3
  */
 
 struct proc_list {
        struct list_head list_head;
        pid_t pid;
-       unsigned int cnt;
+       struct file *file;
 };
 
-static __inline__ void proc_list_add(struct list_head *list,
-                                    struct task_struct *tsk)
+static __inline__ void proc_list_add(spinlock_t *lock, struct list_head *list,
+                                    struct task_struct *tsk, struct file *file)
 {
-       struct proc_list *pl;
        struct proc_list *new;
 
-       list_for_each_entry(pl, list, list_head) {
-               if (pl->pid == tsk->pid) {
-                       /*
-                        * this process has opened DSP devices multi time
-                        */
-                       pl->cnt++;
-                       return;
-               }
-       }
-
        new = kmalloc(sizeof(struct proc_list), GFP_KERNEL);
        new->pid = tsk->pid;
-       new->cnt = 1;
+       new->file = file;
+       spin_lock(lock);
        list_add_tail(&new->list_head, list);
+       spin_unlock(lock);
 }
 
-static __inline__ void proc_list_del(struct list_head *list,
-                                    struct task_struct *tsk)
+static __inline__ void proc_list_del(spinlock_t *lock, struct list_head *list,
+                                    struct task_struct *tsk, struct file *file)
 {
-       struct proc_list *pl, *next;
+       struct proc_list *pl;
 
+       spin_lock(lock);
        list_for_each_entry(pl, list, list_head) {
-               if (pl->pid == tsk->pid) {
-                       if (--pl->cnt == 0) {
-                               list_del(&pl->list_head);
-                               kfree(pl);
-                       }
-                       return;
-               }
-       }
-
-       /*
-        * correspinding pid wasn't found in the list
-        * -- this means the caller of proc_list_del is different from
-        * the proc_list_add's caller. in this case, the parent is
-        * cleaning up the context of a killed child.
-        * let's delete exiting task from the list.
-        */
-       /* need to lock tasklist_lock before calling find_task_by_pid_type. */
-       read_lock(&tasklist_lock);
-       list_for_each_entry_safe(pl, next, list, list_head) {
-               if (find_task_by_pid_type(PIDTYPE_PID, pl->pid) == NULL) {
+               if (pl->file == file) {
                        list_del(&pl->list_head);
                        kfree(pl);
+                       spin_unlock(lock);
+                       return;
                }
        }
-       read_unlock(&tasklist_lock);
+
+       /* correspinding file struct isn't found in the list ???  */
+       printk(KERN_ERR "proc_list_del(): proc_list is inconsistent!\n"
+                       "struct file (%p) not found\n", file);
+       printk(KERN_ERR "listing proc_list...\n");
+       list_for_each_entry(pl, list, list_head)
+               printk(KERN_ERR "  pid:%d file:%p\n", pl->pid, pl->file);
+       spin_unlock(lock);
 }
 
-static __inline__ void proc_list_flush(struct list_head *list)
+static __inline__ void proc_list_flush(spinlock_t *lock, struct list_head *list)
 {
        struct proc_list *pl;
 
+       spin_lock(lock);
        while (!list_empty(list)) {
                pl = list_entry(list->next, struct proc_list, list_head);
                list_del(&pl->list_head);
                kfree(pl);
        }
+       spin_unlock(lock);
 }
index 9a9595d9d01e0d4ff8be8f99c70abeed7cc08466..b6c7dfc98929282b0bfab8ad00ecdcf45b70add1 100644 (file)
@@ -1,28 +1,24 @@
 /*
- * linux/arch/arm/mach-omap/dsp/task.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * OMAP DSP task device driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- * mmap function by Hiroo Ishikawa <ext-hiroo.ishikawa@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/07/26:  DSP Gateway version 3.3
  */
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/proc_fs.h>
 #include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/signal.h>
-#include <asm/irq.h>
-#include <asm/ioctls.h>
-#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
 #include "uaccess_dsp.h"
+#include "dsp_mbcmd.h"
 #include "dsp.h"
 #include "ipbuf.h"
 #include "fifo.h"
 #include "proclist.h"
+#include "ioctl.h"
 
 #define is_aligned(adr,align)  (!((adr)&((align)-1)))
 
 /*
- * taskdev.state: device state machine
+ * devstate: task device state machine
  * NOTASK:     task is not attached.
  * ATTACHED:   task is attached.
  * GARBAGE:    task is detached. waiting for all processes to close this device.
  * ADDREQ:     requesting for tadd
  * DELREQ:     requesting for tdel. no process is opening this device.
+ * FREEZED:    task is attached, but reserved to be killed.
  * ADDFAIL:    tadd failed.
  * ADDING:     tadd in process.
  * DELING:     tdel in process.
  * KILLING:    tkill in process.
  */
-#define devstate_name(stat) (\
-       ((stat) & OMAP_DSP_DEVSTATE_NOTASK)   ? "NOTASK" :\
-       ((stat) & OMAP_DSP_DEVSTATE_ATTACHED) ? "ATTACHED" :\
-       ((stat) & OMAP_DSP_DEVSTATE_GARBAGE)  ? "GARBAGE" :\
-       ((stat) & OMAP_DSP_DEVSTATE_INVALID)  ? "INVALID" :\
-       ((stat) & OMAP_DSP_DEVSTATE_ADDREQ)   ? "ADDREQ" :\
-       ((stat) & OMAP_DSP_DEVSTATE_DELREQ)   ? "DELREQ" :\
-       ((stat) & OMAP_DSP_DEVSTATE_ADDFAIL)  ? "ADDFAIL" :\
-       ((stat) & OMAP_DSP_DEVSTATE_ADDING)   ? "ADDING" :\
-       ((stat) & OMAP_DSP_DEVSTATE_DELING)   ? "DELING" :\
-       ((stat) & OMAP_DSP_DEVSTATE_KILLING)  ? "KILLING" :\
-                                               "unknown")
+#define TASKDEV_ST_NOTASK      0x00000001
+#define TASKDEV_ST_ATTACHED    0x00000002
+#define TASKDEV_ST_GARBAGE     0x00000004
+#define TASKDEV_ST_INVALID     0x00000008
+#define TASKDEV_ST_ADDREQ      0x00000100
+#define TASKDEV_ST_DELREQ      0x00000200
+#define TASKDEV_ST_FREEZED     0x00000400
+#define TASKDEV_ST_ADDFAIL     0x00001000
+#define TASKDEV_ST_ADDING      0x00010000
+#define TASKDEV_ST_DELING      0x00020000
+#define TASKDEV_ST_KILLING     0x00040000
+#define TASKDEV_ST_STATE_MASK  0x7fffffff
+#define TASKDEV_ST_STALE       0x80000000
+
+struct {
+       long state;
+       char *name;
+} devstate_desc[] = {
+       { TASKDEV_ST_NOTASK,   "notask" },
+       { TASKDEV_ST_ATTACHED, "attached" },
+       { TASKDEV_ST_GARBAGE,  "garbage" },
+       { TASKDEV_ST_INVALID,  "invalid" },
+       { TASKDEV_ST_ADDREQ,   "addreq" },
+       { TASKDEV_ST_DELREQ,   "delreq" },
+       { TASKDEV_ST_FREEZED,  "freezed" },
+       { TASKDEV_ST_ADDFAIL,  "addfail" },
+       { TASKDEV_ST_ADDING,   "adding" },
+       { TASKDEV_ST_DELING,   "deling" },
+       { TASKDEV_ST_KILLING,  "killing" },
+};
+
+static char *devstate_name(long state) {
+       int i;
+       int max = ARRAY_SIZE(devstate_desc);
+
+       for (i = 0; i < max; i++) {
+               if (state & devstate_desc[i].state)
+                       return devstate_desc[i].name;
+       }
+       return "unknown";
+}
+
+struct rcvdt_bk_struct {
+       struct ipblink link;
+       unsigned int rp;
+};
 
 struct taskdev {
        struct bus_type *bus;
@@ -83,25 +112,35 @@ struct taskdev {
        struct device dev;      /* Generic device interface */
 
        long state;
-       spinlock_t state_lock;
+       struct rw_semaphore state_sem;
        wait_queue_head_t state_wait_q;
+       struct mutex usecount_mutex;
        unsigned int usecount;
-       char name[OMAP_DSP_TNM_LEN];
+       char name[TNM_LEN];
        struct file_operations fops;
+       spinlock_t proc_list_lock;
        struct list_head proc_list;
        struct dsptask *task;
 
        /* read stuff */
        wait_queue_head_t read_wait_q;
        struct mutex read_mutex;
+       union {
+               struct fifo_struct fifo;        /* for active word */
+               struct rcvdt_bk_struct bk;
+       } rcvdt;
 
        /* write stuff */
        wait_queue_head_t write_wait_q;
        struct mutex write_mutex;
+       spinlock_t wsz_lock;
+       size_t wsz;
 
-       /* ioctl stuff */
-       wait_queue_head_t ioctl_wait_q;
-       struct mutex ioctl_mutex;
+       /* tctl stuff */
+       wait_queue_head_t tctl_wait_q;
+       struct mutex tctl_mutex;
+       int tctl_stat;
+       int tctl_ret;   /* return value for tctl_show() */
 
        /* device lock */
        struct mutex lock;
@@ -110,61 +149,71 @@ struct taskdev {
 
 #define to_taskdev(n) container_of(n, struct taskdev, dev)
 
-struct rcvdt_bk_struct {
-       struct ipblink link;
-       unsigned int rp;
-       struct ipbuf_p *ipbuf_pvt_r;
-};
-
 struct dsptask {
        enum {
-               TASK_STATE_ERR = 0,
-               TASK_STATE_READY,
-               TASK_STATE_CFGREQ
+               TASK_ST_ERR = 0,
+               TASK_ST_READY,
+               TASK_ST_CFGREQ
        } state;
-       unsigned char tid;
-       char name[OMAP_DSP_TNM_LEN];
-       unsigned short ttyp;
+       u8 tid;
+       char name[TNM_LEN];
+       u16 ttyp;
        struct taskdev *dev;
 
        /* read stuff */
-       union {
-               struct fifo_struct fifo;        /* for active word */
-               struct rcvdt_bk_struct bk;
-       } rcvdt;
+       struct ipbuf_p *ipbuf_pvt_r;
 
        /* write stuff */
-       size_t wsz;
-       spinlock_t wsz_lock;
-       struct ipbuf_p *ipbuf_pvt_w;    /* for private block */
-
-       /* tctl stuff */
-       int tctl_stat;
+       struct ipbuf_p *ipbuf_pvt_w;
 
        /* mmap stuff */
        void *map_base;
        size_t map_length;
 };
 
-#define sndtyp_acv(ttyp)       ((ttyp) & OMAP_DSP_TTYP_ASND)
-#define sndtyp_psv(ttyp)       (!((ttyp) & OMAP_DSP_TTYP_ASND))
-#define sndtyp_bk(ttyp)                ((ttyp) & OMAP_DSP_TTYP_BKDM)
-#define sndtyp_wd(ttyp)                (!((ttyp) & OMAP_DSP_TTYP_BKDM))
-#define sndtyp_pvt(ttyp)       ((ttyp) & OMAP_DSP_TTYP_PVDM)
-#define sndtyp_gbl(ttyp)       (!((ttyp) & OMAP_DSP_TTYP_PVDM))
-#define rcvtyp_acv(ttyp)       ((ttyp) & OMAP_DSP_TTYP_ARCV)
-#define rcvtyp_psv(ttyp)       (!((ttyp) & OMAP_DSP_TTYP_ARCV))
-#define rcvtyp_bk(ttyp)                ((ttyp) & OMAP_DSP_TTYP_BKMD)
-#define rcvtyp_wd(ttyp)                (!((ttyp) & OMAP_DSP_TTYP_BKMD))
-#define rcvtyp_pvt(ttyp)       ((ttyp) & OMAP_DSP_TTYP_PVMD)
-#define rcvtyp_gbl(ttyp)       (!((ttyp) & OMAP_DSP_TTYP_PVMD))
-
+#define sndtyp_acv(ttyp)       ((ttyp) & TTYP_ASND)
+#define sndtyp_psv(ttyp)       (!((ttyp) & TTYP_ASND))
+#define sndtyp_bk(ttyp)                ((ttyp) & TTYP_BKDM)
+#define sndtyp_wd(ttyp)                (!((ttyp) & TTYP_BKDM))
+#define sndtyp_pvt(ttyp)       ((ttyp) & TTYP_PVDM)
+#define sndtyp_gbl(ttyp)       (!((ttyp) & TTYP_PVDM))
+#define rcvtyp_acv(ttyp)       ((ttyp) & TTYP_ARCV)
+#define rcvtyp_psv(ttyp)       (!((ttyp) & TTYP_ARCV))
+#define rcvtyp_bk(ttyp)                ((ttyp) & TTYP_BKMD)
+#define rcvtyp_wd(ttyp)                (!((ttyp) & TTYP_BKMD))
+#define rcvtyp_pvt(ttyp)       ((ttyp) & TTYP_PVMD)
+#define rcvtyp_gbl(ttyp)       (!((ttyp) & TTYP_PVMD))
+
+static __inline__ int has_taskdev_lock(struct taskdev *dev);
 static int dsp_rmdev_minor(unsigned char minor);
 static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor);
 static void taskdev_delete(unsigned char minor);
-static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task);
-static void taskdev_detach_task(struct taskdev *dev);
-static int dsp_tdel_bh(unsigned char minor, unsigned short type);
+static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task);
+static int dsp_tdel_bh(struct taskdev *dev, u16 type);
+
+static struct bus_type dsptask_bus = {
+       .name = "dsptask",
+};
+
+static struct class *dsp_task_class;
+static DEFINE_MUTEX(devmgr_lock);
+static struct taskdev *taskdev[TASKDEV_MAX];
+static struct dsptask *dsptask[TASKDEV_MAX];
+static DEFINE_MUTEX(cfg_lock);
+static u16 cfg_cmd;
+static u8 cfg_tid;
+static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q);
+static u8 n_task;      /* static task count */
+static void *heap;
+
+#define is_dynamic_task(tid)   ((tid) >= n_task)
+
+#define devstate_read_lock(dev, devstate) \
+               devstate_read_lock_timeout(dev, devstate, 0)
+#define devstate_read_unlock(dev)      up_read(&(dev)->state_sem)
+#define devstate_write_lock(dev, devstate) \
+               devstate_write_lock_timeout(dev, devstate, 0)
+#define devstate_write_unlock(dev)     up_write(&(dev)->state_sem)
 
 static ssize_t devname_show(struct device *d, struct device_attribute *attr,
                            char *buf);
@@ -189,147 +238,188 @@ static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
 static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
                         char *buf);
 
-static struct device_attribute dev_attr_devname = __ATTR_RO(devname);
-static struct device_attribute dev_attr_devstate = __ATTR_RO(devstate);
-static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list);
-static struct device_attribute dev_attr_fifosz = 
-       __ATTR(fifosz, S_IWUGO | S_IRUGO, fifosz_show, fifosz_store);
-static struct device_attribute dev_attr_fifocnt = __ATTR_RO(fifocnt);
-static struct device_attribute dev_attr_taskname = __ATTR_RO(taskname);
-static struct device_attribute dev_attr_ttyp = __ATTR_RO(ttyp);
-static struct device_attribute dev_attr_ipblink = __ATTR_RO(ipblink);
-static struct device_attribute dev_attr_wsz = __ATTR_RO(wsz);
-static struct device_attribute dev_attr_mmap = __ATTR_RO(mmap);
-
-static struct bus_type dsptask_bus = {
-       .name = "dsptask",
-};
-
-static struct class *dsp_task_class;
-static struct taskdev *taskdev[TASKDEV_MAX];
-static struct dsptask *dsptask[TASKDEV_MAX];
-static DEFINE_MUTEX(cfg_lock);
-static unsigned short cfg_cmd;
-static unsigned char cfg_tid;
-static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q);
-static unsigned char n_task;
-static void *heap;
+#define __ATTR_RW(_name,_mode) { \
+       .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
+       .show   = _name##_show,                                 \
+       .store  = _name##_store,                                        \
+}
 
-#define devstate_lock(dev, devstate)   devstate_lock_timeout(dev, devstate, 0)
+static struct device_attribute dev_attr_devname   = __ATTR_RO(devname);
+static struct device_attribute dev_attr_devstate  = __ATTR_RO(devstate);
+static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list);
+static struct device_attribute dev_attr_taskname  = __ATTR_RO(taskname);
+static struct device_attribute dev_attr_ttyp      = __ATTR_RO(ttyp);
+static struct device_attribute dev_attr_fifosz    = __ATTR_RW(fifosz, 0666);
+static struct device_attribute dev_attr_fifocnt   = __ATTR_RO(fifocnt);
+static struct device_attribute dev_attr_ipblink   = __ATTR_RO(ipblink);
+static struct device_attribute dev_attr_wsz       = __ATTR_RO(wsz);
+static struct device_attribute dev_attr_mmap      = __ATTR_RO(mmap);
 
 /*
- * devstate_lock_timeout():
- * when called with timeout > 0, dev->state can be diffeent from what you want.
+ * devstate_read_lock_timeout()
+ * devstate_write_lock_timeout():
+ * timeout != 0: dev->state can be diffeent from what you want.
+ * timeout == 0: no timeout
  */
-static int devstate_lock_timeout(struct taskdev *dev, long devstate,
-                                int timeout)
+static int devstate_read_lock_timeout(struct taskdev *dev, long devstate,
+                                     int timeout)
 {
        DECLARE_WAITQUEUE(wait, current);
        long current_state = current->state;
        int ret = 0;
 
-       spin_lock(&dev->state_lock);
+       down_read(&dev->state_sem);
+       if (dev->state & devstate)
+               return 0;
+
        add_wait_queue(&dev->state_wait_q, &wait);
-       while (!(dev->state & devstate)) {
+       do {
                set_current_state(TASK_INTERRUPTIBLE);
-               spin_unlock(&dev->state_lock);
+               up_read(&dev->state_sem);
                if (timeout) {
                        if ((timeout = schedule_timeout(timeout)) == 0) {
                                /* timeout */
-                               spin_lock(&dev->state_lock);
+                               down_read(&dev->state_sem);
                                break;
                        }
+               } else
+                       schedule();
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
                }
-               else
+               down_read(&dev->state_sem);
+       } while (!(dev->state & devstate));
+       remove_wait_queue(&dev->state_wait_q, &wait);
+       set_current_state(current_state);
+       return ret;
+}
+
+static int devstate_read_lock_and_test(struct taskdev *dev, long devstate)
+{
+       down_read(&dev->state_sem);
+       if (dev->state & devstate)
+               return 1;       /* success */
+       /* failure */
+       up_read(&dev->state_sem);
+       return 0;
+}
+
+static int devstate_write_lock_timeout(struct taskdev *dev, long devstate,
+                                      int timeout)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       long current_state = current->state;
+       int ret = 0;
+
+       down_write(&dev->state_sem);
+       if (dev->state & devstate)
+               return 0;
+       
+       add_wait_queue(&dev->state_wait_q, &wait);
+       do {
+               set_current_state(TASK_INTERRUPTIBLE);
+               up_write(&dev->state_sem);
+               if (timeout) {
+                       if ((timeout = schedule_timeout(timeout)) == 0) {
+                               /* timeout */
+                               down_write(&dev->state_sem);
+                               break;
+                       }
+               } else
                        schedule();
                if (signal_pending(current)) {
-                       ret = -ERESTARTSYS;
+                       ret = -EINTR;
                        break;
                }
-               spin_lock(&dev->state_lock);
-       }
+               down_write(&dev->state_sem);
+       } while (!(dev->state & devstate));
        remove_wait_queue(&dev->state_wait_q, &wait);
        set_current_state(current_state);
        return ret;
 }
 
-static __inline__ void devstate_unlock(struct taskdev *dev)
+static int devstate_write_lock_and_test(struct taskdev *dev, long devstate)
 {
-       spin_unlock(&dev->state_lock);
+       down_write(&dev->state_sem);
+       if (dev->state & devstate)      /* success */
+               return 1;
+       
+       /* failure */
+       up_write(&dev->state_sem);
+       return -1;
 }
 
-static inline int taskdev_lock_interruptible(struct taskdev *dev,
-                                            struct mutex *lock)
+static int taskdev_lock_interruptible(struct taskdev *dev, struct mutex *mutex)
 {
        int ret;
 
-       if (dev->lock_pid == current->pid) {
-               /* this process has lock */
-               ret = mutex_lock_interruptible(lock);
-       } else {
+       if (has_taskdev_lock(dev))
+               ret = mutex_lock_interruptible(mutex);
+       else {
                if ((ret = mutex_lock_interruptible(&dev->lock)) != 0)
                        return ret;
-               ret = mutex_lock_interruptible(lock);
+               ret = mutex_lock_interruptible(mutex);
                mutex_unlock(&dev->lock);
        }
+
        return ret;
 }
 
-static void proclist_send_sigbus(struct list_head *list)
+static int taskdev_lock_and_statelock_attached(struct taskdev *dev,
+                                              struct mutex *mutex)
 {
-       siginfo_t info;
-       struct proc_list *pl;
-       struct task_struct *tsk;
+       int ret;
 
-       info.si_signo = SIGBUS;
-       info.si_errno = 0;
-       info.si_code = SI_KERNEL;
-       info._sifields._sigfault._addr = NULL;
+       if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+               return -ENODEV;
 
-       /* need to lock tasklist_lock before calling find_task_by_pid_type. */
-       read_lock(&tasklist_lock);
-       list_for_each_entry(pl, list, list_head) {
-               if ((tsk = find_task_by_pid_type(PIDTYPE_PID, pl->pid)) != NULL)
-                       send_sig_info(SIGBUS, &info, tsk);
-       }
-       read_unlock(&tasklist_lock);
+       if ((ret = taskdev_lock_interruptible(dev, mutex)) != 0)
+               devstate_read_unlock(dev);
+
+       return ret;
 }
 
-static int dsp_task_flush_buf(struct dsptask *task)
+static __inline__ void taskdev_unlock_and_stateunlock(struct taskdev *dev,
+                                                     struct mutex *mutex)
+{
+       mutex_unlock(mutex);
+       devstate_read_unlock(dev);
+}
+
+/*
+ * taskdev_flush_buf()
+ * must be called under state_lock(ATTACHED) and dev->read_mutex.
+ */
+static int taskdev_flush_buf(struct taskdev *dev)
 {
-       unsigned short ttyp = task->ttyp;
+       u16 ttyp = dev->task->ttyp;
 
        if (sndtyp_wd(ttyp)) {
                /* word receiving */
-               flush_fifo(&task->rcvdt.fifo);
+               flush_fifo(&dev->rcvdt.fifo);
        } else {
                /* block receiving */
-               struct rcvdt_bk_struct *rcvdt = &task->rcvdt.bk;
-
-               spin_lock(&rcvdt->link.lock);
-               if (sndtyp_gbl(ttyp)) {
-                       /* global IPBUF */
-                       while (!ipblink_empty(&rcvdt->link)) {
-                               unsigned short bid = rcvdt->link.top;
-                               ipblink_del_top(&rcvdt->link, ipbuf);
-                               unuse_ipbuf(bid);
-                       }
-               } else {
-                       /* private IPBUF */
-                       if (!ipblink_empty(&rcvdt->link)) {
-                               ipblink_del_pvt(&rcvdt->link);
-                               release_ipbuf_pvt(rcvdt->ipbuf_pvt_r);
-                       }
+               struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
+
+               if (sndtyp_gbl(ttyp))
+                       ipblink_flush(&rcvdt->link);
+               else {
+                       ipblink_flush_pvt(&rcvdt->link);
+                       release_ipbuf_pvt(dev->task->ipbuf_pvt_r);
                }
-               spin_unlock(&rcvdt->link.lock);
        }
 
        return 0;
 }
 
-static int dsp_task_set_fifosz(struct dsptask *task, unsigned long sz)
+/*
+ * taskdev_set_fifosz()
+ * must be called under dev->read_mutex.
+ */
+static int taskdev_set_fifosz(struct taskdev *dev, unsigned long sz)
 {
-       unsigned short ttyp = task->ttyp;
+       u16 ttyp = dev->task->ttyp;
        int stat;
 
        if (!(sndtyp_wd(ttyp) && sndtyp_acv(ttyp))) {
@@ -344,31 +434,36 @@ static int dsp_task_set_fifosz(struct dsptask *task, unsigned long sz)
                return -EINVAL;
        }
 
-       stat = realloc_fifo(&task->rcvdt.fifo, sz);
+       stat = realloc_fifo(&dev->rcvdt.fifo, sz);
        if (stat == -EBUSY) {
                printk(KERN_ERR "omapdsp: buffer is not empty!\n");
                return stat;
        } else if (stat < 0) {
                printk(KERN_ERR
                       "omapdsp: unable to change receive buffer size. "
-                      "(%ld bytes for %s)\n", sz, task->name);
+                      "(%ld bytes for %s)\n", sz, dev->name);
                return stat;
        }
 
        return 0;
 }
 
+static __inline__ int has_taskdev_lock(struct taskdev *dev)
+{
+       return (dev->lock_pid == current->pid);
+}
+
 static int taskdev_lock(struct taskdev *dev)
 {
        if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
+               return -EINTR;
        dev->lock_pid = current->pid;
        return 0;
 }
 
 static int taskdev_unlock(struct taskdev *dev)
 {
-       if (dev->lock_pid != current->pid) {
+       if (!has_taskdev_lock(dev)) {
                printk(KERN_ERR
                       "omapdsp: an illegal process attempted to "
                       "unlock the dsptask lock!\n");
@@ -379,28 +474,26 @@ static int taskdev_unlock(struct taskdev *dev)
        return 0;
 }
 
-static int dsp_task_config(struct dsptask *task, unsigned char tid)
+static int dsp_task_config(struct dsptask *task, u8 tid)
 {
-       unsigned short ttyp;
-       struct mbcmd mb;
+       u16 ttyp;
        int ret;
 
        task->tid = tid;
        dsptask[tid] = task;
 
        /* TCFG request */
-       task->state = TASK_STATE_CFGREQ;
+       task->state = TASK_ST_CFGREQ;
        if (mutex_lock_interruptible(&cfg_lock)) {
-               ret = -ERESTARTSYS;
+               ret = -EINTR;
                goto fail_out;
        }
-       cfg_cmd = MBCMD(TCFG);
-       mbcmd_set(mb, MBCMD(TCFG), tid, 0);
-       dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
+       cfg_cmd = MBX_CMD_DSP_TCFG;
+       mbcompose_send_and_wait(TCFG, tid, 0, &cfg_wait_q);
        cfg_cmd = 0;
        mutex_unlock(&cfg_lock);
 
-       if (task->state != TASK_STATE_READY) {
+       if (task->state != TASK_ST_READY) {
                printk(KERN_ERR "omapdsp: task %d configuration error!\n", tid);
                ret = -EINVAL;
                goto fail_out;
@@ -426,7 +519,7 @@ static int dsp_task_config(struct dsptask *task, unsigned char tid)
 
        /* private buffer address check */
        if (sndtyp_pvt(ttyp) &&
-           (ipbuf_p_validate(task->rcvdt.bk.ipbuf_pvt_r, DIR_D2A) < 0)) {
+           (ipbuf_p_validate(task->ipbuf_pvt_r, DIR_D2A) < 0)) {
                ret = -EINVAL;
                goto fail_out;
        }
@@ -451,36 +544,6 @@ static int dsp_task_config(struct dsptask *task, unsigned char tid)
                goto fail_out;
        }
 
-       /*
-        * initialization
-        */
-
-       /* read initialization */
-       if (sndtyp_wd(ttyp)) {
-               /* word */
-               size_t fifosz;
-
-               fifosz = sndtyp_psv(ttyp) ? 2 : /* passive */
-                                           32; /* active */
-               if (init_fifo(&task->rcvdt.fifo, fifosz) < 0) {
-                       printk(KERN_ERR
-                              "omapdsp: unable to allocate receive buffer. "
-                              "(%d bytes for %s)\n", fifosz, task->name);
-                       ret = -ENOMEM;
-                       goto fail_out;
-               }
-       } else {
-               /* block */
-               INIT_IPBLINK(&task->rcvdt.bk.link);
-               task->rcvdt.bk.rp = 0;
-       }
-
-       /* write initialization */
-       spin_lock_init(&task->wsz_lock);
-       task->wsz = rcvtyp_acv(ttyp) ? 0 :              /* active */
-                   rcvtyp_wd(ttyp)  ? 2 :              /* passive word */
-                                      ipbcfg.lsz*2;    /* passive block */
-
        return 0;
 
 fail_out:
@@ -490,10 +553,10 @@ fail_out:
 
 static void dsp_task_init(struct dsptask *task)
 {
-       dsp_mbsend(MBCMD(TCTL), task->tid, OMAP_DSP_MBCMD_TCTL_TINIT);
+       mbcompose_send(TCTL, task->tid, TCTL_TINIT);
 }
 
-int dsp_task_config_all(unsigned char n)
+int dsp_task_config_all(u8 n)
 {
        int i, ret;
        struct taskdev *devheap;
@@ -503,26 +566,23 @@ int dsp_task_config_all(unsigned char n)
        memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX);
        memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX);
 
-       n_task = n;
-       printk(KERN_INFO "omapdsp: found %d task(s)\n", n_task);
-       if (n_task == 0)
+       printk(KERN_INFO "omapdsp: found %d task(s)\n", n);
+       if (n == 0)
                return 0;
 
        /*
         * reducing kmalloc!
         */
-       devheapsz  = sizeof(struct taskdev) * n_task;
-       taskheapsz = sizeof(struct dsptask) * n_task;
-       heap = kmalloc(devheapsz + taskheapsz, GFP_KERNEL);
-       if (heap == NULL) {
-               n_task = 0;
+       devheapsz  = sizeof(struct taskdev) * n;
+       taskheapsz = sizeof(struct dsptask) * n;
+       heap = kzalloc(devheapsz + taskheapsz, GFP_KERNEL);
+       if (heap == NULL)
                return -ENOMEM;
-       }
-       memset(heap, 0, devheapsz + taskheapsz);
        devheap  = heap;
        taskheap = heap + devheapsz;
 
-       for (i = 0; i < n_task; i++) {
+       n_task = n;
+       for (i = 0; i < n; i++) {
                struct taskdev *dev  = &devheap[i];
                struct dsptask *task = &taskheap[i];
 
@@ -530,7 +590,8 @@ int dsp_task_config_all(unsigned char n)
                        return ret;
                if ((ret = taskdev_init(dev, task->name, i)) < 0)
                        return ret;
-               taskdev_attach_task(dev, task);
+               if ((ret = taskdev_attach_task(dev, task)) < 0)
+                       return ret;
                dsp_task_init(task);
                printk(KERN_INFO "omapdsp: taskdev %s enabled.\n", dev->name);
        }
@@ -540,20 +601,13 @@ int dsp_task_config_all(unsigned char n)
 
 static void dsp_task_unconfig(struct dsptask *task)
 {
-       unsigned char tid = task->tid;
-
-       preempt_disable();
-       dsp_task_flush_buf(task);
-       if (sndtyp_wd(task->ttyp) && (task->state == TASK_STATE_READY))
-               free_fifo(&task->rcvdt.fifo);
-       dsptask[tid] = NULL;
-       preempt_enable();
+       dsptask[task->tid] = NULL;
 }
 
 void dsp_task_unconfig_all(void)
 {
        unsigned char minor;
-       unsigned char tid;
+       u8 tid;
        struct dsptask *task;
 
        for (minor = 0; minor < n_task; minor++) {
@@ -603,7 +657,7 @@ static struct device_driver dsptask_driver = {
        .bus    = &dsptask_bus,
 };
 
-unsigned char dsp_task_count(void)
+u8 dsp_task_count(void)
 {
        return n_task;
 }
@@ -612,21 +666,22 @@ int dsp_taskmod_busy(void)
 {
        struct taskdev *dev;
        unsigned char minor;
+       unsigned int usecount;
 
        for (minor = 0; minor < TASKDEV_MAX; minor++) {
                dev = taskdev[minor];
                if (dev == NULL)
                        continue;
-               if (dev->usecount > 0) {
+               if ((usecount = dev->usecount) > 0) {
                        printk("dsp_taskmod_busy(): %s: usecount=%d\n",
-                              dev->name, dev->usecount);
+                              dev->name, usecount);
                        return 1;
                }
 /*
-               if ((dev->state & (OMAP_DSP_DEVSTATE_ADDREQ |
-                                  OMAP_DSP_DEVSTATE_DELREQ)) {
+               if ((dev->state & (TASKDEV_ST_ADDREQ |
+                                  TASKDEV_ST_DELREQ)) {
 */
-               if (dev->state & OMAP_DSP_DEVSTATE_ADDREQ) {
+               if (dev->state & TASKDEV_ST_ADDREQ) {
                        printk("dsp_taskmod_busy(): %s is in %s\n",
                               dev->name, devstate_name(dev->state));
                        return 1;
@@ -638,12 +693,11 @@ int dsp_taskmod_busy(void)
 /*
  * DSP task device file operations
  */
-static ssize_t dsp_task_read_wd_acv(struct file *file, char *buf, size_t count,
-                                   loff_t *ppos)
+static ssize_t dsp_task_read_wd_acv(struct file *file, char __user *buf,
+                                   size_t count, loff_t *ppos)
 {
        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        struct taskdev *dev = taskdev[minor];
-       int have_devstate_lock = 0;
        int ret = 0;
 
        if (count == 0) {
@@ -654,58 +708,40 @@ static ssize_t dsp_task_read_wd_acv(struct file *file, char *buf, size_t count,
                return -EINVAL;
        }
 
-       if (taskdev_lock_interruptible(dev, &dev->read_mutex))
-               return -ERESTARTSYS;
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-               ret = -ERESTARTSYS;
-               goto up_out;
-       }
-       have_devstate_lock = 1;
+       if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+               return -ENODEV;
 
-       if (fifo_empty(&dev->task->rcvdt.fifo)) {
+       if (fifo_empty(&dev->rcvdt.fifo)) {
                long current_state = current->state;
                DECLARE_WAITQUEUE(wait, current);
 
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&dev->read_wait_q, &wait);
-               if (fifo_empty(&dev->task->rcvdt.fifo)) {       /* last check */
-                       devstate_unlock(dev);
-                       have_devstate_lock = 0;
+               if (fifo_empty(&dev->rcvdt.fifo))       /* last check */
                        schedule();
-               }
                set_current_state(current_state);
                remove_wait_queue(&dev->read_wait_q, &wait);
-               if (signal_pending(current)) {
-                       ret = -ERESTARTSYS;
+               if (fifo_empty(&dev->rcvdt.fifo)) {
+                       /* failure */
+                       if (signal_pending(current))
+                               ret = -EINTR;
                        goto up_out;
                }
-               if (!have_devstate_lock) {
-                       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-                               ret = -ERESTARTSYS;
-                               goto up_out;
-                       }
-                       have_devstate_lock = 1;
-               }
-               if (fifo_empty(&dev->task->rcvdt.fifo)) /* should not occur */
-                       goto up_out;
        }
 
-       ret = copy_to_user_fm_fifo(buf, &dev->task->rcvdt.fifo, count);
+       ret = copy_to_user_fm_fifo(buf, &dev->rcvdt.fifo, count);
 
 up_out:
-       if (have_devstate_lock)
-               devstate_unlock(dev);
-       mutex_unlock(&dev->read_mutex);
+       taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
        return ret;
 }
 
-static ssize_t dsp_task_read_bk_acv(struct file *file, char *buf, size_t count,
-                                   loff_t *ppos)
+static ssize_t dsp_task_read_bk_acv(struct file *file, char __user *buf,
+                                   size_t count, loff_t *ppos)
 {
        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        struct taskdev *dev = taskdev[minor];
-       struct rcvdt_bk_struct *rcvdt;
-       int have_devstate_lock = 0;
+       struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
        ssize_t ret = 0;
 
        if (count == 0) {
@@ -721,55 +757,38 @@ static ssize_t dsp_task_read_bk_acv(struct file *file, char *buf, size_t count,
                return -EINVAL;
        }
 
-       if (taskdev_lock_interruptible(dev, &dev->read_mutex))
-               return -ERESTARTSYS;
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-               ret = -ERESTARTSYS;
-               goto up_out;
-       }
-       have_devstate_lock = 1;
+       if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+               return -ENODEV;
 
-       if (ipblink_empty(&dev->task->rcvdt.bk.link)) {
+       if (ipblink_empty(&rcvdt->link)) {
                long current_state;
                DECLARE_WAITQUEUE(wait, current);
 
                add_wait_queue(&dev->read_wait_q, &wait);
                current_state = current->state;
                set_current_state(TASK_INTERRUPTIBLE);
-               if (ipblink_empty(&dev->task->rcvdt.bk.link)) { /* last check */
-                       devstate_unlock(dev);
-                       have_devstate_lock = 0;
+               if (ipblink_empty(&rcvdt->link))        /* last check */
                        schedule();
-               }
                set_current_state(current_state);
                remove_wait_queue(&dev->read_wait_q, &wait);
-               if (signal_pending(current)) {
-                       ret = -ERESTARTSYS;
+               if (ipblink_empty(&rcvdt->link)) {
+                       /* failure */
+                       if (signal_pending(current))
+                               ret = -EINTR;
                        goto up_out;
                }
-               if (!have_devstate_lock) {
-                       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-                               ret = -ERESTARTSYS;
-                               goto up_out;
-                       }
-                       have_devstate_lock = 1;
-               }
-               /* signal or 0-byte send from DSP */
-               if (ipblink_empty(&dev->task->rcvdt.bk.link))
-                       goto up_out;
        }
 
-       rcvdt = &dev->task->rcvdt.bk;
        /* copy from delayed IPBUF */
        if (sndtyp_pvt(dev->task->ttyp)) {
                /* private */
                if (!ipblink_empty(&rcvdt->link)) {
-                       struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
+                       struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
                        unsigned char *base, *src;
                        size_t bkcnt;
 
                        if (dsp_mem_enable(ipbp) < 0) {
-                               ret = -ERESTARTSYS;
+                               ret = -EBUSY;
                                goto up_out;
                        }
                        base = MKVIRT(ipbp->ah, ipbp->al);
@@ -777,11 +796,11 @@ static ssize_t dsp_task_read_bk_acv(struct file *file, char *buf, size_t count,
                        if (dsp_address_validate(base, bkcnt,
                                                 "task %s read buffer",
                                                 dev->task->name) < 0) {
-                               ret = -ERESTARTSYS;
+                               ret = -EINVAL;
                                goto pv_out1;
                        }
                        if (dsp_mem_enable(base) < 0) {
-                               ret = -ERESTARTSYS;
+                               ret = -EBUSY;
                                goto pv_out1;
                        }
                        src = base + rcvdt->rp;
@@ -798,9 +817,7 @@ static ssize_t dsp_task_read_bk_acv(struct file *file, char *buf, size_t count,
                                        goto pv_out2;
                                }
                                ret = bkcnt;
-                               spin_lock(&rcvdt->link.lock);
                                ipblink_del_pvt(&rcvdt->link);
-                               spin_unlock(&rcvdt->link.lock);
                                release_ipbuf_pvt(ipbp);
                                rcvdt->rp = 0;
                        }
@@ -812,17 +829,16 @@ pv_out1:
        } else {
                /* global */
                if (dsp_mem_enable_ipbuf() < 0) {
-                       ret = -ERESTARTSYS;
+                       ret = -EBUSY;
                        goto up_out;
                }
                while (!ipblink_empty(&rcvdt->link)) {
                        unsigned char *src;
                        size_t bkcnt;
-                       unsigned short bid = rcvdt->link.top;
-                       struct ipbuf *ipbp = ipbuf[bid];
+                       struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
 
-                       src = ipbp->d + rcvdt->rp;
-                       bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp;
+                       src = ipb_h->p->d + rcvdt->rp;
+                       bkcnt = ((unsigned long)ipb_h->p->c) * 2 - rcvdt->rp;
                        if (bkcnt > count) {
                                if (copy_to_user_dsp(buf, src, count)) {
                                        ret = -EFAULT;
@@ -839,10 +855,8 @@ pv_out1:
                                ret += bkcnt;
                                buf += bkcnt;
                                count -= bkcnt;
-                               spin_lock(&rcvdt->link.lock);
-                               ipblink_del_top(&rcvdt->link, ipbuf);
-                               spin_unlock(&rcvdt->link.lock);
-                               unuse_ipbuf(bid);
+                               ipblink_del_top(&rcvdt->link);
+                               unuse_ipbuf(ipb_h);
                                rcvdt->rp = 0;
                        }
                }
@@ -851,19 +865,15 @@ gb_out:
        }
 
 up_out:
-       if (have_devstate_lock)
-               devstate_unlock(dev);
-       mutex_unlock(&dev->read_mutex);
+       taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
        return ret;
 }
 
-static ssize_t dsp_task_read_wd_psv(struct file *file, char *buf, size_t count,
-                                   loff_t *ppos)
+static ssize_t dsp_task_read_wd_psv(struct file *file, char __user *buf,
+                                   size_t count, loff_t *ppos)
 {
        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        struct taskdev *dev = taskdev[minor];
-       struct mbcmd mb;
-       unsigned char tid;
        int ret = 0;
 
        if (count == 0) {
@@ -877,46 +887,31 @@ static ssize_t dsp_task_read_wd_psv(struct file *file, char *buf, size_t count,
                count = 2;
        }
 
-       if (taskdev_lock_interruptible(dev, &dev->read_mutex))
-               return -ERESTARTSYS;
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-               ret = -ERESTARTSYS;
-               goto up_out;
-       }
-       tid = dev->task->tid;
-       devstate_unlock(dev);
+       if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+               return -ENODEV;
 
-       mbcmd_set(mb, MBCMD(WDREQ), tid, 0);
-       dsp_mbcmd_send_and_wait(&mb, &dev->read_wait_q);
+       mbcompose_send_and_wait(WDREQ, dev->task->tid, 0, &dev->read_wait_q);
 
-       if (signal_pending(current)) {
-               ret = -ERESTARTSYS;
+       if (fifo_empty(&dev->rcvdt.fifo)) {
+               /* failure */
+               if (signal_pending(current))
+                       ret = -EINTR;
                goto up_out;
        }
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-               ret = -ERESTARTSYS;
-               goto up_out;
-       }
-       if (fifo_empty(&dev->task->rcvdt.fifo)) /* should not occur */
-               goto unlock_out;
 
-       ret = copy_to_user_fm_fifo(buf, &dev->task->rcvdt.fifo, count);
+       ret = copy_to_user_fm_fifo(buf, &dev->rcvdt.fifo, count);
 
-unlock_out:
-       devstate_unlock(dev);
 up_out:
-       mutex_unlock(&dev->read_mutex);
+       taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
        return ret;
 }
 
-static ssize_t dsp_task_read_bk_psv(struct file *file, char *buf, size_t count,
-                                   loff_t *ppos)
+static ssize_t dsp_task_read_bk_psv(struct file *file, char __user *buf,
+                                   size_t count, loff_t *ppos)
 {
        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        struct taskdev *dev = taskdev[minor];
-       struct rcvdt_bk_struct *rcvdt;
-       struct mbcmd mb;
-       unsigned char tid;
+       struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
        int ret = 0;
 
        if (count == 0) {
@@ -932,53 +927,41 @@ static ssize_t dsp_task_read_bk_psv(struct file *file, char *buf, size_t count,
                return -EINVAL;
        }
 
-       if (taskdev_lock_interruptible(dev, &dev->read_mutex))
-               return -ERESTARTSYS;
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-               ret = -ERESTARTSYS;
-               goto up_out;
-       }
-       tid = dev->task->tid;
-       devstate_unlock(dev);
+       if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+               return -ENODEV;
 
-       mbcmd_set(mb, MBCMD(BKREQ), tid, count/2);
-       dsp_mbcmd_send_and_wait(&mb, &dev->read_wait_q);
+       mbcompose_send_and_wait(BKREQ, dev->task->tid, count/2,
+                               &dev->read_wait_q);
 
-       if (signal_pending(current)) {
-               ret = -ERESTARTSYS;
+       if (ipblink_empty(&rcvdt->link)) {
+               /* failure */
+               if (signal_pending(current))
+                       ret = -EINTR;
                goto up_out;
        }
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-               ret = -ERESTARTSYS;
-               goto up_out;
-       }
-       rcvdt = &dev->task->rcvdt.bk;
-       /* signal or 0-byte send from DSP */
-       if (ipblink_empty(&rcvdt->link))
-               goto unlock_out;
 
        /*
         * We will not receive more than requested count.
         */
        if (sndtyp_pvt(dev->task->ttyp)) {
                /* private */
-               struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
+               struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
                size_t rcvcnt;
                void *src;
 
                if (dsp_mem_enable(ipbp) < 0) {
-                       ret = -ERESTARTSYS;
-                       goto unlock_out;
+                       ret = -EBUSY;
+                       goto up_out;
                }
                src = MKVIRT(ipbp->ah, ipbp->al);
                rcvcnt = ((unsigned long)ipbp->c) * 2;
                if (dsp_address_validate(src, rcvcnt, "task %s read buffer",
                                         dev->task->name) < 0) {
-                       ret = -ERESTARTSYS;
+                       ret = -EINVAL;
                        goto pv_out1;
                }
                if (dsp_mem_enable(src) < 0) {
-                       ret = -ERESTARTSYS;
+                       ret = -EBUSY;
                        goto pv_out1;
                }
                if (count > rcvcnt)
@@ -987,9 +970,7 @@ static ssize_t dsp_task_read_bk_psv(struct file *file, char *buf, size_t count,
                        ret = -EFAULT;
                        goto pv_out2;
                }
-               spin_lock(&rcvdt->link.lock);
                ipblink_del_pvt(&rcvdt->link);
-               spin_unlock(&rcvdt->link.lock);
                release_ipbuf_pvt(ipbp);
                ret = count;
 pv_out2:
@@ -998,44 +979,38 @@ pv_out1:
                dsp_mem_disable(ipbp);
        } else {
                /* global */
-               unsigned short bid = rcvdt->link.top;
-               struct ipbuf *ipbp = ipbuf[bid];
+               struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
                size_t rcvcnt;
 
                if (dsp_mem_enable_ipbuf() < 0) {
-                       ret = -ERESTARTSYS;
-                       goto unlock_out;
+                       ret = -EBUSY;
+                       goto up_out;
                }
-               rcvcnt = ((unsigned long)ipbp->c) * 2;
+               rcvcnt = ((unsigned long)ipb_h->p->c) * 2;
                if (count > rcvcnt)
                        count = rcvcnt;
-               if (copy_to_user_dsp(buf, ipbp->d, count)) {
+               if (copy_to_user_dsp(buf, ipb_h->p->d, count)) {
                        ret = -EFAULT;
                        goto gb_out;
                }
-               spin_lock(&rcvdt->link.lock);
-               ipblink_del_top(&rcvdt->link, ipbuf);
-               spin_unlock(&rcvdt->link.lock);
-               unuse_ipbuf(bid);
+               ipblink_del_top(&rcvdt->link);
+               unuse_ipbuf(ipb_h);
                ret = count;
 gb_out:
                dsp_mem_disable_ipbuf();
        }
 
-unlock_out:
-       devstate_unlock(dev);
 up_out:
-       mutex_unlock(&dev->read_mutex);
+       taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
        return ret;
 }
 
-static ssize_t dsp_task_write_wd(struct file *file, const char *buf,
+static ssize_t dsp_task_write_wd(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 {
        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        struct taskdev *dev = taskdev[minor];
-       unsigned short wd;
-       int have_devstate_lock = 0;
+       u16 wd;
        int ret = 0;
 
        if (count == 0) {
@@ -1049,41 +1024,26 @@ static ssize_t dsp_task_write_wd(struct file *file, const char *buf,
                count = 2;
        }
 
-       if (taskdev_lock_interruptible(dev, &dev->write_mutex))
-               return -ERESTARTSYS;
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-               ret = -ERESTARTSYS;
-               goto up_out;
-       }
-       have_devstate_lock = 1;
+       if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
+               return -ENODEV;
 
-       if (dev->task->wsz == 0) {
+       if (dev->wsz == 0) {
                long current_state;
                DECLARE_WAITQUEUE(wait, current);
 
                add_wait_queue(&dev->write_wait_q, &wait);
                current_state = current->state;
                set_current_state(TASK_INTERRUPTIBLE);
-               if (dev->task->wsz == 0) {      /* last check */
-                       devstate_unlock(dev);
-                       have_devstate_lock = 0;
+               if (dev->wsz == 0)      /* last check */
                        schedule();
-               }
                set_current_state(current_state);
                remove_wait_queue(&dev->write_wait_q, &wait);
-               if (signal_pending(current)) {
-                       ret = -ERESTARTSYS;
+               if (dev->wsz == 0) {
+                       /* failure */
+                       if (signal_pending(current))
+                               ret = -EINTR;
                        goto up_out;
                }
-               if (!have_devstate_lock) {
-                       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-                               ret = -ERESTARTSYS;
-                               goto up_out;
-                       }
-                       have_devstate_lock = 1;
-               }
-               if (dev->task->wsz == 0)        /* should not occur */
-                       goto up_out;
        }
 
        if (copy_from_user(&wd, buf, count)) {
@@ -1091,29 +1051,26 @@ static ssize_t dsp_task_write_wd(struct file *file, const char *buf,
                goto up_out;
        }
 
-       spin_lock(&dev->task->wsz_lock);
-       if (dsp_mbsend(MBCMD(WDSND), dev->task->tid, wd) < 0) {
-               spin_unlock(&dev->task->wsz_lock);
+       spin_lock(&dev->wsz_lock);
+       if (mbcompose_send(WDSND, dev->task->tid, wd) < 0) {
+               spin_unlock(&dev->wsz_lock);
                goto up_out;
        }
        ret = count;
        if (rcvtyp_acv(dev->task->ttyp))
-               dev->task->wsz = 0;
-       spin_unlock(&dev->task->wsz_lock);
+               dev->wsz = 0;
+       spin_unlock(&dev->wsz_lock);
 
 up_out:
-       if (have_devstate_lock)
-               devstate_unlock(dev);
-       mutex_unlock(&dev->write_mutex);
+       taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
        return ret;
 }
 
-static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
+static ssize_t dsp_task_write_bk(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 {
        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        struct taskdev *dev = taskdev[minor];
-       int have_devstate_lock = 0;
        int ret = 0;
 
        if (count == 0) {
@@ -1129,45 +1086,30 @@ static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
                return -EINVAL;
        }
 
-       if (taskdev_lock_interruptible(dev, &dev->write_mutex))
-               return -ERESTARTSYS;
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-               ret = -ERESTARTSYS;
-               goto up_out;
-       }
-       have_devstate_lock = 1;
+       if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
+               return -ENODEV;
 
-       if (dev->task->wsz == 0) {
+       if (dev->wsz == 0) {
                long current_state;
                DECLARE_WAITQUEUE(wait, current);
 
                add_wait_queue(&dev->write_wait_q, &wait);
                current_state = current->state;
                set_current_state(TASK_INTERRUPTIBLE);
-               if (dev->task->wsz == 0) {      /* last check */
-                       devstate_unlock(dev);
-                       have_devstate_lock = 0;
+               if (dev->wsz == 0)      /* last check */
                        schedule();
-               }
                set_current_state(current_state);
                remove_wait_queue(&dev->write_wait_q, &wait);
-               if (signal_pending(current)) {
-                       ret = -ERESTARTSYS;
+               if (dev->wsz == 0) {
+                       /* failure */
+                       if (signal_pending(current))
+                               ret = -EINTR;
                        goto up_out;
                }
-               if (!have_devstate_lock) {
-                       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-                               ret = -ERESTARTSYS;
-                               goto up_out;
-                       }
-                       have_devstate_lock = 1;
-               }
-               if (dev->task->wsz == 0)        /* should not occur */
-                       goto up_out;
        }
 
-       if (count > dev->task->wsz)
-               count = dev->task->wsz;
+       if (count > dev->wsz)
+               count = dev->wsz;
 
        if (rcvtyp_pvt(dev->task->ttyp)) {
                /* private */
@@ -1175,17 +1117,17 @@ static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
                unsigned char *dst;
 
                if (dsp_mem_enable(ipbp) < 0) {
-                       ret = -ERESTARTSYS;
+                       ret = -EBUSY;
                        goto up_out;
                }
                dst = MKVIRT(ipbp->ah, ipbp->al);
                if (dsp_address_validate(dst, count, "task %s write buffer",
                                         dev->task->name) < 0) {
-                       ret = -ERESTARTSYS;
+                       ret = -EINVAL;
                        goto pv_out1;
                }
                if (dsp_mem_enable(dst) < 0) {
-                       ret = -ERESTARTSYS;
+                       ret = -EBUSY;
                        goto pv_out1;
                }
                if (copy_from_user_dsp(dst, buf, count)) {
@@ -1194,54 +1136,49 @@ static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
                }
                ipbp->c = count/2;
                ipbp->s = dev->task->tid;
-               spin_lock(&dev->task->wsz_lock);
-               if (dsp_mbsend(MBCMD(BKSNDP), dev->task->tid, 0) == 0) {
+               spin_lock(&dev->wsz_lock);
+               if (mbcompose_send(BKSNDP, dev->task->tid, 0) == 0) {
                        if (rcvtyp_acv(dev->task->ttyp))
-                               dev->task->wsz = 0;
+                               dev->wsz = 0;
                        ret = count;
                }
-               spin_unlock(&dev->task->wsz_lock);
+               spin_unlock(&dev->wsz_lock);
 pv_out2:
                dsp_mem_disable(dst);
 pv_out1:
                dsp_mem_disable(ipbp);
        } else {
                /* global */
-               struct ipbuf *ipbp;
-               unsigned short bid;
+               struct ipbuf_head *ipb_h;
 
                if (dsp_mem_enable_ipbuf() < 0) {
-                       ret = -ERESTARTSYS;
+                       ret = -EBUSY;
                        goto up_out;
                }
-               bid = get_free_ipbuf(dev->task->tid);
-               if (bid == OMAP_DSP_BID_NULL)
+               if ((ipb_h = get_free_ipbuf(dev->task->tid)) == NULL)
                        goto gb_out;
-               ipbp = ipbuf[bid];
-               if (copy_from_user_dsp(ipbp->d, buf, count)) {
-                       release_ipbuf(bid);
+               if (copy_from_user_dsp(ipb_h->p->d, buf, count)) {
+                       release_ipbuf(ipb_h);
                        ret = -EFAULT;
                        goto gb_out;
                }
-               ipbp->c  = count/2;
-               ipbp->sa = dev->task->tid;
-               spin_lock(&dev->task->wsz_lock);
-               if (dsp_mbsend(MBCMD(BKSND), dev->task->tid, bid) == 0) {
+               ipb_h->p->c  = count/2;
+               ipb_h->p->sa = dev->task->tid;
+               spin_lock(&dev->wsz_lock);
+               if (mbcompose_send(BKSND, dev->task->tid, ipb_h->bid) == 0) {
                        if (rcvtyp_acv(dev->task->ttyp))
-                               dev->task->wsz = 0;
+                               dev->wsz = 0;
                        ret = count;
                        ipb_bsycnt_inc(&ipbcfg);
                } else
-                       release_ipbuf(bid);
-               spin_unlock(&dev->task->wsz_lock);
+                       release_ipbuf(ipb_h);
+               spin_unlock(&dev->wsz_lock);
 gb_out:
                dsp_mem_disable_ipbuf();
        }
 
 up_out:
-       if (have_devstate_lock)
-               devstate_unlock(dev);
-       mutex_unlock(&dev->write_mutex);
+       taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
        return ret;
 }
 
@@ -1252,78 +1189,42 @@ static unsigned int dsp_task_poll(struct file * file, poll_table * wait)
        struct dsptask *task = dev->task;
        unsigned int mask = 0;
 
+       if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+               return 0;
        poll_wait(file, &dev->read_wait_q, wait);
        poll_wait(file, &dev->write_wait_q, wait);
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0)
-               return 0;
        if (sndtyp_psv(task->ttyp) ||
-           (sndtyp_wd(task->ttyp) && !fifo_empty(&task->rcvdt.fifo)) ||
-           (sndtyp_bk(task->ttyp) && !ipblink_empty(&task->rcvdt.bk.link)))
+           (sndtyp_wd(task->ttyp) && !fifo_empty(&dev->rcvdt.fifo)) ||
+           (sndtyp_bk(task->ttyp) && !ipblink_empty(&dev->rcvdt.bk.link)))
                mask |= POLLIN | POLLRDNORM;
-       if (task->wsz)
+       if (dev->wsz)
                mask |= POLLOUT | POLLWRNORM;
-       devstate_unlock(dev);
+       devstate_read_unlock(dev);
 
        return mask;
 }
 
-static int dsp_task_ioctl(struct inode *inode, struct file *file,
-                         unsigned int cmd, unsigned long arg)
+static int dsp_tctl_issue(struct taskdev *dev, u16 cmd, int argc, u16 argv[])
 {
-       unsigned int minor = MINOR(inode->i_rdev);
-       struct taskdev *dev = taskdev[minor];
-       struct mbcmd mb;
-       unsigned char tid;
+       int tctl_argc;
        struct mb_exarg mbarg, *mbargp;
-       int mbargc;
-       unsigned short mbargv[1];
        int interactive;
-       int ret;
-
-       /* LOCK / UNLOCK operations */
-       switch (cmd) {
-       case OMAP_DSP_TASK_IOCTL_LOCK:
-               return taskdev_lock(dev);
-       case OMAP_DSP_TASK_IOCTL_UNLOCK:
-               return taskdev_unlock(dev);
-       }
-
-       /*
-        * actually only interractive commands need to lock
-        * the mutex, but here all commands do it for simplicity.
-        */
-       if (taskdev_lock_interruptible(dev, &dev->ioctl_mutex))
-               return -ERESTARTSYS;
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-               ret = -ERESTARTSYS;
-               goto up_out;
-       }
+       u8 tid;
+       int ret = 0;
 
-       if ((cmd >= 0x0080) && (cmd < 0x0100)) {
-               /*
-                * 0x0080 - 0x00ff
-                * reserved for backward compatibility
-                * user-defined TCTL commands: no arg, non-interactive
-                */
-               printk(KERN_WARNING "omapdsp: "
-                      "TCTL commands in 0x0080 - 0x0100 are obsolete.\n"
-                      "they won't be supported in the future.\n");
-               mbargc = 0;
-               interactive = 0;
-       } else if (cmd < 0x8000) {
+       if (cmd < 0x8000) {
                /*
-                * 0x0000 - 0x7fff (except 0x0080 - 0x00ff)
+                * 0x0000 - 0x7fff
                 * system reserved TCTL commands
                 */
                switch (cmd) {
-               case OMAP_DSP_MBCMD_TCTL_TEN:
-               case OMAP_DSP_MBCMD_TCTL_TDIS:
-                       mbargc = 0;
+               case TCTL_TEN:
+               case TCTL_TDIS:
+                       tctl_argc = 0;
                        interactive = 0;
                        break;
                default:
-                       ret = -ENOIOCTLCMD;
-                       goto unlock_out;
+                       return -EINVAL;
                }
        }
        /*
@@ -1332,94 +1233,123 @@ static int dsp_task_ioctl(struct inode *inode, struct file *file,
         */
        else if (cmd < 0x8100) {
                /* 0x8000-0x80ff: no arg, non-interactive */
-               mbargc = 0;
+               tctl_argc = 0;
                interactive = 0;
        } else if (cmd < 0x8200) {
                /* 0x8100-0x81ff: 1 arg, non-interactive */
-               mbargc = 1;
-               mbargv[0] = arg & 0xffff;
+               tctl_argc = 1;
                interactive = 0;
        } else if (cmd < 0x9000) {
                /* 0x8200-0x8fff: reserved */
-               ret = -ENOIOCTLCMD;
-               goto unlock_out;
+               return -EINVAL;
        } else if (cmd < 0x9100) {
                /* 0x9000-0x90ff: no arg, interactive */
-               mbargc = 0;
+               tctl_argc = 0;
                interactive = 1;
        } else if (cmd < 0x9200) {
                /* 0x9100-0x91ff: 1 arg, interactive */
-               mbargc = 1;
-               mbargv[0] = arg & 0xffff;
+               tctl_argc = 1;
                interactive = 1;
-       } else if (cmd < 0x10000) {
-               /* 0x9200-0xffff: reserved */
-               ret =  -ENOIOCTLCMD;
-               goto unlock_out;
        } else {
-               /*
-                * 0x10000 -
-                * non TCTL ioctls
-                */
-               switch (cmd) {
-               case OMAP_DSP_TASK_IOCTL_BFLSH:
-                       ret = dsp_task_flush_buf(dev->task);
-                       break;
-               case OMAP_DSP_TASK_IOCTL_SETBSZ:
-                       ret = dsp_task_set_fifosz(dev->task, arg);
-                       break;
-               case OMAP_DSP_TASK_IOCTL_GETNAME:
-                       ret = 0;
-                       if (copy_to_user((void *)arg, dev->name,
-                                        strlen(dev->name) + 1))
-                               ret = -EFAULT;
-                       break;
-               default:
-                       ret = -ENOIOCTLCMD;
-               }
-               goto unlock_out;
+               /* 0x9200-0xffff: reserved */
+               return -EINVAL;
        }
 
+       /*
+        * if argc < 0, use tctl_argc as is.
+        * if argc >= 0, check arg count.
+        */
+       if ((argc >= 0) && (argc != tctl_argc))
+               return -EINVAL;
+
        /*
         * issue TCTL
         */
+       if (taskdev_lock_interruptible(dev, &dev->tctl_mutex))
+               return -EINTR;
+
        tid = dev->task->tid;
-       mbcmd_set(mb, MBCMD(TCTL), tid, cmd);
-       if (mbargc > 0) {
-               mbarg.argc = mbargc;
+       if (tctl_argc > 0) {
+               mbarg.argc = tctl_argc;
                mbarg.tid  = tid;
-               mbarg.argv = mbargv;
+               mbarg.argv = argv;
                mbargp = &mbarg;
        } else
                mbargp = NULL;
 
        if (interactive) {
-               dev->task->tctl_stat = -ERESTARTSYS;
-               devstate_unlock(dev);
+               dev->tctl_stat = -EINVAL;
 
-               dsp_mbcmd_send_and_wait_exarg(&mb, mbargp, &dev->ioctl_wait_q);
+               mbcompose_send_and_wait_exarg(TCTL, tid, cmd, mbargp,
+                                             &dev->tctl_wait_q);
                if (signal_pending(current)) {
-                       ret = -ERESTARTSYS;
+                       ret = -EINTR;
                        goto up_out;
                }
-               if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
-                       ret = -ERESTARTSYS;
-                       goto up_out;
-               }
-               ret = dev->task->tctl_stat;
-               if (ret < 0) {
+               if ((ret = dev->tctl_stat) < 0) {
                        printk(KERN_ERR "omapdsp: TCTL not responding.\n");
-                       goto unlock_out;
+                       goto up_out;
                }
-       } else {
-               dsp_mbcmd_send_exarg(&mb, mbargp);
+       } else
+               mbcompose_send_exarg(TCTL, tid, cmd, mbargp);
+
+up_out:
+       mutex_unlock(&dev->tctl_mutex);
+       return ret;
+}
+
+static int dsp_task_ioctl(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg)
+{
+       unsigned int minor = MINOR(inode->i_rdev);
+       struct taskdev *dev = taskdev[minor];
+       int ret;
+
+       if (cmd < 0x10000) {
+               /* issue TCTL */
+               u16 mbargv[1];
+
+               mbargv[0] = arg & 0xffff;
+               return dsp_tctl_issue(dev, cmd, -1, mbargv);
+       }
+
+       /* non TCTL ioctls */
+       switch (cmd) {
+
+       case TASK_IOCTL_LOCK:
+               ret = taskdev_lock(dev);
+               break;
+
+       case TASK_IOCTL_UNLOCK:
+               ret = taskdev_unlock(dev);
+               break;
+
+       case TASK_IOCTL_BFLSH:  
+               if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+                       return -ENODEV;
+               ret = taskdev_flush_buf(dev);
+               taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+               break;
+
+       case TASK_IOCTL_SETBSZ:
+               if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+                       return -ENODEV;
+               ret = taskdev_set_fifosz(dev, arg);
+               taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+               break;
+
+       case TASK_IOCTL_GETNAME:
                ret = 0;
+               if (copy_to_user((void __user *)arg, dev->name,
+                                strlen(dev->name) + 1))
+                       ret = -EFAULT;
+               break;
+
+       default:
+               ret = -ENOIOCTLCMD;
+
        }
 
-unlock_out:
-       devstate_unlock(dev);
-up_out:
-       mutex_unlock(&dev->ioctl_mutex);
        return ret;
 }
 
@@ -1429,7 +1359,7 @@ static void dsp_task_mmap_open(struct vm_area_struct *vma)
        struct dsptask *task;
        size_t len = vma->vm_end - vma->vm_start;
 
-       BUG_ON(!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED));
+       BUG_ON(!(dev->state & TASKDEV_ST_ATTACHED));
        task = dev->task;
        exmap_use(task->map_base, len);
 }
@@ -1440,7 +1370,7 @@ static void dsp_task_mmap_close(struct vm_area_struct *vma)
        struct dsptask *task;
        size_t len = vma->vm_end - vma->vm_start;
 
-       BUG_ON(!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED));
+       BUG_ON(!(dev->state & TASKDEV_ST_ATTACHED));
        task = dev->task;
        exmap_unuse(task->map_base, len);
 }
@@ -1471,8 +1401,8 @@ static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
        struct dsptask *task;
        int ret = 0;
 
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0)
-               return -ERESTARTSYS;
+       if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+               return -ENODEV;
        task = dev->task;
 
        /*
@@ -1525,7 +1455,7 @@ static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
        exmap_use(task->map_base, vma->vm_end - vma->vm_start);
 
 unlock_out:
-       devstate_unlock(dev);
+       devstate_read_unlock(dev);
        return ret;
 }
 
@@ -1537,49 +1467,84 @@ static int dsp_task_open(struct inode *inode, struct file *file)
 
        if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL))
                return -ENODEV;
-       if (devstate_lock(dev, OMAP_DSP_DEVSTATE_NOTASK |
-                              OMAP_DSP_DEVSTATE_ATTACHED) < 0)
-               return -ERESTARTSYS;
-#ifndef CONFIG_OMAP_DSP_TASK_MULTIOPEN
-       if (dev->usecount > 0) {
-               ret = -EBUSY;
-               goto unlock_out;
-       }
-#endif
 
-       if (dev->state & OMAP_DSP_DEVSTATE_NOTASK) {
-               dev->state = OMAP_DSP_DEVSTATE_ADDREQ;
-               /* wake up twch daemon for tadd */
-               dsp_twch_touch();
-               devstate_unlock(dev);
-               if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED |
-                                      OMAP_DSP_DEVSTATE_ADDFAIL) < 0) {
-                       spin_lock(&dev->state_lock);
-                       if (dev->state & OMAP_DSP_DEVSTATE_ADDREQ)
-                               dev->state = OMAP_DSP_DEVSTATE_NOTASK;
-                       spin_unlock(&dev->state_lock);
-                       return -ERESTARTSYS;
-               }
-               if (dev->state & OMAP_DSP_DEVSTATE_ADDFAIL) {
-                       printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
-                              dev->name);
-                       ret = -EBUSY;
-                       dev->state = OMAP_DSP_DEVSTATE_NOTASK;
-                       wake_up_interruptible_all(&dev->state_wait_q);
-                       goto unlock_out;
+restart:
+       mutex_lock(&dev->usecount_mutex);
+       down_write(&dev->state_sem);
+
+       /* state can be NOTASK, ATTACHED/FREEZED, KILLING, GARBAGE or INVALID here. */
+       switch (dev->state & TASKDEV_ST_STATE_MASK) {
+               case TASKDEV_ST_NOTASK:
+                       break;
+               case TASKDEV_ST_ATTACHED:
+                       goto attached;
+
+               case TASKDEV_ST_INVALID:
+                       up_write(&dev->state_sem);
+                       mutex_unlock(&dev->usecount_mutex);
+                       return -ENODEV;
+
+               case TASKDEV_ST_FREEZED:
+               case TASKDEV_ST_KILLING:
+               case TASKDEV_ST_GARBAGE:
+                       /* on the kill process. wait until it becomes NOTASK. */
+                       up_write(&dev->state_sem);
+                       mutex_unlock(&dev->usecount_mutex);
+                       if (devstate_write_lock(dev, TASKDEV_ST_NOTASK) < 0)
+                               return -EINTR;
+                       devstate_write_unlock(dev);
+                       goto restart;
+       }
+
+       /* NOTASK */
+       dev->state = TASKDEV_ST_ADDREQ;
+       /* wake up twch daemon for tadd */
+       dsp_twch_touch();
+       up_write(&dev->state_sem);
+       if (devstate_write_lock(dev, TASKDEV_ST_ATTACHED |
+                                    TASKDEV_ST_ADDFAIL) < 0) {
+               /* cancelled */
+               if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
+                       mutex_unlock(&dev->usecount_mutex);
+                       /* out of control ??? */
+                       return -EINTR;
                }
+               dev->state = TASKDEV_ST_NOTASK;
+               ret = -EINTR;
+               goto change_out;
+       }
+       if (dev->state & TASKDEV_ST_ADDFAIL) {
+               printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
+                      dev->name);
+               ret = -EBUSY;
+               dev->state = TASKDEV_ST_NOTASK;
+               goto change_out;
        }
 
-       /* state_lock covers usecount, proc_list as well. */
+attached:
+       /* ATTACHED */
+#ifndef CONFIG_OMAP_DSP_TASK_MULTIOPEN
+       if (dev->usecount > 0) {
+               up_write(&dev->state_sem);
+               return -EBUSY;
+       }
+#endif
        dev->usecount++;
-       proc_list_add(&dev->proc_list, current);
+       proc_list_add(&dev->proc_list_lock, &dev->proc_list, current, file);
        file->f_op = &dev->fops;
-       devstate_unlock(dev);
+       up_write(&dev->state_sem);
+       mutex_unlock(&dev->usecount_mutex);
 
+#ifdef DSP_PTE_FREE    /* not used currently. */
+       dsp_map_update(current);
+       dsp_cur_users_add(current);
+#endif /* DSP_PTE_FREE */
        return 0;
 
-unlock_out:
-       devstate_unlock(dev);
+change_out:
+       wake_up_interruptible_all(&dev->state_wait_q);
+       up_write(&dev->state_sem);
+       mutex_unlock(&dev->usecount_mutex);
        return ret;
 }
 
@@ -1588,39 +1553,48 @@ static int dsp_task_release(struct inode *inode, struct file *file)
        unsigned int minor = MINOR(inode->i_rdev);
        struct taskdev *dev = taskdev[minor];
 
-       /* state_lock covers usecount, proc_list as well. */
-       spin_lock(&dev->state_lock);
+#ifdef DSP_PTE_FREE    /* not used currently. */
+       dsp_cur_users_del(current);
+#endif /* DSP_PTE_FREE */
+
+       if (has_taskdev_lock(dev))
+               taskdev_unlock(dev);
+
+       proc_list_del(&dev->proc_list_lock, &dev->proc_list, current, file);
+       mutex_lock(&dev->usecount_mutex);
+       if (--dev->usecount > 0) {
+               /* other processes are using this device. no state change. */
+               mutex_unlock(&dev->usecount_mutex);
+               return 0;
+       }
+
+       /* usecount == 0 */
+       down_write(&dev->state_sem);
 
-       /* state can be ATTACHED, KILLING or GARBAGE here. */
-       switch (dev->state & OMAP_DSP_DEVSTATE_STATE_MASK) {
+       /* state can be ATTACHED/FREEZED, KILLING or GARBAGE here. */
+       switch (dev->state & TASKDEV_ST_STATE_MASK) {
 
-       case OMAP_DSP_DEVSTATE_KILLING:
-               dev->usecount--;
+       case TASKDEV_ST_KILLING:
                break;
 
-       case OMAP_DSP_DEVSTATE_GARBAGE:
-               if(--dev->usecount == 0) {
-                       dev->state = OMAP_DSP_DEVSTATE_NOTASK;
-                       wake_up_interruptible_all(&dev->state_wait_q);
-               }
+       case TASKDEV_ST_GARBAGE:
+               dev->state = TASKDEV_ST_NOTASK;
+               wake_up_interruptible_all(&dev->state_wait_q);
                break;
 
-       case OMAP_DSP_DEVSTATE_ATTACHED:
-               if (dev->lock_pid == current->pid)
-                       taskdev_unlock(dev);
-               proc_list_del(&dev->proc_list, current);
-               if (--dev->usecount == 0) {
-                       if (minor >= n_task) {  /* dynamic task */
-                               dev->state = OMAP_DSP_DEVSTATE_DELREQ;
-                               /* wake up twch daemon for tdel */
-                               dsp_twch_touch();
-                       }
+       case TASKDEV_ST_ATTACHED:
+       case TASKDEV_ST_FREEZED:
+               if (is_dynamic_task(minor)) {
+                       dev->state = TASKDEV_ST_DELREQ;
+                       /* wake up twch daemon for tdel */
+                       dsp_twch_touch();
                }
                break;
 
        }
 
-       spin_unlock(&dev->state_lock);
+       up_write(&dev->state_sem);
+       mutex_unlock(&dev->usecount_mutex);
        return 0;
 }
 
@@ -1632,102 +1606,166 @@ int dsp_mkdev(char *name)
        struct taskdev *dev;
        int status;
        unsigned char minor;
+       int ret;
 
-       if (!dsp_is_ready()) {
+       if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
                printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
                return -EINVAL;
        }
+
+       if (mutex_lock_interruptible(&devmgr_lock))
+               return -EINTR;
+
+       /* naming check */
+       for (minor = 0; minor < TASKDEV_MAX; minor++) {
+               if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
+                       printk(KERN_ERR
+                              "omapdsp: task device name %s is already "
+                              "in use.\n", name);
+                       ret = -EINVAL;
+                       goto out;
+               }
+       }
+
+       /* find free minor number */
        for (minor = n_task; minor < TASKDEV_MAX; minor++) {
                if (taskdev[minor] == NULL)
                        goto do_make;
        }
        printk(KERN_ERR "omapdsp: Too many task devices.\n");
-       return -EBUSY;
+       ret = -EBUSY;
+       goto out;
 
 do_make:
-       if ((dev = kmalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL)
-               return -ENOMEM;
-       memset(dev, 0, sizeof(struct taskdev));
+       if ((dev = kzalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL) {
+               ret = -ENOMEM;
+               goto out;
+       }
        if ((status = taskdev_init(dev, name, minor)) < 0) {
                kfree(dev);
-               return status;
+               ret = status;
+               goto out;
        }
-       return minor;
+       ret = minor;
+
+out:
+       mutex_unlock(&devmgr_lock);
+       return ret;
 }
 
 int dsp_rmdev(char *name)
 {
        unsigned char minor;
+       int status;
        int ret;
 
-       if (!dsp_is_ready()) {
+       if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
                printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
                return -EINVAL;
        }
+
+       if (mutex_lock_interruptible(&devmgr_lock))
+               return -EINTR;
+
+       /* find in dynamic devices */
        for (minor = n_task; minor < TASKDEV_MAX; minor++) {
+               if (taskdev[minor] && !strcmp(taskdev[minor]->name, name))
+                       goto do_remove;
+       }
+
+       /* find in static devices */
+       for (minor = 0; minor < n_task; minor++) {
                if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
-                       if ((ret = dsp_rmdev_minor(minor)) < 0)
-                               return ret;
-                       return minor;
+                       printk(KERN_ERR
+                              "omapdsp: task device %s is static.\n", name);
+                       ret = -EINVAL;
+                       goto out;
                }
        }
+
+       printk(KERN_ERR "omapdsp: task device %s not found.\n", name);
        return -EINVAL;
+
+do_remove:
+       ret = minor;
+       if ((status = dsp_rmdev_minor(minor)) < 0)
+               ret = status;
+out:
+       mutex_unlock(&devmgr_lock);
+       return ret;
 }
 
 static int dsp_rmdev_minor(unsigned char minor)
 {
        struct taskdev *dev = taskdev[minor];
 
-       spin_lock(&dev->state_lock);
+       while (!down_write_trylock(&dev->state_sem)) {
+               down_read(&dev->state_sem);
+               if (dev->state & (TASKDEV_ST_ATTACHED |
+                                 TASKDEV_ST_FREEZED)) {
+                       /*
+                        * task is working. kill it.
+                        * ATTACHED -> FREEZED can be changed under
+                        * down_read of state_sem..
+                        */
+                       dev->state = TASKDEV_ST_FREEZED;
+                       wake_up_interruptible_all(&dev->read_wait_q);
+                       wake_up_interruptible_all(&dev->write_wait_q);
+                       wake_up_interruptible_all(&dev->tctl_wait_q);
+               }
+               up_read(&dev->state_sem);
+               schedule();
+       }
 
-       switch (dev->state & OMAP_DSP_DEVSTATE_STATE_MASK) {
+       switch (dev->state & TASKDEV_ST_STATE_MASK) {
 
-       case OMAP_DSP_DEVSTATE_NOTASK:
+       case TASKDEV_ST_NOTASK:
                /* fine */
-               break;
+               goto notask;
 
-       case OMAP_DSP_DEVSTATE_ATTACHED:
+       case TASKDEV_ST_ATTACHED:
+       case TASKDEV_ST_FREEZED:
                /* task is working. kill it. */
-               dev->state = OMAP_DSP_DEVSTATE_KILLING;
-               proclist_send_sigbus(&dev->proc_list);
-               spin_unlock(&dev->state_lock);
-               dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_KILL);
+               dev->state = TASKDEV_ST_KILLING;
+               up_write(&dev->state_sem);
+               dsp_tdel_bh(dev, TDEL_KILL);
                goto invalidate;
 
-       case OMAP_DSP_DEVSTATE_ADDREQ:
+       case TASKDEV_ST_ADDREQ:
                /* open() is waiting. drain it. */
-               dev->state = OMAP_DSP_DEVSTATE_ADDFAIL;
+               dev->state = TASKDEV_ST_ADDFAIL;
                wake_up_interruptible_all(&dev->state_wait_q);
                break;
 
-       case OMAP_DSP_DEVSTATE_DELREQ:
+       case TASKDEV_ST_DELREQ:
                /* nobody is waiting. */
-               dev->state = OMAP_DSP_DEVSTATE_NOTASK;
+               dev->state = TASKDEV_ST_NOTASK;
                wake_up_interruptible_all(&dev->state_wait_q);
                break;
 
-       case OMAP_DSP_DEVSTATE_ADDING:
-       case OMAP_DSP_DEVSTATE_DELING:
-       case OMAP_DSP_DEVSTATE_KILLING:
-       case OMAP_DSP_DEVSTATE_GARBAGE:
-       case OMAP_DSP_DEVSTATE_ADDFAIL:
+       case TASKDEV_ST_ADDING:
+       case TASKDEV_ST_DELING:
+       case TASKDEV_ST_KILLING:
+       case TASKDEV_ST_GARBAGE:
+       case TASKDEV_ST_ADDFAIL:
                /* transient state. wait for a moment. */
                break;
 
        }
 
-       spin_unlock(&dev->state_lock);
+       up_write(&dev->state_sem);
 
 invalidate:
        /* wait for some time and hope the state is settled */
-       devstate_lock_timeout(dev, OMAP_DSP_DEVSTATE_NOTASK, HZ);
-       if (!(dev->state & OMAP_DSP_DEVSTATE_NOTASK)) {
+       devstate_read_lock_timeout(dev, TASKDEV_ST_NOTASK, 5 * HZ);
+       if (!(dev->state & TASKDEV_ST_NOTASK)) {
                printk(KERN_WARNING
                       "omapdsp: illegal device state (%s) on rmdev %s.\n",
                       devstate_name(dev->state), dev->name);
        }
-       dev->state = OMAP_DSP_DEVSTATE_INVALID;
-       devstate_unlock(dev);
+notask:
+       dev->state = TASKDEV_ST_INVALID;
+       devstate_read_unlock(dev);
 
        taskdev_delete(minor);
        kfree(dev);
@@ -1749,25 +1787,26 @@ static void dsptask_dev_release(struct device *dev)
 
 static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
 {
-       struct class_device *cdev;
-
        taskdev[minor] = dev;
 
+       spin_lock_init(&dev->proc_list_lock);
        INIT_LIST_HEAD(&dev->proc_list);
        init_waitqueue_head(&dev->read_wait_q);
        init_waitqueue_head(&dev->write_wait_q);
-       init_waitqueue_head(&dev->ioctl_wait_q);
+       init_waitqueue_head(&dev->tctl_wait_q);
        mutex_init(&dev->read_mutex);
        mutex_init(&dev->write_mutex);
-       mutex_init(&dev->ioctl_mutex);
+       mutex_init(&dev->tctl_mutex);
        mutex_init(&dev->lock);
+       spin_lock_init(&dev->wsz_lock);
+       dev->tctl_ret = -EINVAL;
        dev->lock_pid = 0;
 
-       strncpy(dev->name, name, OMAP_DSP_TNM_LEN);
-       dev->name[OMAP_DSP_TNM_LEN-1] = '\0';
-       dev->state = (minor < n_task) ? OMAP_DSP_DEVSTATE_ATTACHED :
-                                       OMAP_DSP_DEVSTATE_NOTASK;
+       strncpy(dev->name, name, TNM_LEN);
+       dev->name[TNM_LEN-1] = '\0';
+       dev->state = (minor < n_task) ? TASKDEV_ST_ATTACHED : TASKDEV_ST_NOTASK;
        dev->usecount = 0;
+       mutex_init(&dev->usecount_mutex);
        memcpy(&dev->fops, &dsp_task_fops, sizeof(struct file_operations));
 
        dev->dev.parent = &dsp_device.dev;
@@ -1778,12 +1817,12 @@ static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
        device_create_file(&dev->dev, &dev_attr_devname);
        device_create_file(&dev->dev, &dev_attr_devstate);
        device_create_file(&dev->dev, &dev_attr_proc_list);
-       cdev = class_device_create(dsp_task_class, NULL,
-                                  MKDEV(OMAP_DSP_TASK_MAJOR, minor),
-                                  NULL, "dsptask%d", minor);
+       class_device_create(dsp_task_class, NULL,
+                           MKDEV(OMAP_DSP_TASK_MAJOR, minor),
+                           NULL, "dsptask%d", minor);
 
        init_waitqueue_head(&dev->state_wait_q);
-       spin_lock_init(&dev->state_lock);
+       init_rwsem(&dev->state_sem);
 
        return 0;
 }
@@ -1799,16 +1838,14 @@ static void taskdev_delete(unsigned char minor)
        device_remove_file(&dev->dev, &dev_attr_proc_list);
        class_device_destroy(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor));
        device_unregister(&dev->dev);
-       proc_list_flush(&dev->proc_list);
+       proc_list_flush(&dev->proc_list_lock, &dev->proc_list);
        taskdev[minor] = NULL;
 }
 
-static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
+static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
 {
-       unsigned short ttyp = task->ttyp;
+       u16 ttyp = task->ttyp;
 
-       dev->task = task;
-       task->dev = dev;
        dev->fops.read =
                sndtyp_acv(ttyp) ?
                        sndtyp_wd(ttyp) ? dsp_task_read_wd_acv:
@@ -1816,9 +1853,31 @@ static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
                /* sndtyp_psv */
                        sndtyp_wd(ttyp) ? dsp_task_read_wd_psv:
                        /* sndtyp_bk */   dsp_task_read_bk_psv;
+       if (sndtyp_wd(ttyp)) {
+               /* word */
+               size_t fifosz;
+
+               fifosz = sndtyp_psv(ttyp) ? 2 : /* passive */
+                                           32; /* active */
+               if (init_fifo(&dev->rcvdt.fifo, fifosz) < 0) {
+                       printk(KERN_ERR
+                              "omapdsp: unable to allocate receive buffer. "
+                              "(%d bytes for %s)\n", fifosz, dev->name);
+                       return -ENOMEM;
+               }
+       } else {
+               /* block */
+               INIT_IPBLINK(&dev->rcvdt.bk.link);
+               dev->rcvdt.bk.rp = 0;
+       }
+
        dev->fops.write =
                rcvtyp_wd(ttyp) ? dsp_task_write_wd:
                /* rcvbyp_bk */   dsp_task_write_bk;
+       dev->wsz = rcvtyp_acv(ttyp) ? 0 :               /* active */
+                  rcvtyp_wd(ttyp)  ? 2 :               /* passive word */
+                                     ipbcfg.lsz*2;     /* passive block */
+
        if (task->map_length)
                dev->fops.mmap = dsp_task_mmap;
 
@@ -1832,11 +1891,16 @@ static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
        device_create_file(&dev->dev, &dev_attr_wsz);
        if (task->map_length)
                device_create_file(&dev->dev, &dev_attr_mmap);
+
+       dev->task = task;
+       task->dev = dev;
+
+       return 0;
 }
 
 static void taskdev_detach_task(struct taskdev *dev)
 {
-       unsigned short ttyp = dev->task->ttyp;
+       u16 ttyp = dev->task->ttyp;
 
        device_remove_file(&dev->dev, &dev_attr_taskname);
        device_remove_file(&dev->dev, &dev_attr_ttyp);
@@ -1849,52 +1913,46 @@ static void taskdev_detach_task(struct taskdev *dev)
        if (dev->task->map_length)
                device_remove_file(&dev->dev, &dev_attr_mmap);
 
-       if (dev->task) {
-               dev->task = NULL;
-               dev->fops.read = NULL;
-               dev->fops.write = NULL;
-               printk(KERN_INFO "omapdsp: taskdev %s disabled.\n", dev->name);
-       }
+       dev->fops.read = NULL;
+       taskdev_flush_buf(dev);
+       if (sndtyp_wd(ttyp))
+               free_fifo(&dev->rcvdt.fifo);
+
+       dev->fops.write = NULL;
+       dev->wsz = 0;
+
+       printk(KERN_INFO "omapdsp: taskdev %s disabled.\n", dev->name);
+       dev->task = NULL;
 }
 
 /*
  * tadd / tdel / tkill
  */
-int dsp_tadd(unsigned char minor, unsigned long adr)
+static int dsp_tadd(struct taskdev *dev, dsp_long_t adr)
 {
-       struct taskdev *dev;
        struct dsptask *task;
-       struct mbcmd mb;
        struct mb_exarg arg;
-       unsigned char tid, tid_response;
-       unsigned short argv[2];
-       int ret = minor;
-
-       if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
-               printk(KERN_ERR
-                      "omapdsp: no task device with minor %d\n", minor);
-               return -EINVAL;
-       }
+       u8 tid, tid_response;
+       u16 argv[2];
+       int ret = 0;
 
-       spin_lock(&dev->state_lock);
-       if (!(dev->state & OMAP_DSP_DEVSTATE_ADDREQ)) {
+       if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
                printk(KERN_ERR
                       "omapdsp: taskdev %s is not requesting for tadd. "
                       "(state is %s)\n", dev->name, devstate_name(dev->state));
-               spin_unlock(&dev->state_lock);
                return -EINVAL;
        }
-       dev->state = OMAP_DSP_DEVSTATE_ADDING;
-       spin_unlock(&dev->state_lock);
+       dev->state = TASKDEV_ST_ADDING;
+       devstate_write_unlock(dev);
 
-       if (adr == OMAP_DSP_TADD_ABORTADR) {
+       if (adr == TADD_ABORTADR) {
                /* aborting tadd intentionally */
                printk(KERN_INFO "omapdsp: tadd address is ABORTADR.\n");
                goto fail_out;
        }
        if (adr >= DSPSPACE_SIZE) {
                printk(KERN_ERR
-                      "omapdsp: illegal address 0x%08lx for tadd\n", adr);
+                      "omapdsp: illegal address 0x%08x for tadd\n", adr);
                ret = -EINVAL;
                goto fail_out;
        }
@@ -1904,13 +1962,12 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
        argv[1] = adr & 0xffff; /* addrl */
 
        if (mutex_lock_interruptible(&cfg_lock)) {
-               ret = -ERESTARTSYS;
+               ret = -EINTR;
                goto fail_out;
        }
-       cfg_tid = OMAP_DSP_TID_ANON;
-       cfg_cmd = MBCMD(TADD);
-       mbcmd_set(mb, MBCMD(TADD), 0, 0);
-       arg.tid  = OMAP_DSP_TID_ANON;
+       cfg_tid = TID_ANON;
+       cfg_cmd = MBX_CMD_DSP_TADD;
+       arg.tid  = TID_ANON;
        arg.argc = 2;
        arg.argv = argv;
 
@@ -1926,7 +1983,7 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
        cfg_cmd = 0;
        mutex_unlock(&cfg_lock);
 
-       if (tid == OMAP_DSP_TID_ANON) {
+       if (tid == TID_ANON) {
                printk(KERN_ERR "omapdsp: tadd failed!\n");
                ret = -EINVAL;
                goto fail_out;
@@ -1936,15 +1993,13 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
                ret = -EINVAL;
                goto fail_out;
        }
-       if ((task = kmalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
+       if ((task = kzalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
                ret = -ENOMEM;
                goto del_out;
        }
-       memset(task, 0, sizeof(struct dsptask));
 
        if ((ret = dsp_task_config(task, tid)) < 0)
                goto free_out;
-       taskdev_attach_task(dev, task);
 
        if (strcmp(dev->name, task->name)) {
                printk(KERN_ERR
@@ -1954,11 +2009,14 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
                goto free_out;
        }
 
+       if ((ret = taskdev_attach_task(dev, task)) < 0)
+               goto free_out;
+
        dsp_task_init(task);
        printk(KERN_INFO "omapdsp: taskdev %s enabled.\n", dev->name);
-       dev->state = OMAP_DSP_DEVSTATE_ATTACHED;
+       dev->state = TASKDEV_ST_ATTACHED;
        wake_up_interruptible_all(&dev->state_wait_q);
-       return minor;
+       return 0;
 
 free_out:
        kfree(task);
@@ -1966,19 +2024,18 @@ free_out:
 del_out:
        printk(KERN_ERR "omapdsp: deleting the task...\n");
 
-       dev->state = OMAP_DSP_DEVSTATE_DELING;
+       dev->state = TASKDEV_ST_DELING;
 
        if (mutex_lock_interruptible(&cfg_lock)) {
                printk(KERN_ERR "omapdsp: aborting tdel process. "
                                "DSP side could be corrupted.\n");
                goto fail_out;
        }
-       cfg_tid = OMAP_DSP_TID_ANON;
-       cfg_cmd = MBCMD(TDEL);
-       mbcmd_set(mb, MBCMD(TDEL), tid, OMAP_DSP_MBCMD_TDEL_KILL);
-       dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
+       cfg_tid = TID_ANON;
+       cfg_cmd = MBX_CMD_DSP_TDEL;
+       mbcompose_send_and_wait(TDEL, tid, TDEL_KILL, &cfg_wait_q);
        tid_response = cfg_tid;
-       cfg_tid = OMAP_DSP_TID_ANON;
+       cfg_tid = TID_ANON;
        cfg_cmd = 0;
        mutex_unlock(&cfg_lock);
 
@@ -1987,84 +2044,161 @@ del_out:
                                "DSP side could be corrupted.\n");
 
 fail_out:
-       dev->state = OMAP_DSP_DEVSTATE_ADDFAIL;
+       dev->state = TASKDEV_ST_ADDFAIL;
        wake_up_interruptible_all(&dev->state_wait_q);
        return ret;
 }
 
-int dsp_tdel(unsigned char minor)
+int dsp_tadd_minor(unsigned char minor, dsp_long_t adr)
 {
        struct taskdev *dev;
+       int status;
+       int ret;
+
+       if (mutex_lock_interruptible(&devmgr_lock))
+               return -EINTR;
 
        if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
                printk(KERN_ERR
                       "omapdsp: no task device with minor %d\n", minor);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
-       spin_lock(&dev->state_lock);
-       if (!(dev->state & OMAP_DSP_DEVSTATE_DELREQ)) {
+       ret = minor;
+       if ((status = dsp_tadd(dev, adr)) < 0)
+               ret = status;
+
+out:
+       mutex_unlock(&devmgr_lock);
+       return ret;
+}
+
+static int dsp_tdel(struct taskdev *dev)
+{
+       if (!devstate_write_lock_and_test(dev, TASKDEV_ST_DELREQ)) {
                printk(KERN_ERR
                       "omapdsp: taskdev %s is not requesting for tdel. "
                       "(state is %s)\n", dev->name, devstate_name(dev->state));
-               spin_unlock(&dev->state_lock);
                return -EINVAL;
        }
-       dev->state = OMAP_DSP_DEVSTATE_DELING;
-       spin_unlock(&dev->state_lock);
+       dev->state = TASKDEV_ST_DELING;
+       devstate_write_unlock(dev);
 
-       return dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_SAFE);
+       return dsp_tdel_bh(dev, TDEL_SAFE);
 }
 
-int dsp_tkill(unsigned char minor)
+int dsp_tdel_minor(unsigned char minor)
 {
        struct taskdev *dev;
+       int status;
+       int ret;
+
+       if (mutex_lock_interruptible(&devmgr_lock))
+               return -EINTR;
 
        if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
                printk(KERN_ERR
                       "omapdsp: no task device with minor %d\n", minor);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = minor;
+       if ((status = dsp_tdel(dev)) < 0)
+               ret = status;
+
+out:
+       mutex_unlock(&devmgr_lock);
+       return ret;
+}
+
+static int dsp_tkill(struct taskdev *dev)
+{
+       while (!down_write_trylock(&dev->state_sem)) {
+               if (!devstate_read_lock_and_test(dev, (TASKDEV_ST_ATTACHED |
+                                                      TASKDEV_ST_FREEZED))) {
+                       printk(KERN_ERR
+                              "omapdsp: task has not been attached for "
+                              "taskdev %s\n", dev->name);
+                       return -EINVAL;
+               }
+               /* ATTACHED -> FREEZED can be changed under read semaphore. */
+               dev->state = TASKDEV_ST_FREEZED;
+               wake_up_interruptible_all(&dev->read_wait_q);
+               wake_up_interruptible_all(&dev->write_wait_q);
+               wake_up_interruptible_all(&dev->tctl_wait_q);
+               devstate_read_unlock(dev);
+               schedule();
        }
-       spin_lock(&dev->state_lock);
-       if (!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED)) {
+
+       if (!(dev->state & (TASKDEV_ST_ATTACHED |
+                           TASKDEV_ST_FREEZED))) {
                printk(KERN_ERR
                       "omapdsp: task has not been attached for taskdev %s\n",
                       dev->name);
-               spin_unlock(&dev->state_lock);
+               devstate_write_unlock(dev);
+               return -EINVAL;
+       }
+       if (!is_dynamic_task(dev->task->tid)) {
+               printk(KERN_ERR "omapdsp: task %s is not a dynamic task.\n",
+                      dev->name);
+               devstate_write_unlock(dev);
                return -EINVAL;
        }
-       dev->state = OMAP_DSP_DEVSTATE_KILLING;
-       proclist_send_sigbus(&dev->proc_list);
-       spin_unlock(&dev->state_lock);
+       dev->state = TASKDEV_ST_KILLING;
+       devstate_write_unlock(dev);
 
-       return dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_KILL);
+       return dsp_tdel_bh(dev, TDEL_KILL);
 }
 
-static int dsp_tdel_bh(unsigned char minor, unsigned short type)
+int dsp_tkill_minor(unsigned char minor)
+{
+       struct taskdev *dev;
+       int status;
+       int ret;
+
+       if (mutex_lock_interruptible(&devmgr_lock))
+               return -EINTR;
+
+       if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
+               printk(KERN_ERR
+                      "omapdsp: no task device with minor %d\n", minor);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = minor;
+       if ((status = dsp_tkill(dev)) < 0)
+               ret = status;
+
+out:
+       mutex_unlock(&devmgr_lock);
+       return ret;
+}
+
+static int dsp_tdel_bh(struct taskdev *dev, u16 type)
 {
-       struct taskdev *dev = taskdev[minor];
        struct dsptask *task;
-       struct mbcmd mb;
-       unsigned char tid, tid_response;
-       int ret = minor;
+       u8 tid, tid_response;
+       int ret = 0;
 
        task = dev->task;
        tid = task->tid;
        if (mutex_lock_interruptible(&cfg_lock)) {
-               if (type == OMAP_DSP_MBCMD_TDEL_SAFE) {
-                       dev->state = OMAP_DSP_DEVSTATE_DELREQ;
-                       return -ERESTARTSYS;
+               if (type == TDEL_SAFE) {
+                       dev->state = TASKDEV_ST_DELREQ;
+                       return -EINTR;
                } else {
-                       tid_response = OMAP_DSP_TID_ANON;
-                       ret = -ERESTARTSYS;
+                       tid_response = TID_ANON;
+                       ret = -EINTR;
                        goto detach_out;
                }
        }
-       cfg_tid = OMAP_DSP_TID_ANON;
-       cfg_cmd = MBCMD(TDEL);
-       mbcmd_set(mb, MBCMD(TDEL), tid, type);
-       dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
+       cfg_tid = TID_ANON;
+       cfg_cmd = MBX_CMD_DSP_TDEL;
+       mbcompose_send_and_wait(TDEL, tid, type, &cfg_wait_q);
        tid_response = cfg_tid;
-       cfg_tid = OMAP_DSP_TID_ANON;
+       cfg_tid = TID_ANON;
        cfg_cmd = 0;
        mutex_unlock(&cfg_lock);
 
@@ -2075,14 +2209,14 @@ detach_out:
 
        if (tid_response != tid) {
                printk(KERN_ERR "omapdsp: %s failed!\n",
-                      (type == OMAP_DSP_MBCMD_TDEL_SAFE) ? "tdel" : "tkill");
+                      (type == TDEL_SAFE) ? "tdel" : "tkill");
                ret = -EINVAL;
        }
-       spin_lock(&dev->state_lock);
-       dev->state = (dev->usecount > 0) ? OMAP_DSP_DEVSTATE_GARBAGE :
-                                          OMAP_DSP_DEVSTATE_NOTASK;
+       down_write(&dev->state_sem);
+       dev->state = (dev->usecount > 0) ? TASKDEV_ST_GARBAGE :
+                                          TASKDEV_ST_NOTASK;
        wake_up_interruptible_all(&dev->state_wait_q);
-       spin_unlock(&dev->state_lock);
+       up_write(&dev->state_sem);
 
        return ret;
 }
@@ -2094,18 +2228,18 @@ long taskdev_state_stale(unsigned char minor)
 {
        if (taskdev[minor]) {
                long state = taskdev[minor]->state;
-               taskdev[minor]->state |= OMAP_DSP_DEVSTATE_STALE;
+               taskdev[minor]->state |= TASKDEV_ST_STALE;
                return state;
        } else
-               return OMAP_DSP_DEVSTATE_NOTASK;
+               return TASKDEV_ST_NOTASK;
 }
 
 /*
- * functions called from mailbox1 interrupt routine
+ * functions called from mailbox interrupt routine
  */
-void mbx1_wdsnd(struct mbcmd *mb)
+void mbx_wdsnd(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
+       u8 tid = mb->cmd_l;
        struct dsptask *task = dsptask[tid];
 
        if ((tid >= TASKDEV_MAX) || (task == NULL)) {
@@ -2125,14 +2259,15 @@ void mbx1_wdsnd(struct mbcmd *mb)
                return;
        }
 
-       write_word_to_fifo(&task->rcvdt.fifo, mb->data);
+       write_word_to_fifo(&task->dev->rcvdt.fifo, mb->data);
        wake_up_interruptible(&task->dev->read_wait_q);
 }
 
-void mbx1_wdreq(struct mbcmd *mb)
+void mbx_wdreq(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
+       u8 tid = mb->cmd_l;
        struct dsptask *task = dsptask[tid];
+       struct taskdev *dev;
 
        if ((tid >= TASKDEV_MAX) || (task == NULL)) {
                printk(KERN_ERR "mbx: WDREQ with illegal tid! %d\n", tid);
@@ -2145,23 +2280,26 @@ void mbx1_wdreq(struct mbcmd *mb)
                return;
        }
 
-       spin_lock(&task->wsz_lock);
-       task->wsz = 2;
-       spin_unlock(&task->wsz_lock);
-       wake_up_interruptible(&task->dev->write_wait_q);
+       dev = task->dev;
+       spin_lock(&dev->wsz_lock);
+       dev->wsz = 2;
+       spin_unlock(&dev->wsz_lock);
+       wake_up_interruptible(&dev->write_wait_q);
 }
 
-void mbx1_bksnd(struct mbcmd *mb)
+void mbx_bksnd(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
-       unsigned short bid = mb->data;
+       u8 tid = mb->cmd_l;
+       u16 bid = mb->data;
        struct dsptask *task = dsptask[tid];
-       unsigned short cnt;
+       struct ipbuf_head *ipb_h;
+       u16 cnt;
 
        if (bid >= ipbcfg.ln) {
                printk(KERN_ERR "mbx: BKSND with illegal bid! %d\n", bid);
                return;
        }
+       ipb_h = bid_to_ipbuf(bid);
        ipb_bsycnt_dec(&ipbcfg);
        if ((tid >= TASKDEV_MAX) || (task == NULL)) {
                printk(KERN_ERR "mbx: BKSND with illegal tid! %d\n", tid);
@@ -2177,15 +2315,15 @@ void mbx1_bksnd(struct mbcmd *mb)
                       "mbx: BKSND from private sending task! (task%d)\n", tid);
                goto unuse_ipbuf_out;
        }
-       if (sync_with_dsp(&ipbuf[bid]->sd, tid, 10) < 0) {
+       if (sync_with_dsp(&ipb_h->p->sd, tid, 10) < 0) {
                printk(KERN_ERR "mbx: BKSND - IPBUF sync failed!\n");
                return;
        }
 
        /* should be done in DSP, but just in case. */
-       ipbuf[bid]->next = OMAP_DSP_BID_NULL;
+       ipb_h->p->next = BID_NULL;
 
-       cnt = ipbuf[bid]->c;
+       cnt = ipb_h->p->c;
        if (cnt > ipbcfg.lsz) {
                printk(KERN_ERR "mbx: BKSND cnt(%d) > ipbuf line size(%d)!\n",
                       cnt, ipbcfg.lsz);
@@ -2194,12 +2332,10 @@ void mbx1_bksnd(struct mbcmd *mb)
 
        if (cnt == 0) {
                /* 0-byte send from DSP */
-               unuse_ipbuf_nowait(bid);
+               unuse_ipbuf_nowait(ipb_h);
                goto done;
        }
-       spin_lock(&task->rcvdt.bk.link.lock);
-       ipblink_add_tail(&task->rcvdt.bk.link, bid, ipbuf);
-       spin_unlock(&task->rcvdt.bk.link.lock);
+       ipblink_add_tail(&task->dev->rcvdt.bk.link, bid);
        /* we keep coming bid and return alternative line to DSP. */
        balance_ipbuf();
 
@@ -2208,15 +2344,16 @@ done:
        return;
 
 unuse_ipbuf_out:
-       unuse_ipbuf_nowait(bid);
+       unuse_ipbuf_nowait(ipb_h);
        return;
 }
 
-void mbx1_bkreq(struct mbcmd *mb)
+void mbx_bkreq(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
-       unsigned short cnt = mb->data;
+       u8 tid = mb->cmd_l;
+       u16 cnt = mb->data;
        struct dsptask *task = dsptask[tid];
+       struct taskdev *dev;
 
        if ((tid >= TASKDEV_MAX) || (task == NULL)) {
                printk(KERN_ERR "mbx: BKREQ with illegal tid! %d\n", tid);
@@ -2240,35 +2377,37 @@ void mbx1_bkreq(struct mbcmd *mb)
                return;
        }
 
-       spin_lock(&task->wsz_lock);
-       task->wsz = cnt*2;
-       spin_unlock(&task->wsz_lock);
-       wake_up_interruptible(&task->dev->write_wait_q);
+       dev = task->dev;
+       spin_lock(&dev->wsz_lock);
+       dev->wsz = cnt*2;
+       spin_unlock(&dev->wsz_lock);
+       wake_up_interruptible(&dev->write_wait_q);
 }
 
-void mbx1_bkyld(struct mbcmd *mb)
+void mbx_bkyld(struct mbcmd *mb)
 {
-       unsigned short bid = mb->data;
+       u16 bid = mb->data;
+       struct ipbuf_head *ipb_h;
 
        if (bid >= ipbcfg.ln) {
                printk(KERN_ERR "mbx: BKYLD with illegal bid! %d\n", bid);
                return;
        }
+       ipb_h = bid_to_ipbuf(bid);
 
        /* should be done in DSP, but just in case. */
-       ipbuf[bid]->next = OMAP_DSP_BID_NULL;
+       ipb_h->p->next = BID_NULL;
 
        /* we don't need to sync with DSP */
        ipb_bsycnt_dec(&ipbcfg);
-       release_ipbuf(bid);
+       release_ipbuf(ipb_h);
 }
 
-void mbx1_bksndp(struct mbcmd *mb)
+void mbx_bksndp(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
+       u8 tid = mb->cmd_l;
        struct dsptask *task = dsptask[tid];
-       struct rcvdt_bk_struct *rcvdt = &task->rcvdt.bk;
-       struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
+       struct ipbuf_p *ipbp;
 
        if ((tid >= TASKDEV_MAX) || (task == NULL)) {
                printk(KERN_ERR "mbx: BKSNDP with illegal tid! %d\n", tid);
@@ -2292,23 +2431,23 @@ void mbx1_bksndp(struct mbcmd *mb)
         * until then DSP can't send next data.
         */
 
+       ipbp = task->ipbuf_pvt_r;
        if (sync_with_dsp(&ipbp->s, tid, 10) < 0) {
                printk(KERN_ERR "mbx: BKSNDP - IPBUF sync failed!\n");
                return;
        }
        printk(KERN_DEBUG "mbx: ipbuf_pvt_r->a = 0x%08lx\n",
               MKLONG(ipbp->ah, ipbp->al));
-       spin_lock(&rcvdt->link.lock);
-       ipblink_add_pvt(&rcvdt->link);
-       spin_unlock(&rcvdt->link.lock);
+       ipblink_add_pvt(&task->dev->rcvdt.bk.link);
        wake_up_interruptible(&task->dev->read_wait_q);
 }
 
-void mbx1_bkreqp(struct mbcmd *mb)
+void mbx_bkreqp(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
+       u8 tid = mb->cmd_l;
        struct dsptask *task = dsptask[tid];
-       struct ipbuf_p *ipbp = task->ipbuf_pvt_w;
+       struct taskdev *dev;
+       struct ipbuf_p *ipbp;
 
        if ((tid >= TASKDEV_MAX) || (task == NULL)) {
                printk(KERN_ERR "mbx: BKREQP with illegal tid! %d\n", tid);
@@ -2330,21 +2469,23 @@ void mbx1_bkreqp(struct mbcmd *mb)
                return;
        }
 
-       if (sync_with_dsp(&ipbp->s, OMAP_DSP_TID_FREE, 10) < 0) {
+       ipbp = task->ipbuf_pvt_w;
+       if (sync_with_dsp(&ipbp->s, TID_FREE, 10) < 0) {
                printk(KERN_ERR "mbx: BKREQP - IPBUF sync failed!\n");
                return;
        }
        printk(KERN_DEBUG "mbx: ipbuf_pvt_w->a = 0x%08lx\n",
               MKLONG(ipbp->ah, ipbp->al));
-       spin_lock(&task->wsz_lock);
-       task->wsz = ipbp->c*2;
-       spin_unlock(&task->wsz_lock);
-       wake_up_interruptible(&task->dev->write_wait_q);
+       dev = task->dev;
+       spin_lock(&dev->wsz_lock);
+       dev->wsz = ipbp->c*2;
+       spin_unlock(&dev->wsz_lock);
+       wake_up_interruptible(&dev->write_wait_q);
 }
 
-void mbx1_tctl(struct mbcmd *mb)
+void mbx_tctl(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
+       u8 tid = mb->cmd_l;
        struct dsptask *task = dsptask[tid];
 
        if ((tid >= TASKDEV_MAX) || (task == NULL)) {
@@ -2352,34 +2493,40 @@ void mbx1_tctl(struct mbcmd *mb)
                return;
        }
 
-       if (!waitqueue_active(&task->dev->ioctl_wait_q)) {
+       if (!waitqueue_active(&task->dev->tctl_wait_q)) {
                printk(KERN_WARNING "mbx: unexpected TCTL from DSP!\n");
                return;
        }
 
-       task->tctl_stat = mb->data;
-       wake_up_interruptible(&task->dev->ioctl_wait_q);
+       task->dev->tctl_stat = mb->data;
+       wake_up_interruptible(&task->dev->tctl_wait_q);
 }
 
-void mbx1_tcfg(struct mbcmd *mb)
+void mbx_tcfg(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
+       u8 tid = mb->cmd_l;
        struct dsptask *task = dsptask[tid];
-       unsigned short *tnm;
-       volatile unsigned short *buf;
+       u16 *tnm;
+       volatile u16 *buf;
        int i;
 
        if ((tid >= TASKDEV_MAX) || (task == NULL)) {
                printk(KERN_ERR "mbx: TCFG with illegal tid! %d\n", tid);
                return;
        }
-       if ((task->state != TASK_STATE_CFGREQ) || (cfg_cmd != MBCMD(TCFG))) {
+       if ((task->state != TASK_ST_CFGREQ) || (cfg_cmd != MBX_CMD_DSP_TCFG)) {
                printk(KERN_WARNING "mbx: unexpected TCFG from DSP!\n");
                return;
        }
 
+       if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+               printk(KERN_ERR "mbx: TCFG - ipbuf_sys_da read failed!\n");
+               dsp_mem_disable(ipbuf_sys_da);
+               goto out;
+       }
        if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
                printk(KERN_ERR "mbx: TCFG - IPBUF sync failed!\n");
+               dsp_mem_disable(ipbuf_sys_da);
                goto out;
        }
 
@@ -2387,41 +2534,42 @@ void mbx1_tcfg(struct mbcmd *mb)
         * read configuration data on system IPBUF
         */
        buf = ipbuf_sys_da->d;
-       task->ttyp                 = buf[0];
-       task->rcvdt.bk.ipbuf_pvt_r = MKVIRT(buf[1], buf[2]);
-       task->ipbuf_pvt_w          = MKVIRT(buf[3], buf[4]);
-       task->map_base             = MKVIRT(buf[5], buf[6]);
-       task->map_length           = MKLONG(buf[7], buf[8]) << 1;       /* word -> byte */
-       tnm                        = MKVIRT(buf[9], buf[10]);
+       task->ttyp        = buf[0];
+       task->ipbuf_pvt_r = MKVIRT(buf[1], buf[2]);
+       task->ipbuf_pvt_w = MKVIRT(buf[3], buf[4]);
+       task->map_base    = MKVIRT(buf[5], buf[6]);
+       task->map_length  = MKLONG(buf[7], buf[8]) << 1;        /* word -> byte */
+       tnm               = MKVIRT(buf[9], buf[10]);
        release_ipbuf_pvt(ipbuf_sys_da);
+       dsp_mem_disable(ipbuf_sys_da);
 
        /*
         * copy task name string
         */
-       if (dsp_address_validate(tnm, OMAP_DSP_TNM_LEN, "task name buffer") <0) {
+       if (dsp_address_validate(tnm, TNM_LEN, "task name buffer") < 0) {
                task->name[0] = '\0';
                goto out;
        }
 
-       for (i = 0; i < OMAP_DSP_TNM_LEN-1; i++) {
+       for (i = 0; i < TNM_LEN-1; i++) {
                /* avoiding byte access */
-               unsigned short tmp = tnm[i];
+               u16 tmp = tnm[i];
                task->name[i] = tmp & 0x00ff;
                if (!tmp)
                        break;
        }
-       task->name[OMAP_DSP_TNM_LEN-1] = '\0';
+       task->name[TNM_LEN-1] = '\0';
 
-       task->state = TASK_STATE_READY;
+       task->state = TASK_ST_READY;
 out:
        wake_up_interruptible(&cfg_wait_q);
 }
 
-void mbx1_tadd(struct mbcmd *mb)
+void mbx_tadd(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
+       u8 tid = mb->cmd_l;
 
-       if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBCMD(TADD))) {
+       if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBX_CMD_DSP_TADD)) {
                printk(KERN_WARNING "mbx: unexpected TADD from DSP!\n");
                return;
        }
@@ -2429,11 +2577,11 @@ void mbx1_tadd(struct mbcmd *mb)
        wake_up_interruptible(&cfg_wait_q);
 }
 
-void mbx1_tdel(struct mbcmd *mb)
+void mbx_tdel(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
+       u8 tid = mb->cmd_l;
 
-       if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBCMD(TDEL))) {
+       if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBX_CMD_DSP_TDEL)) {
                printk(KERN_WARNING "mbx: unexpected TDEL from DSP!\n");
                return;
        }
@@ -2441,25 +2589,28 @@ void mbx1_tdel(struct mbcmd *mb)
        wake_up_interruptible(&cfg_wait_q);
 }
 
-void mbx1_err_fatal(unsigned char tid)
+void mbx_err_fatal(u8 tid)
 {
        struct dsptask *task = dsptask[tid];
+       struct taskdev *dev;
 
        if ((tid >= TASKDEV_MAX) || (task == NULL)) {
                printk(KERN_ERR "mbx: FATAL ERR with illegal tid! %d\n", tid);
                return;
        }
 
-       spin_lock(&task->dev->state_lock);
-       proclist_send_sigbus(&task->dev->proc_list);
-       spin_unlock(&task->dev->state_lock);
+       /* wake up waiting processes */
+       dev = task->dev;
+       wake_up_interruptible_all(&dev->read_wait_q);
+       wake_up_interruptible_all(&dev->write_wait_q);
+       wake_up_interruptible_all(&dev->tctl_wait_q);
 }
 
-static short *dbg_buf;
-static unsigned short dbg_buf_sz, dbg_line_sz;
+static u16 *dbg_buf;
+static u16 dbg_buf_sz, dbg_line_sz;
 static int dbg_rp;
 
-int dsp_dbg_config(short *buf, unsigned short sz, unsigned short lsz)
+int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz)
 {
 #ifdef OLD_BINARY_SUPPORT
        if ((mbx_revision == MBREV_3_0) || (mbx_revision == MBREV_3_2)) {
@@ -2495,26 +2646,26 @@ void dsp_dbg_stop(void)
 }
 
 #ifdef OLD_BINARY_SUPPORT
-static void mbx1_dbg_old(struct mbcmd *mb);
+static void mbx_dbg_old(struct mbcmd *mb);
 #endif
 
-void mbx1_dbg(struct mbcmd *mb)
+void mbx_dbg(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
+       u8 tid = mb->cmd_l;
        int cnt = mb->data;
        char s[80], *s_end = &s[79], *p;
-       unsigned short *src;
+       u16 *src;
        int i;
 
 #ifdef OLD_BINARY_SUPPORT
        if ((mbx_revision == MBREV_3_0) || (mbx_revision == MBREV_3_2)) {
-               mbx1_dbg_old(mb);
+               mbx_dbg_old(mb);
                return;
        }
 #endif
 
        if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
-           (tid != OMAP_DSP_TID_ANON)) {
+           (tid != TID_ANON)) {
                printk(KERN_ERR "mbx: DBG with illegal tid! %d\n", tid);
                return;
        }
@@ -2530,7 +2681,7 @@ void mbx1_dbg(struct mbcmd *mb)
        src = &dbg_buf[dbg_rp];
        p = s;
        for (i = 0; i < cnt; i++) {
-               unsigned short tmp;
+               u16 tmp;
                /*
                 * Be carefull that dbg_buf should not be read with
                 * 1-byte access since it might be placed in DARAM/SARAM
@@ -2565,36 +2716,40 @@ void mbx1_dbg(struct mbcmd *mb)
 }
 
 #ifdef OLD_BINARY_SUPPORT
-static void mbx1_dbg_old(struct mbcmd *mb)
+static void mbx_dbg_old(struct mbcmd *mb)
 {
-       unsigned char tid = mb->cmd_l;
+       u8 tid = mb->cmd_l;
        char s[80], *s_end = &s[79], *p;
-       unsigned short *src;
-       volatile unsigned short *buf;
+       u16 *src;
+       volatile u16 *buf;
        int cnt;
        int i;
 
        if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
-           (tid != OMAP_DSP_TID_ANON)) {
+           (tid != TID_ANON)) {
                printk(KERN_ERR "mbx: DBG with illegal tid! %d\n", tid);
                return;
        }
+       if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+               printk(KERN_ERR "mbx: DBG - ipbuf_sys_da read failed!\n");
+               return;
+       }
        if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
                printk(KERN_ERR "mbx: DBG - IPBUF sync failed!\n");
-               return;
+               goto out1;
        }
        buf = ipbuf_sys_da->d;
        cnt = buf[0];
        src = MKVIRT(buf[1], buf[2]);
        if (dsp_address_validate(src, cnt, "dbg buffer") < 0)
-               return;
+               goto out2;
 
        if (dsp_mem_enable(src) < 0)
-               return;
+               goto out2;
 
        p = s;
        for (i = 0; i < cnt; i++) {
-               unsigned short tmp;
+               u16 tmp;
                /*
                 * Be carefull that ipbuf should not be read with
                 * 1-byte access since it might be placed in DARAM/SARAM
@@ -2623,28 +2778,33 @@ static void mbx1_dbg_old(struct mbcmd *mb)
                printk(KERN_INFO "%s\n", s);
        }
 
-       release_ipbuf_pvt(ipbuf_sys_da);
        dsp_mem_disable(src);
+out2:
+       release_ipbuf_pvt(ipbuf_sys_da);
+out1:
+       dsp_mem_disable(ipbuf_sys_da);
 }
 #endif /* OLD_BINARY_SUPPORT */
 
 /*
- * sysfs files
+ * sysfs files: for each device
  */
+
+/* devname */
 static ssize_t devname_show(struct device *d, struct device_attribute *attr,
                            char *buf)
 {
-       struct taskdev *dev = to_taskdev(d);
-       return sprintf(buf, "%s\n", dev->name);
+       return sprintf(buf, "%s\n", to_taskdev(d)->name);
 }
 
+/* devstate */
 static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
                             char *buf)
 {
-       struct taskdev *dev = to_taskdev(d);
-       return sprintf(buf, "%s\n", devstate_name(dev->state));
+       return sprintf(buf, "%s\n", devstate_name(to_taskdev(d)->state));
 }
 
+/* proc_list */
 static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
                              char *buf)
 {
@@ -2653,32 +2813,47 @@ static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
        int len = 0;
 
        dev = to_taskdev(d);
-       spin_lock(&dev->state_lock);
+       spin_lock(&dev->proc_list_lock);
        list_for_each_entry(pl, &dev->proc_list, list_head) {
-               len += sprintf(buf + len, "%d\n", pl->pid);
+               /* need to lock tasklist_lock before calling
+                * find_task_by_pid_type. */
+               if (find_task_by_pid_type(PIDTYPE_PID, pl->pid) != NULL)
+                       len += sprintf(buf + len, "%d\n", pl->pid);
+               read_unlock(&tasklist_lock);
        }
-       spin_unlock(&dev->state_lock);
+       spin_unlock(&dev->proc_list_lock);
 
        return len;
 }
 
+/* taskname */
 static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
                             char *buf)
 {
        struct taskdev *dev = to_taskdev(d);
        int len;
 
+       if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+               return -ENODEV;
+
        len = sprintf(buf, "%s\n", dev->task->name);
 
+       devstate_read_unlock(dev);
        return len;
 }
 
+/* ttyp */
 static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
                         char *buf)
 {
-       unsigned short ttyp = to_taskdev(d)->task->ttyp;
+       struct taskdev *dev = to_taskdev(d);
+       u16 ttyp;
        int len = 0;
 
+       if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+               return -ENODEV;
+
+       ttyp = dev->task->ttyp;
        len += sprintf(buf + len, "0x%04x\n", ttyp);
        len += sprintf(buf + len, "%s %s send\n",
                        (sndtyp_acv(ttyp)) ? "active" :
@@ -2693,44 +2868,48 @@ static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
                        (rcvtyp_pvt(ttyp)) ? "private block" :
                                             "global block");
 
+       devstate_read_unlock(dev);
        return len;
 }
 
+/* fifosz */
 static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
                           char *buf)
 {
-       struct fifo_struct *fifo = &to_taskdev(d)->task->rcvdt.fifo;
+       struct fifo_struct *fifo = &to_taskdev(d)->rcvdt.fifo;
        return sprintf(buf, "%d\n", fifo->sz);
 }
 
 static int fifosz_store(struct device *d, struct device_attribute *attr,
                        const char *buf, size_t count)
 {
-       struct dsptask *task = to_taskdev(d)->task;
+       struct taskdev *dev = to_taskdev(d);
        unsigned long fifosz;
        int ret;
 
        fifosz = simple_strtol(buf, NULL, 10);
-       ret = dsp_task_set_fifosz(task, fifosz);
+       ret = taskdev_set_fifosz(dev, fifosz);
 
        return (ret < 0) ? ret : strlen(buf);
 }
 
+/* fifocnt */
 static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
                            char *buf)
 {
-       struct fifo_struct *fifo = &to_taskdev(d)->task->rcvdt.fifo;
+       struct fifo_struct *fifo = &to_taskdev(d)->rcvdt.fifo;
        return sprintf(buf, "%d\n", fifo->cnt);
 }
 
-static __inline__ char *bid_name(unsigned short bid)
+/* ipblink */
+static __inline__ char *bid_name(u16 bid)
 {
        static char s[6];
 
        switch (bid) {
-       case OMAP_DSP_BID_NULL:
+       case BID_NULL:
                return "NULL";
-       case OMAP_DSP_BID_PVT:
+       case BID_PVT:
                return "PRIVATE";
        default:
                sprintf(s, "%d", bid);
@@ -2741,7 +2920,7 @@ static __inline__ char *bid_name(unsigned short bid)
 static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
                            char *buf)
 {
-       struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->task->rcvdt.bk;
+       struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->rcvdt.bk;
        int len;
 
        spin_lock(&rcvdt->link.lock);
@@ -2752,12 +2931,14 @@ static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
        return len;
 }
 
+/* wsz */
 static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
                        char *buf)
 {
-       return sprintf(buf, "%d\n", to_taskdev(d)->task->wsz);
+       return sprintf(buf, "%d\n", to_taskdev(d)->wsz);
 }
 
+/* mmap */
 static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
                         char *buf)
 {
@@ -2766,25 +2947,27 @@ static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
 }
 
 /*
- * called from ipbuf_read_proc()
+ * called from ipbuf_show()
  */
-int ipbuf_is_held(unsigned char tid, unsigned short bid)
+int ipbuf_is_held(u8 tid, u16 bid)
 {
        struct dsptask *task = dsptask[tid];
-       unsigned short b;
+       struct ipblink *link;
+       u16 b;
        int ret = 0;
 
        if (task == NULL)
                return 0;
 
-       spin_lock(&task->rcvdt.bk.link.lock);
-       ipblink_for_each(b, &task->rcvdt.bk.link, ipbuf) {
+       link = &task->dev->rcvdt.bk.link;
+       spin_lock(&link->lock);
+       ipblink_for_each(b, link) {
                if (b == bid) { /* found */
                        ret = 1;
                        break;
                }
        }
-       spin_unlock(&task->rcvdt.bk.link.lock);
+       spin_unlock(&link->lock);
 
        return ret;
 }
index cdd71823c74a646ffa926fd807eb1337a4c96df9..f2bccc9ea3da0223145e767b43029c308e8eafeb 100644 (file)
@@ -1,41 +1,34 @@
 /*
- * linux/arch/arm/mach-omap/dsp/taskwatch.c
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * OMAP DSP task watch device driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 200%/05/16:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
-#include <linux/major.h>
-#include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/poll.h>
-#include <linux/interrupt.h>
 #include <linux/sched.h>
-#include <linux/mutex.h>
 #include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/arch/dsp.h>
+#include "dsp_mbcmd.h"
 #include "dsp.h"
+#include "ioctl.h"
 
 static DECLARE_WAIT_QUEUE_HEAD(read_wait_q);
 static unsigned int change_cnt;
@@ -49,14 +42,14 @@ void dsp_twch_touch(void)
 /*
  * @count: represents the device counts of the user's interst
  */
-static ssize_t dsp_twch_read(struct file *file, char *buf, size_t count,
+static ssize_t dsp_twch_read(struct file *file, char __user *buf, size_t count,
                             loff_t *ppos)
 {
        long taskstat[TASKDEV_MAX];
        int devcount = count / sizeof(long);
        int i;
 
-       if (!dsp_is_ready()) {
+       if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
                printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
                return -EINVAL;
        }
@@ -74,7 +67,7 @@ static ssize_t dsp_twch_read(struct file *file, char *buf, size_t count,
                remove_wait_queue(&read_wait_q, &wait);
 
                /* unconfigured while waiting ;-( */
-               if (dsp_is_ready())
+               if (dsp_cfgstat_get_stat() != CFGSTAT_READY)
                        return -EINVAL;
        }
 
@@ -112,62 +105,50 @@ static unsigned int dsp_twch_poll(struct file *file, poll_table *wait)
 static int dsp_twch_ioctl(struct inode *inode, struct file *file,
                          unsigned int cmd, unsigned long arg)
 {
-       static DEFINE_MUTEX(ioctl_lock);
        int ret;
 
-       if (mutex_lock_interruptible(&ioctl_lock))
-               return -ERESTARTSYS;
-
        switch (cmd) {
-       case OMAP_DSP_TWCH_IOCTL_MKDEV:
+       case TWCH_IOCTL_MKDEV:
                {
-                       char name[OMAP_DSP_TNM_LEN];
-                       if (copy_from_user(name, (void *)arg, OMAP_DSP_TNM_LEN)) {
-                               ret = -EFAULT;
-                               goto up_out;
-                       }
-                       name[OMAP_DSP_TNM_LEN-1] = '\0';
+                       char name[TNM_LEN];
+                       if (copy_from_user(name, (void __user *)arg, TNM_LEN))
+                               return -EFAULT;
+                       name[TNM_LEN-1] = '\0';
                        ret = dsp_mkdev(name);
                        break;
                }
 
-       case OMAP_DSP_TWCH_IOCTL_RMDEV:
+       case TWCH_IOCTL_RMDEV:
                {
-                       char name[OMAP_DSP_TNM_LEN];
-                       if (copy_from_user(name, (void *)arg, OMAP_DSP_TNM_LEN)) {
-                               ret = -EFAULT;
-                               goto up_out;
-                       }
-                       name[OMAP_DSP_TNM_LEN-1] = '\0';
+                       char name[TNM_LEN];
+                       if (copy_from_user(name, (void __user *)arg, TNM_LEN))
+                               return -EFAULT;
+                       name[TNM_LEN-1] = '\0';
                        ret = dsp_rmdev(name);
                        break;
                }
 
-       case OMAP_DSP_TWCH_IOCTL_TADD:
+       case TWCH_IOCTL_TADD:
                {
                        struct omap_dsp_taddinfo ti;
-                       if (copy_from_user(&ti, (void *)arg, sizeof(ti))) {
-                               ret = -EFAULT;
-                               goto up_out;
-                       }
-                       ret = dsp_tadd(ti.minor, ti.taskadr);
+                       if (copy_from_user(&ti, (void __user *)arg, sizeof(ti)))
+                               return -EFAULT;
+                       ret = dsp_tadd_minor(ti.minor, ti.taskadr);
                        break;
                }
 
-       case OMAP_DSP_TWCH_IOCTL_TDEL:
-               ret = dsp_tdel(arg);
+       case TWCH_IOCTL_TDEL:
+               ret = dsp_tdel_minor(arg);
                break;
 
-       case OMAP_DSP_TWCH_IOCTL_TKILL:
-               ret = dsp_tkill(arg);
+       case TWCH_IOCTL_TKILL:
+               ret = dsp_tkill_minor(arg);
                break;
 
        default:
-               ret = -ENOIOCTLCMD;
+               return -ENOIOCTLCMD;
        }
 
-up_out:
-       mutex_unlock(&ioctl_lock);
        return ret;
 }
 
index 6e427a2b2d4f995076e3bc46f40a1cfe08b734ff..6ffd68b2c42d29510115e8527e92e2b1bb4ae6a0 100644 (file)
@@ -1,27 +1,24 @@
 /*
- * linux/arch/arm/mach-omap/dsp/uaccess_dsp.S
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * user memory access functions for DSP driver
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2004,2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2004/06/29:  DSP Gateway version 3.3
  */
 
 #include <linux/linkage.h>
index d1eb7e52e27c944f70509e9d4ca3f37938e91ecd..686faf2e9b7dd785cfb13822b1c5224774fb88b0 100644 (file)
@@ -1,34 +1,31 @@
 /*
- * linux/arch/arm/mach-omap/dsp/uaccess_dsp.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * Header for user access functions for DSP driver
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2002-2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Modified from linux/include/asm-arm/uaccess.h
- * by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2004/06/29:  DSP Gateway version 3.3
  */
 
 #ifndef _OMAP_DSP_UACCESS_DSP_H
 #define _OMAP_DSP_UACCESS_DSP_H
 
 #include <asm/uaccess.h>
+#include "dsp_common.h"
 
 #define HAVE_ASM_COPY_FROM_USER_DSP_2B
 
@@ -39,12 +36,6 @@ extern unsigned long __copy_to_user_dsp_2b(void __user *to,
                                                const void *from);
 #endif
 
-extern unsigned long dspmem_base, dspmem_size;
-#define is_dsp_internal_mem(va) \
-       (((unsigned long)(va) >= dspmem_base) &&  \
-        ((unsigned long)(va) < dspmem_base + dspmem_size))
-
-
 #ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
 static __inline__ unsigned long copy_from_user_dsp_2b(void *to,
                                                      const void *from)
@@ -181,6 +172,4 @@ static __inline__ unsigned long copy_to_user_dsp(void *to, const void *from,
        return n;
 }
 
-#undef is_dsp_internal_mem
-
 #endif /* _OMAP_DSP_UACCESS_DSP_H */
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
new file mode 100644 (file)
index 0000000..6a37582
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ * OMAP mailbox driver
+ *
+ * Copyright (C) 2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#ifdef CONFIG_ARCH_OMAP2
+#include <linux/clk.h>
+#endif
+#include <asm/io.h>
+#ifdef CONFIG_ARCH_OMAP1
+#include <asm/delay.h>
+#endif
+#include <asm/arch/mailbox.h>
+#include "mailbox_hw.h"
+
+#if defined(CONFIG_ARCH_OMAP1)
+
+#define read_mbx(m, msgp) \
+               do { \
+                       *(msgp) = omap_readw((m)->data_r); \
+                       *(msgp) |= ((mbx_msg_t)omap_readw((m)->cmd_r)) << 16; \
+               } while (0)
+#define write_mbx(m, msg) \
+               do { \
+                       omap_writew((msg) & 0xffff, (m)->data_w); \
+                       omap_writew((msg) >> 16, (m)->cmd_w); \
+               } while (0)
+#define enable_newmsg_irq(m)   enable_irq((m)->irq)
+#define disable_newmsg_irq(m)  disable_irq((m)->irq)
+#define mbx_is_notfull(m)      (omap_readw((m)->flag_w) == 0)
+
+#elif defined(CONFIG_ARCH_OMAP2)
+
+#define omap_bit_setl(b,r) \
+               do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
+#define omap_bit_clrl(b,r) \
+               do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
+
+#define read_mbx(m, msgp) \
+               do { *(msgp) = omap_readl((m)->message_r); } while (0)
+#define write_mbx(m, msg)      omap_writel(msg, (m)->message_w)
+#define enable_newmsg_irq(m)   omap_bit_setl((m)->newmsg_bit, (m)->irqenable)
+#define disable_newmsg_irq(m)  omap_bit_clrl((m)->newmsg_bit, (m)->irqenable)
+#define enable_notfull_irq(m)  omap_bit_setl((m)->notfull_bit, (m)->irqenable)
+#define disable_notfull_irq(m) omap_bit_clrl((m)->notfull_bit, (m)->irqenable)
+#define clear_newmsg_irq(m)    omap_writel((m)->newmsg_bit, (m)->irqstatus)
+#define clear_notfull_irq(m)   omap_writel((m)->notfull_bit, (m)->irqstatus)
+#define notfull_irq_enabled(m) (omap_readl((m)->irqenable) & (m)->notfull_bit)
+#define has_newmsg_irq(m)      (omap_readl((m)->irqstatus) & (m)->newmsg_bit)
+#define has_notfull_irq(m)     (omap_readl((m)->irqstatus) & (m)->notfull_bit)
+#define mbx_nomsg(m)           (omap_readl((m)->msgstatus_r) == 0)
+#define mbx_is_notfull(m)      (omap_readl((m)->fifostatus_w) == 0)
+
+#endif /* CONFIG_ARCH_OMAP2 */
+
+static void do_mbx(void *p);
+
+#define MBQ_DEPTH      16
+struct mbq {
+       mbx_msg_t msg[MBQ_DEPTH];
+       int rp, wp, full;
+};
+
+#define mbq_inc(p)     do { if (++(p) == MBQ_DEPTH) (p) = 0; } while(0)
+
+#if defined(CONFIG_ARCH_OMAP1)
+#  define MBX_USE_SEQ_BIT      /* XXX */
+#elif defined(CONFIG_ARCH_OMAP2)
+#  undef MBX_USE_SEQ_BIT
+#endif
+
+struct mbx {
+       char *name;
+       unsigned int irq;
+       char irq_devid_newmsg;
+#ifdef CONFIG_ARCH_OMAP2
+       char irq_devid_notfull;
+#endif
+#ifdef MBX_USE_SEQ_BIT
+       mbx_msg_t seq_snd;
+       mbx_msg_t seq_rcv;
+               /* seq_rcv should be initialized with any value other than
+                * 0 and 1 << 31, to allow either value for the first
+                * message.  */
+#endif
+       mbx_receiver_t *receiver_map[MBX_CMD_MAX];
+       struct work_struct work;
+       struct mbq mbq;
+#ifdef CONFIG_ARCH_OMAP2
+       wait_queue_head_t full_wait_q;
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1)
+       void *cmd_w;
+       void *data_w;
+       void *flag_w;
+       void *cmd_r;
+       void *data_r;
+#elif defined(CONFIG_ARCH_OMAP2)
+       void *irqenable;
+       void *irqstatus;
+       void *message_w;
+       void *message_r;
+       void *fifostatus_w;
+       void *msgstatus_r;
+       u32 notfull_bit;
+       u32 newmsg_bit;
+#endif
+};
+
+#if defined(CONFIG_ARCH_OMAP1)
+
+#if defined(CONFIG_ARCH_OMAP15XX)
+#define INT_DSP_MAILBOX1       INT_1510_DSP_MAILBOX1
+#elif defined(CONFIG_ARCH_OMAP16XX)
+#define INT_DSP_MAILBOX1       INT_1610_DSP_MAILBOX1
+#endif
+
+static struct mbx mbx_dsp = {
+       .name = "DSP",
+       .irq = INT_DSP_MAILBOX1,
+       .work = __WORK_INITIALIZER(mbx_dsp.work, do_mbx, &mbx_dsp),
+
+       .cmd_w  = (void *)MAILBOX_ARM2DSP1b,
+       .data_w = (void *)MAILBOX_ARM2DSP1,
+       .flag_w = (void *)MAILBOX_ARM2DSP1_Flag,
+       .cmd_r  = (void *)MAILBOX_DSP2ARM1b,
+       .data_r = (void *)MAILBOX_DSP2ARM1,
+};
+
+#elif defined(CONFIG_ARCH_OMAP2)
+
+/*
+ * MAILBOX 0: ARM -> DSP,
+ * MAILBOX 1: ARM <- DSP.
+ * MAILBOX 2: ARM -> IVA,
+ * MAILBOX 3: ARM <- IVA.
+ */
+static struct mbx mbx_dsp = {
+       .name = "DSP",
+       .irq = INT_24XX_MAIL_U0_MPU,
+       .work = __WORK_INITIALIZER(mbx_dsp.work, do_mbx, &mbx_dsp),
+       .full_wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(mbx_dsp.full_wait_q),
+
+       .irqenable    = (void *)MAILBOX_IRQENABLE_0,
+       .irqstatus    = (void *)MAILBOX_IRQSTATUS_0,
+       .message_w    = (void *)MAILBOX_MESSAGE_0,
+       .message_r    = (void *)MAILBOX_MESSAGE_1,
+       .fifostatus_w = (void *)MAILBOX_FIFOSTATUS_0,
+       .msgstatus_r  = (void *)MAILBOX_MSGSTATUS_1,
+       .notfull_bit  = MAILBOX_IRQ_NOTFULL(0),
+       .newmsg_bit   = MAILBOX_IRQ_NEWMSG(1),
+};
+static struct mbx mbx_iva = {
+       .name = "IVA",
+       .irq = INT_24XX_MAIL_U3_MPU,
+       .work = __WORK_INITIALIZER(mbx_iva.work, do_mbx, &mbx_iva),
+       .full_wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(mbx_iva.full_wait_q),
+
+       .irqenable    = (void *)MAILBOX_IRQENABLE_3,
+       .irqstatus    = (void *)MAILBOX_IRQSTATUS_3,
+       .message_w    = (void *)MAILBOX_MESSAGE_2,
+       .message_r    = (void *)MAILBOX_MESSAGE_3,
+       .fifostatus_w = (void *)MAILBOX_FIFOSTATUS_2,
+       .msgstatus_r  = (void *)MAILBOX_MSGSTATUS_3,
+       .notfull_bit  = MAILBOX_IRQ_NOTFULL(2),
+       .newmsg_bit   = MAILBOX_IRQ_NEWMSG(3),
+};
+
+#endif /* CONFIG_ARCH_OMAP2 */
+
+static struct mbx *mbxes[] = {
+       &mbx_dsp,
+#ifdef CONFIG_ARCH_OMAP2
+       &mbx_iva,
+#endif
+};
+
+struct mbx *mbx_get(const char *id)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mbxes); i++) {
+               if (!strcmp(id, mbxes[i]->name))
+                       return mbxes[i];
+       }
+
+       return ERR_PTR(-ENOENT);
+}
+
+#if defined(CONFIG_ARCH_OMAP1)
+static __inline__ int mbsync_irq_save(struct mbx *mbx, unsigned long *flags,
+                                     int try_cnt)
+{
+       int cnt;
+
+       local_irq_save(*flags);
+       if (mbx_is_notfull(mbx))
+               return 0;
+       /*
+        * mailbox is busy. wait for some usecs...
+        */
+       local_irq_restore(*flags);
+       for (cnt = 0; cnt < try_cnt; cnt++) {
+               udelay(1);
+               local_irq_save(*flags);
+               if (mbx_is_notfull(mbx))        /* success! */
+                       return 0;
+               local_irq_restore(*flags);
+       }
+
+       /* fail! */
+       return -1;
+}
+#elif defined(CONFIG_ARCH_OMAP2)
+static __inline__ int mbsync_irq_save(struct mbx *mbx, unsigned long *flags)
+{
+       long current_state; 
+       DECLARE_WAITQUEUE(wait, current);
+
+       do {
+               local_irq_save(*flags);
+               if (mbx_is_notfull(mbx))
+                       return 0;
+
+               /*
+                * mailbox is busy. 
+                */
+               local_irq_restore(*flags);
+               enable_notfull_irq(mbx);
+
+               /* wait until the FIFO becomes not-full */
+               add_wait_queue(&mbx->full_wait_q, &wait);
+               current_state = current->state;
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (!mbx_is_notfull(mbx))       /* last check */
+                       schedule();
+               set_current_state(current_state);
+               remove_wait_queue(&mbx->full_wait_q, &wait);
+
+               if (signal_pending(current))
+                       return -1;
+       } while (1);
+}
+#endif
+
+/*
+ * message dispatcher API
+ */
+int mbx_send(struct mbx *mbx, mbx_msg_t msg)
+{
+       unsigned long flags;
+
+#if defined(CONFIG_ARCH_OMAP1)
+       /*
+        * DSP mailbox interrupt latency must be less than 1ms.
+        */
+       if (mbsync_irq_save(mbx, &flags, 1000) < 0) {
+               printk(KERN_ERR
+                      "mailbox(%s) is busy. message 0x%08x is aborting.\n",
+                      mbx->name, msg);
+               return -1;
+       }
+#elif defined(CONFIG_ARCH_OMAP2)
+       if (mbsync_irq_save(mbx, &flags) < 0)
+               return -1;
+#endif
+
+#ifdef MBX_USE_SEQ_BIT
+       /* add seq_snd to msg */
+       msg = (msg & 0x7fffffff) | mbx->seq_snd;
+       /* flip seq_snd */
+       mbx->seq_snd ^= 1 << 31;
+#endif
+
+       write_mbx(mbx, msg);
+
+       local_irq_restore(flags);
+       return 0;
+}
+
+/*
+ * register / unregister API
+ */
+int register_mbx_receiver(struct mbx *mbx, unsigned char cmd,
+                         mbx_receiver_t *rcv)
+{
+       if (cmd >= MBX_CMD_MAX) {
+               printk(KERN_ERR "register_mbx_receiver(): "
+                      "bad cmd (0x%x)\n", cmd);
+               return -EINVAL;
+       }
+       if (mbx->receiver_map[cmd] != NULL) {
+               printk(KERN_ERR "register_mbx_receiver(): cmd 0x%x is "
+                      "already reserved.\n", cmd);
+               return -EINVAL;
+       }
+
+       mbx->receiver_map[cmd] = rcv;
+       return 0;
+}
+
+int unregister_mbx_receiver(struct mbx *mbx, unsigned char cmd,
+                           mbx_receiver_t *rcv)
+{
+       if (cmd >= MBX_CMD_MAX) {
+               printk(KERN_ERR "unregister_mbx_receiver(): "
+                      "bad cmd (0x%x)\n", cmd);
+               return -EINVAL;
+       }
+       if (mbx->receiver_map[cmd] != rcv) {
+               printk(KERN_ERR "unregister_mbx_receiver(): cmd 0x%x and "
+                      "receiver function mismatch!\n", cmd);
+               return -EINVAL;
+       }
+
+       mbx->receiver_map[cmd] = NULL;
+       return 0;
+}
+
+/*
+ * IRQ disable / enable API
+ */
+void disable_mbx_irq(struct mbx *mbx)
+{
+       disable_irq(mbx->irq);
+}
+
+void enable_mbx_irq(struct mbx *mbx)
+{
+       enable_irq(mbx->irq);
+}
+
+/*
+ * init_seq API
+ */
+void mbx_init_seq(struct mbx *mbx)
+{
+#ifdef MBX_USE_SEQ_BIT
+       /* backward compatibility */
+       mbx->seq_snd = 0x80000000;
+
+       /* any value other than 0 and 1 << 31 */
+       mbx->seq_rcv = 0xffffffff;
+#endif /* MBX_USE_SEQ_BIT */
+}
+
+/*
+ * receiver workqueue
+ */
+static void do_mbx(void *p)
+{
+       int empty = 0;
+       struct mbx *mbx = (struct mbx *)p;
+       struct mbq *mbq = &mbx->mbq;
+       mbx_receiver_t *receiver;
+       mbx_msg_t msg;
+#ifdef MBX_USE_SEQ_BIT
+       mbx_msg_t seq;
+#endif
+
+       disable_newmsg_irq(mbx);
+       if ((mbq->rp == mbq->wp) && !mbq->full)
+               empty = 1;
+       enable_newmsg_irq(mbx);
+
+       while (!empty) {
+               msg = mbq->msg[mbq->rp];
+#ifdef MBX_USE_SEQ_BIT
+               seq = msg & (1 << 31);
+
+               if (seq == mbx->seq_rcv) {
+                       printk(KERN_ERR
+                              "mbx: illegal seq bit! ignoring this command. "
+                              "(%08x)\n", msg);
+                       goto inc;
+               }
+               mbx->seq_rcv = seq;
+#endif
+
+               /* call receiver function */
+               if ((receiver = mbx->receiver_map[(msg >> 24) & 0x7f]) == NULL)
+                       printk(KERN_ERR
+                              "mbx: unknown message (%08x) received from "
+                              "%s.\n", msg, mbx->name);
+               else
+                       receiver(msg);
+
+#ifdef MBX_USE_SEQ_BIT
+inc:
+#endif
+               disable_newmsg_irq(mbx);
+               mbq_inc(mbq->rp);
+               if (mbq->rp == mbq->wp)
+                       empty = 1;
+               /* if mbq has been full, now we have a room. */
+               if (mbq->full) {
+                       mbq->full = 0;
+                       enable_newmsg_irq(mbx);
+               }
+               enable_newmsg_irq(mbx);
+       }
+}
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t mbx_int_newmsg(int irq, void *p, struct pt_regs *regs)
+{
+       struct mbx *mbx = container_of(p, struct mbx, irq_devid_newmsg);
+       struct mbq *mbq = &mbx->mbq;
+       mbx_msg_t *msg;
+
+#ifdef CONFIG_ARCH_OMAP2
+       /*
+        * mailbox IRQ can be muxed.
+        * if it is not a newmsg interrupt, do nothing.
+        */
+       if (!has_newmsg_irq(mbx))
+               return IRQ_NONE;
+#endif
+
+       do {
+#ifdef CONFIG_ARCH_OMAP2
+               if (mbx_nomsg(mbx)) {
+                       /* no more messages in the fifo. clear IRQ source. */
+                       clear_newmsg_irq(mbx);
+                       break;
+               }
+#endif
+
+               msg = &mbq->msg[mbq->wp];
+               read_mbx(mbx, msg);
+
+               mbq_inc(mbq->wp);
+               if (mbq->wp == mbq->rp) {       /* mbq is full */
+                       mbq->full = 1;
+                       disable_newmsg_irq(mbx);
+                       break;
+               }
+#if defined(CONFIG_ARCH_OMAP1)
+       } while (0);    /* do it once */
+#elif defined(CONFIG_ARCH_OMAP2)
+       } while (1);
+#endif
+
+       schedule_work(&mbx->work);
+       return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_ARCH_OMAP2
+static irqreturn_t mbx_int_notfull(int irq, void *p, struct pt_regs *regs)
+{
+       struct mbx *mbx = container_of(p, struct mbx, irq_devid_notfull);
+
+       /*
+        * mailbox IRQ can be muxed.
+        * if it is not a notfull interrupt, we do nothing.
+        */
+#if 0
+       if (!has_notfull_irq(mbx))
+#else
+       if (!(has_notfull_irq(mbx) && notfull_irq_enabled(mbx)))
+#endif
+               return IRQ_NONE;
+
+       disable_notfull_irq(mbx);
+
+#if 0  /*
+        * note: this doesn't seeem to work as explained in the manual.
+        * IRQSTATUS:NOTFULL can't be cleared even we write 1 to that bit.
+        * It is always set when it's not full, regardless of IRQENABLE setting.
+        */
+       clear_notfull_irq(mbx);
+#endif
+
+       wake_up_interruptible_all(&mbx->full_wait_q);
+       return IRQ_HANDLED;
+}
+#endif /* CONFIG_ARCH_OMAP2 */
+
+static int __init mbx_request_irq(struct mbx *mbx, const char *devname)
+{
+       int ret;
+
+#ifdef CONFIG_ARCH_OMAP2
+       enable_newmsg_irq(mbx);
+#endif
+
+       ret = request_irq(mbx->irq, mbx_int_newmsg, SA_INTERRUPT | SA_SHIRQ,
+                         devname, &mbx->irq_devid_newmsg);
+       if (ret) {
+               printk(KERN_ERR
+                      "failed to register DSP mailbox newmsg interrupt: "
+                      "%d\n", ret);
+               return ret;
+       }
+
+#ifdef CONFIG_ARCH_OMAP2
+       ret = request_irq(mbx->irq, mbx_int_notfull, SA_INTERRUPT | SA_SHIRQ,
+                         devname, &mbx->irq_devid_notfull);
+       if (ret) {
+               printk(KERN_ERR
+                      "failed to register DSP mailbox notfull interrupt: "
+                      "%d\n", ret);
+               return ret;
+       }
+#endif
+
+       return 0;
+}
+
+static int __init omap_mailbox_init(void)
+{
+       int ret;
+#ifdef CONFIG_ARCH_OMAP2
+       struct clk *mbx_ick_handle;
+#endif
+
+       printk(KERN_INFO "Initializing OMAP Mailboxes\n");
+#ifdef CONFIG_ARCH_OMAP2
+       /*
+        * FIXME: mbx_ick will never unsed
+        */
+       mbx_ick_handle = clk_get(NULL, "mailboxes_ick");
+       if (IS_ERR(mbx_ick_handle)) {
+               printk("Could not get mailboxes_ick\n");
+               return -ENODEV;
+       } else
+               clk_enable(mbx_ick_handle);
+#endif
+
+       if ((ret = mbx_request_irq(&mbx_dsp, "mbx_dsp")) != 0)
+               return ret;
+#ifdef CONFIG_ARCH_OMAP2
+       if ((ret = mbx_request_irq(&mbx_iva, "mbx_iva")) != 0)
+               return ret;
+#endif
+
+       return 0;
+}
+
+arch_initcall(omap_mailbox_init);
+
+EXPORT_SYMBOL(mbx_get);
+EXPORT_SYMBOL(mbx_send);
+EXPORT_SYMBOL(register_mbx_receiver);
+EXPORT_SYMBOL(unregister_mbx_receiver);
+EXPORT_SYMBOL(disable_mbx_irq);
+EXPORT_SYMBOL(enable_mbx_irq);
+EXPORT_SYMBOL(mbx_init_seq);
diff --git a/arch/arm/plat-omap/mailbox_hw.h b/arch/arm/plat-omap/mailbox_hw.h
new file mode 100644 (file)
index 0000000..9b10433
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Header for OMAP mailbox driver
+ *
+ * Copyright (C) 2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <asm/hardware.h>
+
+#if defined(CONFIG_ARCH_OMAP1)
+
+#define MAILBOX_BASE                   (0xfffcf000)
+#define MAILBOX_ARM2DSP1               (MAILBOX_BASE + 0x00)
+#define MAILBOX_ARM2DSP1b              (MAILBOX_BASE + 0x04)
+#define MAILBOX_DSP2ARM1               (MAILBOX_BASE + 0x08)
+#define MAILBOX_DSP2ARM1b              (MAILBOX_BASE + 0x0c)
+#define MAILBOX_DSP2ARM2               (MAILBOX_BASE + 0x10)
+#define MAILBOX_DSP2ARM2b              (MAILBOX_BASE + 0x14)
+#define MAILBOX_ARM2DSP1_Flag          (MAILBOX_BASE + 0x18)
+#define MAILBOX_DSP2ARM1_Flag          (MAILBOX_BASE + 0x1c)
+#define MAILBOX_DSP2ARM2_Flag          (MAILBOX_BASE + 0x20)
+
+#elif defined(CONFIG_ARCH_OMAP2)
+
+/*
+ * Mailbox: L4 peripheral -- use omap_readX(), omap_writeX()
+ */
+#define OMAP24XX_MAILBOX_BASE          (L4_24XX_BASE + 0x94000)
+
+#define MAILBOX_REVISION               (OMAP24XX_MAILBOX_BASE + 0x00)
+#define MAILBOX_SYSCONFIG              (OMAP24XX_MAILBOX_BASE + 0x10)
+#define MAILBOX_SYSSTATUS              (OMAP24XX_MAILBOX_BASE + 0x14)
+#define MAILBOX_MESSAGE_0              (OMAP24XX_MAILBOX_BASE + 0x40)
+#define MAILBOX_MESSAGE_1              (OMAP24XX_MAILBOX_BASE + 0x44)
+#define MAILBOX_MESSAGE_2              (OMAP24XX_MAILBOX_BASE + 0x48)
+#define MAILBOX_MESSAGE_3              (OMAP24XX_MAILBOX_BASE + 0x4c)
+#define MAILBOX_MESSAGE_4              (OMAP24XX_MAILBOX_BASE + 0x50)
+#define MAILBOX_MESSAGE_5              (OMAP24XX_MAILBOX_BASE + 0x54)
+#define MAILBOX_FIFOSTATUS_0           (OMAP24XX_MAILBOX_BASE + 0x80)
+#define MAILBOX_FIFOSTATUS_1           (OMAP24XX_MAILBOX_BASE + 0x84)
+#define MAILBOX_FIFOSTATUS_2           (OMAP24XX_MAILBOX_BASE + 0x88)
+#define MAILBOX_FIFOSTATUS_3           (OMAP24XX_MAILBOX_BASE + 0x8c)
+#define MAILBOX_FIFOSTATUS_4           (OMAP24XX_MAILBOX_BASE + 0x90)
+#define MAILBOX_FIFOSTATUS_5           (OMAP24XX_MAILBOX_BASE + 0x94)
+#define MAILBOX_MSGSTATUS_0            (OMAP24XX_MAILBOX_BASE + 0xc0)
+#define MAILBOX_MSGSTATUS_1            (OMAP24XX_MAILBOX_BASE + 0xc4)
+#define MAILBOX_MSGSTATUS_2            (OMAP24XX_MAILBOX_BASE + 0xc8)
+#define MAILBOX_MSGSTATUS_3            (OMAP24XX_MAILBOX_BASE + 0xcc)
+#define MAILBOX_MSGSTATUS_4            (OMAP24XX_MAILBOX_BASE + 0xd0)
+#define MAILBOX_MSGSTATUS_5            (OMAP24XX_MAILBOX_BASE + 0xd4)
+#define MAILBOX_IRQSTATUS_0            (OMAP24XX_MAILBOX_BASE + 0x100)
+#define MAILBOX_IRQENABLE_0            (OMAP24XX_MAILBOX_BASE + 0x104)
+#define MAILBOX_IRQSTATUS_1            (OMAP24XX_MAILBOX_BASE + 0x108)
+#define MAILBOX_IRQENABLE_1            (OMAP24XX_MAILBOX_BASE + 0x10c)
+#define MAILBOX_IRQSTATUS_2            (OMAP24XX_MAILBOX_BASE + 0x110)
+#define MAILBOX_IRQENABLE_2            (OMAP24XX_MAILBOX_BASE + 0x114)
+#define MAILBOX_IRQSTATUS_3            (OMAP24XX_MAILBOX_BASE + 0x118)
+#define MAILBOX_IRQENABLE_3            (OMAP24XX_MAILBOX_BASE + 0x11c)
+
+#define MAILBOX_IRQ_NOTFULL(n)         (1<<(2*(n)+1))
+#define MAILBOX_IRQ_NEWMSG(n)          (1<<(2*(n)))
+
+#endif /* CONFIG_ARCH_OMAP2 */
diff --git a/include/asm-arm/arch-omap/dsp.h b/include/asm-arm/arch-omap/dsp.h
deleted file mode 100644 (file)
index 06dad83..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * linux/include/asm-arm/arch-omap/dsp.h
- *
- * Header for OMAP DSP driver
- *
- * Copyright (C) 2002-2005 Nokia Corporation
- *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * 2005/06/01:  DSP Gateway version 3.3
- */
-
-#ifndef ASM_ARCH_DSP_H
-#define ASM_ARCH_DSP_H
-
-
-/*
- * for /dev/dspctl/ctl
- */
-#define OMAP_DSP_IOCTL_RESET                   1
-#define OMAP_DSP_IOCTL_RUN                     2
-#define OMAP_DSP_IOCTL_SETRSTVECT              3
-#define OMAP_DSP_IOCTL_CPU_IDLE                        4
-#define OMAP_DSP_IOCTL_MPUI_WORDSWAP_ON                5
-#define OMAP_DSP_IOCTL_MPUI_WORDSWAP_OFF       6
-#define OMAP_DSP_IOCTL_MPUI_BYTESWAP_ON                7
-#define OMAP_DSP_IOCTL_MPUI_BYTESWAP_OFF       8
-#define OMAP_DSP_IOCTL_GBL_IDLE                        9
-#define OMAP_DSP_IOCTL_DSPCFG                  10
-#define OMAP_DSP_IOCTL_DSPUNCFG                        11
-#define OMAP_DSP_IOCTL_TASKCNT                 12
-#define OMAP_DSP_IOCTL_POLL                    13
-#define OMAP_DSP_IOCTL_REGMEMR                 40
-#define OMAP_DSP_IOCTL_REGMEMW                 41
-#define OMAP_DSP_IOCTL_REGIOR                  42
-#define OMAP_DSP_IOCTL_REGIOW                  43
-#define OMAP_DSP_IOCTL_GETVAR                  44
-#define OMAP_DSP_IOCTL_SETVAR                  45
-#define OMAP_DSP_IOCTL_RUNLEVEL                        50
-#define OMAP_DSP_IOCTL_SUSPEND                 51
-#define OMAP_DSP_IOCTL_RESUME                  52
-#define OMAP_DSP_IOCTL_FBEN                    53
-#define OMAP_DSP_IOCTL_FBDIS                   54
-#define OMAP_DSP_IOCTL_MBSEND                  99
-
-/*
- * for taskdev
- * (ioctls below should be >= 0x10000)
- */
-#define OMAP_DSP_TASK_IOCTL_BFLSH      0x10000
-#define OMAP_DSP_TASK_IOCTL_SETBSZ     0x10001
-#define OMAP_DSP_TASK_IOCTL_LOCK       0x10002
-#define OMAP_DSP_TASK_IOCTL_UNLOCK     0x10003
-#define OMAP_DSP_TASK_IOCTL_GETNAME    0x10004
-
-/*
- * for /dev/dspctl/mem
- */
-#define OMAP_DSP_MEM_IOCTL_EXMAP       1
-#define OMAP_DSP_MEM_IOCTL_EXUNMAP     2
-#define OMAP_DSP_MEM_IOCTL_EXMAP_FLUSH 3
-#define OMAP_DSP_MEM_IOCTL_FBEXPORT    5
-#define OMAP_DSP_MEM_IOCTL_MMUITACK    7
-#define OMAP_DSP_MEM_IOCTL_MMUINIT     9
-#define OMAP_DSP_MEM_IOCTL_KMEM_RESERVE        11
-#define OMAP_DSP_MEM_IOCTL_KMEM_RELEASE        12
-
-struct omap_dsp_mapinfo {
-       unsigned long dspadr;
-       unsigned long size;
-};
-
-/*
- * for /dev/dspctl/twch
- */
-#define OMAP_DSP_TWCH_IOCTL_MKDEV      1
-#define OMAP_DSP_TWCH_IOCTL_RMDEV      2
-#define OMAP_DSP_TWCH_IOCTL_TADD       11
-#define OMAP_DSP_TWCH_IOCTL_TDEL       12
-#define OMAP_DSP_TWCH_IOCTL_TKILL      13
-
-#define OMAP_DSP_DEVSTATE_NOTASK       0x00000001
-#define OMAP_DSP_DEVSTATE_ATTACHED     0x00000002
-#define OMAP_DSP_DEVSTATE_GARBAGE      0x00000004
-#define OMAP_DSP_DEVSTATE_INVALID      0x00000008
-#define OMAP_DSP_DEVSTATE_ADDREQ       0x00000100
-#define OMAP_DSP_DEVSTATE_DELREQ       0x00000200
-#define OMAP_DSP_DEVSTATE_ADDFAIL      0x00001000
-#define OMAP_DSP_DEVSTATE_ADDING       0x00010000
-#define OMAP_DSP_DEVSTATE_DELING       0x00020000
-#define OMAP_DSP_DEVSTATE_KILLING      0x00040000
-#define OMAP_DSP_DEVSTATE_STATE_MASK   0x7fffffff
-#define OMAP_DSP_DEVSTATE_STALE                0x80000000
-
-struct omap_dsp_taddinfo {
-       unsigned char minor;
-       unsigned long taskadr;
-};
-#define OMAP_DSP_TADD_ABORTADR 0xffffffff
-
-
-/*
- * error cause definition (for error detection device)
- */
-#define OMAP_DSP_ERRDT_WDT     0x00000001
-#define OMAP_DSP_ERRDT_MMU     0x00000002
-
-
-/*
- * mailbox protocol definitions
- */
-
-struct omap_dsp_mailbox_cmd {
-       unsigned short cmd;
-       unsigned short data;
-};
-
-struct omap_dsp_reginfo {
-       unsigned short adr;
-       unsigned short val;
-};
-
-struct omap_dsp_varinfo {
-       unsigned char varid;
-       unsigned short val[0];
-};
-
-#define OMAP_DSP_MBPROT_REVISION       0x0019
-
-#define OMAP_DSP_MBCMD_WDSND   0x10
-#define OMAP_DSP_MBCMD_WDREQ   0x11
-#define OMAP_DSP_MBCMD_BKSND   0x20
-#define OMAP_DSP_MBCMD_BKREQ   0x21
-#define OMAP_DSP_MBCMD_BKYLD   0x23
-#define OMAP_DSP_MBCMD_BKSNDP  0x24
-#define OMAP_DSP_MBCMD_BKREQP  0x25
-#define OMAP_DSP_MBCMD_TCTL    0x30
-#define OMAP_DSP_MBCMD_TCTLDATA        0x31
-#define OMAP_DSP_MBCMD_POLL    0x32
-#define OMAP_DSP_MBCMD_WDT     0x50    /* v3.3: obsolete */
-#define OMAP_DSP_MBCMD_RUNLEVEL        0x51
-#define OMAP_DSP_MBCMD_PM      0x52
-#define OMAP_DSP_MBCMD_SUSPEND 0x53
-#define OMAP_DSP_MBCMD_KFUNC   0x54
-#define OMAP_DSP_MBCMD_TCFG    0x60
-#define OMAP_DSP_MBCMD_TADD    0x62
-#define OMAP_DSP_MBCMD_TDEL    0x63
-#define OMAP_DSP_MBCMD_TSTOP   0x65
-#define OMAP_DSP_MBCMD_DSPCFG  0x70
-#define OMAP_DSP_MBCMD_REGRW   0x72
-#define OMAP_DSP_MBCMD_GETVAR  0x74
-#define OMAP_DSP_MBCMD_SETVAR  0x75
-#define OMAP_DSP_MBCMD_ERR     0x78
-#define OMAP_DSP_MBCMD_DBG     0x79
-
-#define OMAP_DSP_MBCMD_TCTL_TINIT      0x0000
-#define OMAP_DSP_MBCMD_TCTL_TEN                0x0001
-#define OMAP_DSP_MBCMD_TCTL_TDIS       0x0002
-#define OMAP_DSP_MBCMD_TCTL_TCLR       0x0003
-#define OMAP_DSP_MBCMD_TCTL_TCLR_FORCE 0x0004
-
-#define OMAP_DSP_MBCMD_RUNLEVEL_USER           0x01
-#define OMAP_DSP_MBCMD_RUNLEVEL_SUPER          0x0e
-#define OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY       0x10
-
-#define OMAP_DSP_MBCMD_PM_DISABLE      0x00
-#define OMAP_DSP_MBCMD_PM_ENABLE       0x01
-
-#define OMAP_DSP_MBCMD_KFUNC_FBCTL     0x00
-#define OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR 0x01
-
-#define OMAP_DSP_MBCMD_FBCTL_UPD       0x0000
-#define OMAP_DSP_MBCMD_FBCTL_ENABLE    0x0002
-#define OMAP_DSP_MBCMD_FBCTL_DISABLE   0x0003
-
-#define OMAP_DSP_MBCMD_AUDIO_PWR_UP    0x0000
-#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1 0x0001
-#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2 0x0002
-
-#define OMAP_DSP_MBCMD_TDEL_SAFE       0x0000
-#define OMAP_DSP_MBCMD_TDEL_KILL       0x0001
-
-#define OMAP_DSP_MBCMD_DSPCFG_REQ      0x00
-#define OMAP_DSP_MBCMD_DSPCFG_SYSADRH  0x28
-#define OMAP_DSP_MBCMD_DSPCFG_SYSADRL  0x29
-#define OMAP_DSP_MBCMD_DSPCFG_PROTREV  0x70
-#define OMAP_DSP_MBCMD_DSPCFG_ABORT    0x78
-#define OMAP_DSP_MBCMD_DSPCFG_LAST     0x80
-
-#define OMAP_DSP_MBCMD_REGRW_MEMR      0x00
-#define OMAP_DSP_MBCMD_REGRW_MEMW      0x01
-#define OMAP_DSP_MBCMD_REGRW_IOR       0x02
-#define OMAP_DSP_MBCMD_REGRW_IOW       0x03
-#define OMAP_DSP_MBCMD_REGRW_DATA      0x04
-
-#define OMAP_DSP_MBCMD_VARID_ICRMASK   0x00
-#define OMAP_DSP_MBCMD_VARID_LOADINFO  0x01
-
-#define OMAP_DSP_TTYP_ARCV     0x0001
-#define OMAP_DSP_TTYP_ASND     0x0002
-#define OMAP_DSP_TTYP_BKMD     0x0004
-#define OMAP_DSP_TTYP_BKDM     0x0008
-#define OMAP_DSP_TTYP_PVMD     0x0010
-#define OMAP_DSP_TTYP_PVDM     0x0020
-
-#define OMAP_DSP_EID_BADTID    0x10
-#define OMAP_DSP_EID_BADTCN    0x11
-#define OMAP_DSP_EID_BADBID    0x20
-#define OMAP_DSP_EID_BADCNT    0x21
-#define OMAP_DSP_EID_NOTLOCKED 0x22
-#define OMAP_DSP_EID_STVBUF    0x23
-#define OMAP_DSP_EID_BADADR    0x24
-#define OMAP_DSP_EID_BADTCTL   0x30
-#define OMAP_DSP_EID_BADPARAM  0x50
-#define OMAP_DSP_EID_FATAL     0x58
-#define OMAP_DSP_EID_NOMEM     0xc0
-#define OMAP_DSP_EID_NORES     0xc1
-#define OMAP_DSP_EID_IPBFULL   0xc2
-#define OMAP_DSP_EID_WDT       0xd0
-#define OMAP_DSP_EID_TASKNOTRDY        0xe0
-#define OMAP_DSP_EID_TASKBSY   0xe1
-#define OMAP_DSP_EID_TASKERR   0xef
-#define OMAP_DSP_EID_BADCFGTYP 0xf0
-#define OMAP_DSP_EID_DEBUG     0xf8
-#define OMAP_DSP_EID_BADSEQ    0xfe
-#define OMAP_DSP_EID_BADCMD    0xff
-
-#define OMAP_DSP_TNM_LEN       16
-
-#define OMAP_DSP_TID_FREE      0xff
-#define OMAP_DSP_TID_ANON      0xfe
-
-#define OMAP_DSP_BID_NULL      0xffff
-#define OMAP_DSP_BID_PVT       0xfffe
-
-#endif /* ASM_ARCH_DSP_H */
index 16a459dfa714ab770da53bff8680d90a36a70d6c..2a851ebe675aad17b6562a9f3a9cd23d2ecbde30 100644 (file)
@@ -1,36 +1,35 @@
 /*
- * linux/include/asm-arm/arch-omap/dsp_common.h
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
  *
- * Header for OMAP DSP subsystem control
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
  *
- * Copyright (C) 2004,2005 Nokia Corporation
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
  *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * This program 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 program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  *
- * 2005/06/03:  DSP Gateway version 3.3
  */
 
 #ifndef ASM_ARCH_DSP_COMMON_H
 #define ASM_ARCH_DSP_COMMON_H
 
+#ifdef CONFIG_ARCH_OMAP1
 extern void omap_dsp_request_mpui(void);
 extern void omap_dsp_release_mpui(void);
 extern int omap_dsp_request_mem(void);
 extern int omap_dsp_release_mem(void);
+#endif
 
 extern void (*omap_dsp_audio_pwr_up_request)(int stage);
 extern void (*omap_dsp_audio_pwr_down_request)(int stage);
index 78f68e6a4f0c59a24407cd7fbe8c905dea0b97ec..4aca7e3d7566c1b9619e9ce60ec598fde09e8a82 100644 (file)
 #define io_p2v(pa)     ((pa) + IO_OFFSET)      /* Works for L3 and L4 */
 #define io_v2p(va)     ((va) - IO_OFFSET)      /* Works for L3 and L4 */
 
+/* DSP */
+#define DSP_MEM_24XX_PHYS      OMAP24XX_DSP_MEM_BASE   /* 0x58000000 */
+#define DSP_MEM_24XX_VIRT      0xe0000000
+#define DSP_MEM_24XX_SIZE      0x28000
+#define DSP_IPI_24XX_PHYS      OMAP24XX_DSP_IPI_BASE   /* 0x59000000 */
+#define DSP_IPI_24XX_VIRT      0xe1000000
+#define DSP_IPI_24XX_SIZE      SZ_4K
+#define DSP_MMU_24XX_PHYS      OMAP24XX_DSP_MMU_BASE   /* 0x5a000000 */
+#define DSP_MMU_24XX_VIRT      0xe2000000
+#define DSP_MMU_24XX_SIZE      SZ_4K
+
 #endif
 
 #ifndef __ASSEMBLER__
index c5bb05a69b81ec815c405d79b8b3bd553e29abc3..db940fbafe8416e5cb4eb9ed86c1f4146b84b799 100644 (file)
@@ -37,8 +37,6 @@
 #define INT_DSP_MMU_ABORT      7
 #define INT_HOST               8
 #define INT_ABORT              9
-#define INT_DSP_MAILBOX1       10
-#define INT_DSP_MAILBOX2       11
 #define INT_BRIDGE_PRIV                13
 #define INT_GPIO_BANK1         14
 #define INT_UART3              15
@@ -63,6 +61,8 @@
 #define INT_1510_RES2          2
 #define INT_1510_SPI_TX                4
 #define INT_1510_SPI_RX                5
+#define INT_1510_DSP_MAILBOX1  10
+#define INT_1510_DSP_MAILBOX2  11
 #define INT_1510_RES12         12
 #define INT_1510_LB_MMU                17
 #define INT_1510_RES18         18
@@ -75,6 +75,8 @@
 #define INT_1610_IH2_FIQ       2
 #define INT_1610_McBSP2_TX     4
 #define INT_1610_McBSP2_RX     5
+#define INT_1610_DSP_MAILBOX1  10
+#define INT_1610_DSP_MAILBOX2  11
 #define INT_1610_LCD_LINE      12
 #define INT_1610_GPTIMER1      17
 #define INT_1610_GPTIMER2      18
 #define INT_RTC_TIMER          (25 + IH2_BASE)
 #define INT_RTC_ALARM          (26 + IH2_BASE)
 #define INT_MEM_STICK          (27 + IH2_BASE)
-#define INT_DSP_MMU            (28 + IH2_BASE)
 
 /*
  * OMAP-1510 specific IRQ numbers for interrupt handler 2
  */
+#define INT_1510_DSP_MMU       (28 + IH2_BASE)
 #define INT_1510_COM_SPI_RO    (31 + IH2_BASE)
 
 /*
 #define INT_1610_USB_OTG       (8 + IH2_BASE)
 #define INT_1610_SoSSI         (9 + IH2_BASE)
 #define INT_1610_SoSSI_MATCH   (19 + IH2_BASE)
+#define INT_1610_DSP_MMU       (28 + IH2_BASE)
 #define INT_1610_McBSP2RX_OF   (31 + IH2_BASE)
 #define INT_1610_STI           (32 + IH2_BASE)
 #define INT_1610_STI_WAKEUP    (33 + IH2_BASE)
 #define INT_24XX_SDMA_IRQ3     15
 #define INT_24XX_CAM_IRQ       24
 #define INT_24XX_DSS_IRQ       25
+#define INT_24XX_MAIL_U0_MPU   26
+#define INT_24XX_DSP_UMA       27
+#define INT_24XX_DSP_MMU       28
 #define INT_24XX_GPIO_BANK1    29
 #define INT_24XX_GPIO_BANK2    30
 #define INT_24XX_GPIO_BANK3    31
 #define INT_24XX_GPIO_BANK4    32
+#define INT_24XX_MAIL_U3_MPU   34
 #define INT_24XX_GPTIMER1      37
 #define INT_24XX_GPTIMER2      38
 #define INT_24XX_GPTIMER3      39
diff --git a/include/asm-arm/arch-omap/mailbox.h b/include/asm-arm/arch-omap/mailbox.h
new file mode 100644 (file)
index 0000000..b677918
--- /dev/null
@@ -0,0 +1,54 @@
+/* mailbox.h */
+
+#ifndef MAILBOX_H
+#define MAILBOX_H
+
+typedef u32 mbx_msg_t;
+typedef void (mbx_receiver_t)(mbx_msg_t msg);
+
+struct mbx;    /* contents are private */
+
+struct mbx *mbx_get(const char *id);
+extern int mbx_send(struct mbx *mbx_h, mbx_msg_t msg);
+extern int register_mbx_receiver(struct mbx *mbx, unsigned char cmd,
+                                mbx_receiver_t *rcv);
+extern int unregister_mbx_receiver(struct mbx *mbx, unsigned char cmd,
+                                  mbx_receiver_t *rcv);
+extern void enable_mbx_irq(struct mbx *mbx);
+extern void disable_mbx_irq(struct mbx *mbx);
+extern void mbx_init_seq(struct mbx *mbx);
+
+/*
+ * mailbox command: 0x00 - 0x7f
+ * when a driver wants to use mailbox, it must reserve mailbox commands here.
+ */
+#define MBX_CMD_MAX    0x80
+
+/* DSP Gateway */
+#define MBX_CMD_DSP_WDSND      0x10
+#define MBX_CMD_DSP_WDREQ      0x11
+#define MBX_CMD_DSP_BKSND      0x20
+#define MBX_CMD_DSP_BKREQ      0x21
+#define MBX_CMD_DSP_BKYLD      0x23
+#define MBX_CMD_DSP_BKSNDP     0x24
+#define MBX_CMD_DSP_BKREQP     0x25
+#define MBX_CMD_DSP_TCTL       0x30
+#define MBX_CMD_DSP_TCTLDATA   0x31
+#define MBX_CMD_DSP_POLL       0x32
+#define MBX_CMD_DSP_WDT                0x50
+#define MBX_CMD_DSP_RUNLEVEL   0x51
+#define MBX_CMD_DSP_PM         0x52
+#define MBX_CMD_DSP_SUSPEND    0x53
+#define MBX_CMD_DSP_KFUNC      0x54
+#define MBX_CMD_DSP_TCFG       0x60
+#define MBX_CMD_DSP_TADD       0x62
+#define MBX_CMD_DSP_TDEL       0x63
+#define MBX_CMD_DSP_TSTOP      0x65
+#define MBX_CMD_DSP_DSPCFG     0x70
+#define MBX_CMD_DSP_REGRW      0x72
+#define MBX_CMD_DSP_GETVAR     0x74
+#define MBX_CMD_DSP_SETVAR     0x75
+#define MBX_CMD_DSP_ERR                0x78
+#define MBX_CMD_DSP_DBG                0x79
+
+#endif /* MAILBOX_H */
index 993572cfc1c4fb8cbd5d1694ed327e97fd304d49..b70063376f0a4ed2bc3d51781e2688c02e549daa 100644 (file)
 
 #define OMAP242X_CONTROL_STATUS        (L4_24XX_BASE + 0x2f8)
 
+/* DSP SS */
+#define OMAP24XX_DSP_BASE      0x58000000
+#define OMAP24XX_DSP_MEM_BASE  (OMAP24XX_DSP_BASE + 0x0)
+#define OMAP24XX_DSP_IPI_BASE  (OMAP24XX_DSP_BASE + 0x1000000)
+#define OMAP24XX_DSP_MMU_BASE  (OMAP24XX_DSP_BASE + 0x2000000)
+
 #endif /* __ASM_ARCH_OMAP24XX_H */