[PATCH] ARM: OMAP: DSP Gateway v3.3
authorToshiro Kobayashi <Toshihiro.Kobayashi@nokia.com>
Wed, 27 Jul 2005 11:06:19 +0000 (04:06 -0700)
committerTony Lindgren <tony@atomide.com>
Wed, 27 Jul 2005 11:06:19 +0000 (04:06 -0700)
This is DSP Gateway v3.3 patch.

21 files changed:
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_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/ipbuf.c
arch/arm/plat-omap/dsp/ipbuf.h
arch/arm/plat-omap/dsp/mblog.c
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/mcbsp.c
include/asm-arm/arch-omap/dsp.h
include/asm-arm/arch-omap/dsp_common.h

index 6282a281503d4c1d126ee123eae910678c121f37..0a4876630f791acd9ab6635a136e598d4f34c85b 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2005/01/21:  DSP Gateway version 3.2
+ * 2005/06/09:  DSP Gateway version 3.3
  */
 
 #include "hardware_dsp.h"
@@ -31,6 +31,7 @@
 
 #ifdef OLD_BINARY_SUPPORT
 #define MBREV_3_0      0x0017
+#define MBREV_3_2      0x0018
 #endif
 
 #define DSP_INIT_PAGE  0xfff000
 #define IDLEPG_BASE    0xfffe00
 #define IDLEPG_SIZE    0x100
 
+/* timeout value for DSP response */
+#define DSP_TIMEOUT    (10 * HZ)
+
+enum dsp_mem_type_e {
+       MEM_TYPE_CROSSING = -1,
+       MEM_TYPE_NONE = 0,
+       MEM_TYPE_DARAM,
+       MEM_TYPE_SARAM,
+       MEM_TYPE_EXTERN,
+};
+
+enum arm_dsp_dir {
+       DIR_A2D,
+       DIR_D2A,
+};
+
 /*
  * INT_D2A_MB value definition
  *   INT_DSP_MAILBOX1: use Mailbox 1 (INT 10) for DSP->ARM mailbox
 #define TASKDEV_MAX    254
 
 #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;
+};
+
+struct mem_sync_struct {
+       struct sync_seq *DARAM;
+       struct sync_seq *SARAM;
+       struct sync_seq *SDRAM;
+};
+
 /* struct mbcmd and struct mbcmd_hw must be compatible */
 struct mbcmd {
        unsigned short cmd_l:8;
@@ -79,26 +110,32 @@ struct mb_exarg {
 
 extern void dsp_mb_start(void);
 extern void dsp_mb_stop(void);
-extern void dsp_mb_config(void *sync_seq_adr);
+extern int dsp_mb_config(void *p);
 extern int sync_with_dsp(unsigned short *syncwd, unsigned short tid,
                         int try_cnt);
-extern int __mbsend(struct mbcmd *mb);
-extern int __dsp_mbsend(struct mbcmd *mb, struct mb_exarg *arg,
-                       int recovery_flag);
-#define dsp_mbsend(mb)                 __dsp_mbsend(mb, NULL, 0)
-#define dsp_mbsend_recovery(mb)                __dsp_mbsend(mb, NULL, 1)
-#define dsp_mbsend_exarg(mb, arg)      __dsp_mbsend(mb, arg, 0)
-extern int __dsp_mbsend_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
-                                wait_queue_head_t *q);
-#define dsp_mbsend_and_wait(mb, q) \
-       __dsp_mbsend_and_wait(mb, NULL, q)
-#define dsp_mbsend_and_wait_exarg(mb, arg, q) \
-       __dsp_mbsend_and_wait(mb, arg, q)
+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);
+#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)
 
 extern void ipbuf_start(void);
 extern void ipbuf_stop(void);
-extern int ipbuf_config(unsigned short ln, unsigned short lsz,
-                       unsigned long adr);
+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);
@@ -110,6 +147,8 @@ extern void balance_ipbuf(void);
                (ipbuf_pvt)->s = OMAP_DSP_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);
@@ -125,16 +164,24 @@ 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 long taskdev_state(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 void dsp_dbg_stop(void);
 
 extern int ipbuf_is_held(unsigned char tid, unsigned short bid);
 
+extern void dsp_mem_sync_inc(void);
+extern int dsp_mem_sync_config(struct mem_sync_struct *sync);
+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 int dsp_mem_disable(void *adr);
-extern int __dsp_mem_enable(void *adr);
-extern int __dsp_mem_disable(void *adr);
+extern void dsp_mem_disable(void *adr);
+extern void dsp_mem_usecount_clear(void);
+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);
 extern void dsp_mem_start(void);
+extern void dsp_mem_stop(void);
 
 extern void dsp_twch_start(void);
 extern void dsp_twch_stop(void);
@@ -165,14 +212,9 @@ extern const struct cmdinfo *cmdinfo[];
 #define cmd_name(mb)   (cmdinfo[(mb).cmd_h]->name)
 extern char *subcmd_name(struct mbcmd *mb);
 
-enum mblog_dir {
-       MBLOG_DIR_AD,
-       MBLOG_DIR_DA,
-};
-
-extern void mblog_add(struct mbcmd *mb, enum mblog_dir dir);
+extern void mblog_add(struct mbcmd *mb, enum arm_dsp_dir dir);
 #ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
-extern void mblog_printcmd(struct mbcmd *mb, enum mblog_dir dir);
+extern void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir dir);
 #else /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
 #define mblog_printcmd(mb, dir)        do {} while(0)
 #endif /* CONFIG_OMAP_DSP_MBCMD_VERBOSE */
index e24c1afbbaddf3d5806e4df1a11a227ee4fe1e4b..a8b72ee81d1130bff136255a0926cd8864afab17 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2004/11/19:  DSP Gateway version 3.2
+ * 2005/06/13:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
 
 struct clk *dsp_ck_handle;
 struct clk *api_ck_handle;
-unsigned long dspmem_base, dspmem_size;
-int dsp_runstat = RUNSTAT_RESET;
-unsigned short dsp_icrmask = DSPREG_ICR_EMIF_IDLE_DOMAIN |
-                            DSPREG_ICR_DPLL_IDLE_DOMAIN |
-                            DSPREG_ICR_PER_IDLE_DOMAIN |
-                            DSPREG_ICR_CACHE_IDLE_DOMAIN |
-                            DSPREG_ICR_DMA_IDLE_DOMAIN |
-                            DSPREG_ICR_CPU_IDLE_DOMAIN;
+unsigned long dspmem_base, dspmem_size,
+             daram_base, daram_size,
+             saram_base, saram_size;
+
+struct cpustat {
+       struct semaphore sem;
+       enum e_cpustat stat;
+       enum e_cpustat req;
+       unsigned short icrmask;
+       struct {
+               int mpui;
+               int mem;
+               int mem_delayed;
+       } usecount;
+       int (*mem_req_cb)(void);
+       void (*mem_rel_cb)(void);
+};
+struct cpustat cpustat = {
+       .sem = __MUTEX_INITIALIZER(cpustat.sem),
+       .stat = CPUSTAT_RESET,
+       .icrmask = 0xffff,
+};
 
 int dsp_set_rstvect(unsigned long adr)
 {
@@ -88,22 +102,59 @@ static void simple_load_code(unsigned char *src_c, unsigned short *dst, int len)
 }
 
 /* program size must be multiple of 2 */
-#define IDLE_TEXT_SIZE 28
-#define IDLE_TEXT(icr) { \
+#define GBL_IDLE_TEXT_SIZE     52
+#define GBL_IDLE_TEXT_INIT { \
+       /* SAM */ \
+       0x3c, 0x4a,                     /* 0x3c4a:     MOV 0x4, AR2 */ \
+       0xf4, 0x41, 0xfc, 0xff,         /* 0xf441fcff: AND 0xfcff, *AR2 */ \
        /* disable WDT */ \
-       0x76, 0x34, 0x04, 0xb8,         /* 0x763404b8: mov AR3 0x3404 */ \
-       0xfb, 0x61, 0x00, 0xf5,         /* 0xfb6100f5: mov *AR3 0x00f5 */ \
-       0x9a,                           /* 0x9a:       port */ \
-       0xfb, 0x61, 0x00, 0xa0,         /* 0xfb6100a0: mov *AR3 0x00a0 */ \
-       0x9a,                           /* 0x9a:       port */ \
+       0x76, 0x34, 0x04, 0xb8,         /* 0x763404b8: MOV 0x3404, AR3 */ \
+       0xfb, 0x61, 0x00, 0xf5,         /* 0xfb6100f5: MOV 0x00f5, *AR3 */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       0xfb, 0x61, 0x00, 0xa0,         /* 0xfb6100a0: MOV 0x00a0, *AR3 */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       /* *IER0 = 0, *IER1 = 0 */ \
+       0x3c, 0x0b,                     /* 0x3c0b:     MOV 0x0, AR3 */ \
+       0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
+       0x76, 0x00, 0x45, 0xb8,         /* 0x76004508: MOV 0x45, AR3 */ \
+       0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
+       /* *ICR = 0xffff */ \
+       0x3c, 0x1b,                     /* 0x3c1b:     MOV 0x1, AR3 */ \
+       0xfb, 0x61, 0xff, 0xff,         /* 0xfb61ffff: MOV 0xffff, *AR3 */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       /* HOM */ \
+       0xf5, 0x41, 0x03, 0x00,         /* 0xf5410300: OR 0x0300, *AR2 */ \
+       /* idle and loop forever */ \
+       0x7a, 0x00, 0x00, 0x0c,         /* 0x7a00000c: IDLE */ \
+       0x4a, 0x7a,                     /* 0x4a7a:     B -6 (infinite loop) */ \
+       0x20, 0x20, 0x20,               /* 0x20:       NOP */ \
+}
+
+/* program size must be multiple of 2 */
+#define CPU_IDLE_TEXT_SIZE     48
+#define CPU_IDLE_TEXT_INIT(icrh, icrl) { \
+       /* SAM */ \
+       0x3c, 0x4b,                     /* 0x3c4b:     MOV 0x4, AR3 */ \
+       0xf4, 0x61, 0xfc, 0xff,         /* 0xf461fcff: AND 0xfcff, *AR3 */ \
+       /* disable WDT */ \
+       0x76, 0x34, 0x04, 0xb8,         /* 0x763404b8: MOV 0x3404, AR3 */ \
+       0xfb, 0x61, 0x00, 0xf5,         /* 0xfb6100f5: MOV 0x00f5, *AR3 */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       0xfb, 0x61, 0x00, 0xa0,         /* 0xfb6100a0: MOV 0x00a0, *AR3 */ \
+       0x9a,                           /* 0x9a:       PORT */ \
+       /* *IER0 = 0, *IER1 = 0 */ \
+       0x3c, 0x0b,                     /* 0x3c0b:     MOV 0x0, AR3 */ \
+       0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
+       0x76, 0x00, 0x45, 0xb8,         /* 0x76004508: MOV 0x45, AR3 */ \
+       0xe6, 0x61, 0x00,               /* 0xe66100:   MOV 0, *AR3 */ \
        /* set ICR = icr */ \
-       0x3c, 0x1b,                     /* 0x3c1b:     mov AR3 0x1 */ \
-       0xe6, 0x61, (icr),              /* 0xe661**:   mov *AR3, icr */ \
-       0x9a,                           /* 0x9a:       port */ \
+       0x3c, 0x1b,                     /* 0x3c1b:     MOV AR3 0x1 */ \
+       0xfb, 0x61, (icrh), (icrl),     /* 0xfb61****: MOV *AR3, icr */ \
+       0x9a,                           /* 0x9a:       PORT */ \
        /* idle and loop forever */ \
-       0x7a, 0x00, 0x00, 0x0c,         /* 0x7a00000c: idle */ \
-       0x4a, 0x7a,                     /* 0x4a7a:     b -6 (infinite loop) */ \
-       0x20, 0x20                      /* 0x20: nop */ \
+       0x7a, 0x00, 0x00, 0x0c,         /* 0x7a00000c: IDLE */ \
+       0x4a, 0x7a,                     /* 0x4a7a:     B -6 (infinite loop) */ \
+       0x20, 0x20, 0x20                /* 0x20: nop */ \
 }
 
 /*
@@ -115,38 +166,57 @@ static void simple_load_code(unsigned char *src_c, unsigned short *dst, int len)
  */
 static unsigned long idle_boot_base = DSP_BOOT_ADR_MPUI;
 
-void dsp_idle(void)
+static void dsp_gbl_idle(void)
+{
+       unsigned char idle_text[GBL_IDLE_TEXT_SIZE] = GBL_IDLE_TEXT_INIT;
+
+       __dsp_reset();
+       clk_use(api_ck_handle);
+
+#if 0
+       omap_writew(MPUI_DSP_BOOT_CONFIG_IDLE, MPUI_DSP_BOOT_CONFIG);
+#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);
+       else
+               dsp_set_rstvect(idle_boot_base);
+
+       __dsp_run();
+       udelay(100);    /* to make things stable */
+       clk_unuse(api_ck_handle);
+}
+
+static void dsp_cpu_idle(void)
 {
-       unsigned char icr;
+       unsigned short icr_tmp;
+       unsigned char icrh, icrl;
 
-       disable_irq(INT_DSP_MMU);
-       preempt_disable();
        __dsp_reset();
        clk_use(api_ck_handle);
 
        /*
         * icr settings:
         * DMA should not sleep for DARAM/SARAM access
-        * DPLL should not sleep for DMA.
+        * DPLL should not sleep while any other domain is active
         */
-       icr = dsp_icrmask &
-             ~(DSPREG_ICR_DMA_IDLE_DOMAIN | DSPREG_ICR_DPLL_IDLE_DOMAIN) &
-             0xff;
+       icr_tmp = cpustat.icrmask & ~(DSPREG_ICR_DMA_IDLE_DOMAIN |
+                                     DSPREG_ICR_DPLL_IDLE_DOMAIN);
+       icrh = icr_tmp >> 8;
+       icrl = icr_tmp & 0xff;
        {
-               unsigned char idle_text[IDLE_TEXT_SIZE] = IDLE_TEXT(icr);
+               unsigned char idle_text[CPU_IDLE_TEXT_SIZE] = CPU_IDLE_TEXT_INIT(icrh, icrl);
                simple_load_code(idle_text, dspbyte_to_virt(idle_boot_base),
-                                IDLE_TEXT_SIZE);
+                                CPU_IDLE_TEXT_SIZE);
        }
        if (idle_boot_base == DSP_BOOT_ADR_MPUI)
                omap_writew(MPUI_DSP_BOOT_CONFIG_MPUI, MPUI_DSP_BOOT_CONFIG);
        else
                dsp_set_rstvect(idle_boot_base);
-       clk_unuse(api_ck_handle);
-       udelay(10);     /* to make things stable */
        __dsp_run();
-       dsp_runstat = RUNSTAT_IDLE;
-       preempt_enable();
-       enable_irq(INT_DSP_MMU);
+       udelay(100);    /* to make things stable */
+       clk_unuse(api_ck_handle);
 }
 
 void dsp_set_idle_boot_base(unsigned long adr, size_t size)
@@ -154,13 +224,18 @@ void dsp_set_idle_boot_base(unsigned long adr, size_t size)
        if (adr == idle_boot_base)
                return;
        idle_boot_base = adr;
-       if (size < IDLE_TEXT_SIZE) {
+       if ((size < GBL_IDLE_TEXT_SIZE) ||
+           (size < CPU_IDLE_TEXT_SIZE)) {
                printk(KERN_ERR
                       "omapdsp: size for idle program is not enough!\n");
                BUG();
        }
-       if (dsp_runstat == RUNSTAT_IDLE)
-               dsp_idle();
+
+       /* restart idle program with new base address */
+       if (cpustat.stat == CPUSTAT_GBL_IDLE)
+               dsp_gbl_idle();
+       if (cpustat.stat == CPUSTAT_CPU_IDLE)
+               dsp_cpu_idle();
 }
 
 static unsigned short save_dsp_idlect2;
@@ -197,9 +272,10 @@ void omap_dsp_pm_resume(void)
        omap_writew(save_arm_idlect2, ARM_IDLECT2);
 
        /* Run DSP, if it was running */
-       if (dsp_runstat != RUNSTAT_RESET)
+       if (cpustat.stat != CPUSTAT_RESET)
                __dsp_run();
 }
+
 static int init_done;
 
 static int __init omap_dsp_init(void)
@@ -209,12 +285,20 @@ static int __init omap_dsp_init(void)
        if (cpu_is_omap1510()) {
                dspmem_base = OMAP1510_DSP_BASE;
                dspmem_size = OMAP1510_DSP_SIZE;
+               daram_base = OMAP1510_DARAM_BASE;
+               daram_size = OMAP1510_DARAM_SIZE;
+               saram_base = OMAP1510_SARAM_BASE;
+               saram_size = OMAP1510_SARAM_SIZE;
        }
 #endif
 #ifdef CONFIG_ARCH_OMAP16XX
        if (cpu_is_omap16xx()) {
                dspmem_base = OMAP16XX_DSP_BASE;
                dspmem_size = OMAP16XX_DSP_SIZE;
+               daram_base = OMAP16XX_DARAM_BASE;
+               daram_size = OMAP16XX_DARAM_SIZE;
+               saram_base = OMAP16XX_SARAM_BASE;
+               saram_size = OMAP16XX_SARAM_SIZE;
        }
 #endif
        if (dspmem_size == 0) {
@@ -243,31 +327,228 @@ static int __init omap_dsp_init(void)
        return 0;
 }
 
-void omap_dsp_request_idle(void)
+static void dsp_cpustat_update(void)
 {
-       if (dsp_runstat == RUNSTAT_RESET) {
-               if (!init_done)
-                       omap_dsp_init();
-               dsp_idle();
+       if (!init_done)
+               omap_dsp_init();
+
+       if (cpustat.req == CPUSTAT_RUN) {
+               if (cpustat.stat < CPUSTAT_RUN) {
+                       __dsp_reset();
+                       clk_use(api_ck_handle);
+                       udelay(10);
+                       __dsp_run();
+                       cpustat.stat = CPUSTAT_RUN;
+                       enable_irq(INT_DSP_MMU);
+               }
+               return;
+       }
+
+       /* cpustat.stat < CPUSTAT_RUN */
+
+       if (cpustat.stat == CPUSTAT_RUN) {
+               disable_irq(INT_DSP_MMU);
+               clk_unuse(api_ck_handle);
+       }
+
+       /*
+        * (1) when ARM wants DARAM access, MPUI should be SAM and
+        *     DSP needs to be on.
+        * (2) if any bits of icr is masked, we can not enter global idle.
+        */
+       if ((cpustat.req == CPUSTAT_CPU_IDLE) ||
+           (cpustat.usecount.mem > 0) ||
+           (cpustat.usecount.mem_delayed > 0) ||
+           ((cpustat.usecount.mpui > 0) && (cpustat.icrmask != 0xffff))) {
+               if (cpustat.stat != CPUSTAT_CPU_IDLE) {
+                       dsp_cpu_idle();
+                       cpustat.stat = CPUSTAT_CPU_IDLE;
+               }
+               return;
+       }
+
+       /*
+        * when ARM only needs MPUI access, MPUI can be HOM and
+        * DSP can be idling.
+        */
+       if ((cpustat.req == CPUSTAT_GBL_IDLE) ||
+           (cpustat.usecount.mpui > 0)) {
+               if (cpustat.stat != CPUSTAT_GBL_IDLE) {
+                       dsp_gbl_idle();
+                       cpustat.stat = CPUSTAT_GBL_IDLE;
+               }
+               return;
+       }
+
+       /*
+        * no user, no request
+        */
+       if (cpustat.stat != CPUSTAT_RESET) {
+               __dsp_reset();
+               cpustat.stat = CPUSTAT_RESET;
        }
 }
 
+void dsp_cpustat_request(enum e_cpustat req)
+{
+       down(&cpustat.sem);
+       cpustat.req = req;
+       dsp_cpustat_update();
+       up(&cpustat.sem);
+}
+
+enum e_cpustat dsp_cpustat_get_stat(void)
+{
+       return cpustat.stat;
+}
+
+unsigned short dsp_cpustat_get_icrmask(void)
+{
+       return cpustat.icrmask;
+}
+
+void dsp_cpustat_set_icrmask(unsigned short mask)
+{
+       down(&cpustat.sem);
+       cpustat.icrmask = mask;
+       dsp_cpustat_update();
+       up(&cpustat.sem);
+}
+
+void omap_dsp_request_mpui(void)
+{
+       down(&cpustat.sem);
+       if (cpustat.usecount.mpui++ == 0)
+               dsp_cpustat_update();
+       up(&cpustat.sem);
+}
+
+void omap_dsp_release_mpui(void)
+{
+       down(&cpustat.sem);
+       if (cpustat.usecount.mpui-- == 0) {
+               printk(KERN_ERR
+                      "omapdsp: unbalanced mpui request/release detected.\n"
+                      "         cpustat.usecount.mpui is going to be "
+                      "less than zero! ... fixed to be zero.\n");
+               cpustat.usecount.mpui = 0;
+       }
+       if (cpustat.usecount.mpui == 0)
+               dsp_cpustat_update();
+       up(&cpustat.sem);
+}
+
+int omap_dsp_request_mem(void)
+{
+       int ret = 0;
+
+       down(&cpustat.sem);
+       if ((cpustat.usecount.mem++ == 0) &&
+           (cpustat.usecount.mem_delayed == 0)) {
+               if (cpustat.mem_req_cb) {
+                       if ((ret = cpustat.mem_req_cb()) < 0) {
+                               cpustat.usecount.mem--;
+                               goto out;
+                       }
+               }
+               dsp_cpustat_update();
+       }
+out:
+       up(&cpustat.sem);
+
+       return ret;
+}
+
+/*
+ * release_mem will be delayed.
+ */
+static void do_release_mem(void) {
+       down(&cpustat.sem);
+       cpustat.usecount.mem_delayed = 0;
+       if (cpustat.usecount.mem == 0) {
+               dsp_cpustat_update();
+               if (cpustat.mem_rel_cb)
+                       cpustat.mem_rel_cb();
+       }
+       up(&cpustat.sem);
+}
+
+static DECLARE_WORK(mem_rel_work, (void (*)(void *))do_release_mem, NULL);
+
+int omap_dsp_release_mem(void)
+{
+       down(&cpustat.sem);
+
+       /* cancel previous release work */
+       cancel_delayed_work(&mem_rel_work);
+       cpustat.usecount.mem_delayed = 0;
+
+       if (cpustat.usecount.mem-- == 0) {
+               printk(KERN_ERR
+                      "omapdsp: unbalanced memory request/release detected.\n"
+                      "         cpustat.usecount.mem is going to be "
+                      "less than zero! ... fixed to be zero.\n");
+               cpustat.usecount.mem = 0;
+       }
+       if (cpustat.usecount.mem == 0) {
+               cpustat.usecount.mem_delayed = 1;
+               schedule_delayed_work(&mem_rel_work, HZ);
+       }
+
+       up(&cpustat.sem);
+
+       return 0;
+}
+
+void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void))
+{
+       down(&cpustat.sem);
+
+       cpustat.mem_req_cb = req_cb;
+       cpustat.mem_rel_cb = rel_cb;
+
+       /*
+        * This function must be called while mem is enabled!
+        */
+       BUG_ON(cpustat.usecount.mem == 0);
+
+       up(&cpustat.sem);
+}
+
+void dsp_unregister_mem_cb(void)
+{
+       down(&cpustat.sem);
+       cpustat.mem_req_cb = NULL;
+       cpustat.mem_rel_cb = NULL;
+       up(&cpustat.sem);
+}
+
 arch_initcall(omap_dsp_init);
 
 EXPORT_SYMBOL(omap_dsp_pm_suspend);
 EXPORT_SYMBOL(omap_dsp_pm_resume);
-EXPORT_SYMBOL(omap_dsp_request_idle);
+EXPORT_SYMBOL(omap_dsp_request_mpui);
+EXPORT_SYMBOL(omap_dsp_release_mpui);
+EXPORT_SYMBOL(omap_dsp_request_mem);
+EXPORT_SYMBOL(omap_dsp_release_mem);
 
 #ifdef CONFIG_OMAP_DSP_MODULE
 EXPORT_SYMBOL(dsp_ck_handle);
 EXPORT_SYMBOL(api_ck_handle);
 EXPORT_SYMBOL(dspmem_base);
 EXPORT_SYMBOL(dspmem_size);
-EXPORT_SYMBOL(dsp_runstat);
-EXPORT_SYMBOL(dsp_icrmask);
+EXPORT_SYMBOL(daram_base);
+EXPORT_SYMBOL(daram_size);
+EXPORT_SYMBOL(saram_base);
+EXPORT_SYMBOL(saram_size);
 EXPORT_SYMBOL(dsp_set_rstvect);
-EXPORT_SYMBOL(dsp_idle);
 EXPORT_SYMBOL(dsp_set_idle_boot_base);
+EXPORT_SYMBOL(dsp_cpustat_request);
+EXPORT_SYMBOL(dsp_cpustat_get_stat);
+EXPORT_SYMBOL(dsp_cpustat_get_icrmask);
+EXPORT_SYMBOL(dsp_cpustat_set_icrmask);
+EXPORT_SYMBOL(dsp_register_mem_cb);
+EXPORT_SYMBOL(dsp_unregister_mem_cb);
 
 EXPORT_SYMBOL(__cpu_flush_kern_tlb_range);
 #endif
index a4b2610a39d3904eb24f3bbd0ce6e4c7696c7bbc..36034bd8ae42beaccca54bc89c11437646fe8ed7 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2004/11/16:  DSP Gateway version 3.2
+ * 2005/06/13:  DSP Gateway version 3.3
  */
 
 #include "hardware_dsp.h"
  *   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)
 
 #define mpui_wordswap_off() \
-       { \
+       do { \
                omap_writel( \
                        (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_WORDSWAP_MASK) | \
                        MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL); \
        } while(0)
 
 #define mpui_byteswap_on() \
-       { \
+       do { \
                omap_writel( \
                        (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_BYTESWAP_MASK) | \
                        MPUI_CTRL_BYTESWAP_API, MPUI_CTRL); \
        } while(0)
 
 #define mpui_byteswap_off() \
-       { \
+       do { \
                omap_writel( \
                        (omap_readl(MPUI_CTRL) & ~MPUI_CTRL_BYTESWAP_MASK) | \
                        MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL); \
  * TC wordswap on / off
  */
 #define tc_wordswap() \
-       { \
+       do { \
                omap_writel(TC_ENDIANISM_SWAP_WORD | TC_ENDIANISM_EN, \
                            TC_ENDIANISM); \
        } while(0)
 
 #define tc_noswap() \
-       {  \
+       do {  \
                omap_writel(omap_readl(TC_ENDIANISM) & ~TC_ENDIANISM_EN, \
                            TC_ENDIANISM); \
        } while(0)
 #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)
 
-#define        RUNSTAT_RESET   0
-#define        RUNSTAT_IDLE    1
-#define        RUNSTAT_RUN     2
-
 extern struct clk *dsp_ck_handle;
 extern struct clk *api_ck_handle;
-extern unsigned long dspmem_base, dspmem_size;
-extern int dsp_runstat;
-extern unsigned short dsp_icrmask;
+extern unsigned long dspmem_base, dspmem_size,
+                    daram_base, daram_size,
+                    saram_base, saram_size;
+
+enum e_cpustat {
+       CPUSTAT_RESET = 0,
+       CPUSTAT_GBL_IDLE = 1,
+       CPUSTAT_CPU_IDLE = 2,
+       CPUSTAT_RUN = 3
+};
+
+#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_idle(void);
 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);
+void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void));
+void dsp_unregister_mem_cb(void);
index e86d3599a951133d96b614e1507b09221124c028..c0a06492f40a09b3aaa0cf743bc43c6614189f70 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2005/02/15:  DSP Gateway version 3.2
+ * 2005/06/07:  DSP Gateway version 3.3
  */
 
 #include <linux/init.h>
@@ -55,17 +55,11 @@ enum mbseq_check_level {
 };
 
 static enum mbseq_check_level mbseq_check_level = MBSEQ_CHECK_VERBOSE;
-static unsigned short mbseq_send;
-static unsigned short mbseq_expect;
-
-struct sync_seq {
-       unsigned short da_dsp;
-       unsigned short da_arm;
-       unsigned short ad_dsp;
-       unsigned short ad_arm;
-};
 
-static struct sync_seq *sync_seq;
+static int mbx1_valid;
+static struct sync_seq *mbseq;
+static unsigned short mbseq_expect_tmp;
+static unsigned short *mbseq_expect = &mbseq_expect_tmp;
 
 /*
  * mailbox commands
@@ -78,7 +72,11 @@ 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);
+#ifdef OLD_BINARY_SUPPORT
+/* v3.3 obsolete */
 extern void mbx1_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);
@@ -100,7 +98,11 @@ static const struct cmdinfo
        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    },
+#ifdef OLD_BINARY_SUPPORT
+       /* v3.3 obsolete */
        cif_wdt      = { "WDT",      CMD_L_TYPE_NULL,   mbx1_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 },
@@ -129,7 +131,7 @@ const struct cmdinfo *cmdinfo[128] = {
        &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_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,
@@ -137,7 +139,12 @@ const struct cmdinfo *cmdinfo[128] = {
        &cif_null, &cif_null, &cif_null, &cif_null,
        &cif_null, &cif_null, &cif_null, &cif_null,
        &cif_null, &cif_null, &cif_null, &cif_null,
+#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,
+#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,
@@ -207,7 +214,7 @@ static __inline__ int mbsync_irq_save(unsigned long *flags, int try_cnt)
 #define print_mb_mmu_abort(mb) do {} while(0)
 #endif /* !CONFIG_OMAP_DSP_MBCMD_VERBOSE */
 
-int __mbsend(struct mbcmd *mb)
+int __mbcmd_send(struct mbcmd *mb)
 {
        struct mbcmd_hw *mb_hw = (struct mbcmd_hw *)mb;
        unsigned long flags;
@@ -220,12 +227,13 @@ int __mbsend(struct mbcmd *mb)
                return -1;
        }
 
-       mb->seq = mbseq_send & 1;
-       mbseq_send++;
-       if (sync_seq)
-               sync_seq->ad_arm = mbseq_send;
-       mblog_add(mb, MBLOG_DIR_AD);
-       mblog_printcmd(mb, MBLOG_DIR_AD);
+       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);
@@ -235,9 +243,9 @@ int __mbsend(struct mbcmd *mb)
 }
 
 /*
- * __dsp_mbsend(): mailbox dispatcher
+ * __dsp_mbcmd_send(): mailbox dispatcher
  */
-int __dsp_mbsend(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
+int __dsp_mbcmd_send(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
 {
        static DECLARE_MUTEX(mbsend_sem);
        int ret = 0;
@@ -257,10 +265,18 @@ int __dsp_mbsend(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
        if (arg) {      /* we have extra argument */
                int i;
 
-               if (__dsp_mem_enable(ipbuf_sys_ad) < 0)
-                       goto out;
+               /*
+                * even if ipbuf_sys_ad is in DSP internal memory, 
+                * dsp_mem_enable() never cause to call PM mailbox command
+                * because in that case DSP memory should be always enabled.
+                * (see ipbuf_sys_hold_mem_active in ipbuf.c)
+                *
+                * 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) {
                        printk(KERN_ERR "omapdsp: ipbuf_sys_ad is busy.\n");
+                       dsp_mem_disable(ipbuf_sys_ad);
                        ret = -EBUSY;
                        goto out;
                }
@@ -268,19 +284,18 @@ int __dsp_mbsend(struct mbcmd *mb, struct mb_exarg *arg, int recovery_flag)
                        ipbuf_sys_ad->d[i] = arg->argv[i];
                }
                ipbuf_sys_ad->s = arg->tid;
-               if (__dsp_mem_disable(ipbuf_sys_ad) < 0)
-                       goto out;
+               dsp_mem_disable(ipbuf_sys_ad);
        }
 
-       ret = __mbsend(mb);
+       ret = __mbcmd_send(mb);
 
 out:
        up(&mbsend_sem);
        return ret;
 }
 
-int __dsp_mbsend_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
-                         wait_queue_head_t *q)
+int __dsp_mbcmd_send_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
+                             wait_queue_head_t *q)
 {
        long current_state;
        DECLARE_WAITQUEUE(wait, current);
@@ -288,36 +303,72 @@ int __dsp_mbsend_and_wait(struct mbcmd *mb, struct mb_exarg *arg,
        add_wait_queue(q, &wait);
        current_state = current->state;
        set_current_state(TASK_INTERRUPTIBLE);
-       if (dsp_mbsend_exarg(mb, arg) < 0) {
+       if (dsp_mbcmd_send_exarg(mb, arg) < 0) {
                set_current_state(current_state);
                remove_wait_queue(q, &wait);
                return -1;
        }
-       schedule();
+       schedule_timeout(DSP_TIMEOUT);
        set_current_state(current_state);
        remove_wait_queue(q, &wait);
 
        return 0;
 }
 
+int __dsp_mbsend(unsigned char cmdh, unsigned char cmdl, unsigned short data,
+                int recovery_flag)
+{
+       struct mbcmd mb;
+
+       mbcmd_set(mb, cmdh, cmdl, data);
+       return __dsp_mbcmd_send(&mb, NULL, recovery_flag);
+}
+
+static int mbsync_hold_mem_active;
+
 void dsp_mb_start(void)
 {
-       mbseq_send = 0;
-       mbseq_expect = 0;
+       mbx1_valid = 1; /* start interpreting */
+       mbseq_expect_tmp = 0;
 }
 
 void dsp_mb_stop(void)
 {
-       sync_seq = NULL;
+       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;
 }
 
-/*
- * dsp_mb_config() is called from mbx1 workqueue
- */
-void dsp_mb_config(void *sync_seq_adr)
+int dsp_mb_config(void *p)
 {
-       sync_seq = sync_seq_adr;
-       sync_seq->da_arm = mbseq_expect;
+       unsigned long flags;
+
+       if (dsp_address_validate(p, sizeof(struct sync_seq), "mbseq") < 0)
+               return -1;
+       if (dsp_mem_type(p, sizeof(struct sync_seq)) != MEM_TYPE_EXTERN) {
+               printk(KERN_WARNING
+                      "omapdsp: mbseq is placed in DSP internal memory.\n"
+                      "         It will prevent DSP from idling.\n");
+               mbsync_hold_mem_active = 1;
+               /*
+                * dsp_mem_enable() never fails because
+                * it has been already enabled in dspcfg process and
+                * this will just increment the usecount.
+                */
+               dsp_mem_enable((void *)daram_base);
+       }
+
+       local_irq_save(flags);
+       mbseq = p;
+       mbseq->da_arm = mbseq_expect_tmp;
+       mbseq_expect = &mbseq->da_arm;
+       local_irq_restore(flags);
+
+       return 0;
 }
 
 /*
@@ -351,8 +402,8 @@ static void do_mbx1(void)
 
                mb = &mbq.mb[mbq.rp];
 
-               mblog_add(mb, MBLOG_DIR_DA);
-               mblog_printcmd(mb, MBLOG_DIR_DA);
+               mblog_add(mb, DIR_D2A);
+               mblog_printcmd(mb, DIR_D2A);
 
                /*
                 * call handler for each command
@@ -386,7 +437,6 @@ static DECLARE_WORK(mbx1_work, (void (*)(void *))do_mbx1, NULL);
 /*
  * kernel function dispatcher
  */
-#ifdef CONFIG_FB_OMAP_EXTERNAL_LCDC
 extern void mbx1_fbctl_disable(void);
 
 static void mbx1_kfunc_fbctl(unsigned short data)
@@ -400,16 +450,13 @@ static void mbx1_kfunc_fbctl(unsigned short data)
                       "mailbox: Unknown FBCTL from DSP: 0x%04x\n", data);
        }
 }
-#endif
 
 static void mbx1_kfunc(struct mbcmd *mb)
 {
        switch (mb->cmd_l) {
-#ifdef CONFIG_FB_OMAP_EXTERNAL_LCDC
        case OMAP_DSP_MBCMD_KFUNC_FBCTL:
                mbx1_kfunc_fbctl(mb->data);
                break;
-#endif
 
        default:
                printk(KERN_ERR
@@ -435,7 +482,11 @@ static irqreturn_t mbx1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        mb->hw.cmd  = omap_readw(MAILBOX_DSP2ARM2b);
 #endif
 
-       if (mb->sw.seq != (mbseq_expect & 1)) {
+       /* 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;
@@ -449,9 +500,7 @@ static irqreturn_t mbx1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                }
        }
 
-       mbseq_expect++;
-       if (sync_seq)
-               sync_seq->da_arm = mbseq_expect;
+       (*mbseq_expect)++;
 
        mbq_inc(mbq.wp);
        if (mbq.wp == mbq.rp) { /* mbq is full */
@@ -585,6 +634,9 @@ static int __init dsp_drv_probe(struct device *dev)
                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) {
@@ -617,7 +669,7 @@ fail1:
 
 static int dsp_drv_remove(struct device *dev)
 {
-       __dsp_reset();
+       dsp_cpustat_request(CPUSTAT_RESET);
 
 #if 0
        free_irq(INT_MPUIO, dev);
@@ -626,6 +678,9 @@ static int dsp_drv_remove(struct device *dev)
        free_irq(INT_D2A_MB2, dev);
        free_irq(INT_D2A_MB1, dev);
 
+       /* recover disable_depth */
+       enable_irq(INT_DSP_MMU);
+
        dspuncfg();
        dsp_taskmod_exit();
        mblog_exit();
index 985b852a8fd0dc5983009f1ed145083042cd7f95..4031cf8e85c0d7ffb58665697697fbdb7ab5fd32 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2005/02/17:  DSP Gateway version 3.2
+ * 2005/06/09:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
@@ -47,12 +47,12 @@ static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
 static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
 extern struct device_attribute dev_attr_ipbuf;
 
-static enum {
+static enum cfgstat {
        CFG_ERR,
        CFG_READY,
        CFG_SUSPEND
 } cfgstat;
-static int mbx_revision;
+int mbx_revision;
 static DECLARE_WAIT_QUEUE_HEAD(ioctl_wait_q);
 static unsigned short ioctl_wait_cmd;
 static DECLARE_MUTEX(ioctl_sem);
@@ -62,33 +62,6 @@ static unsigned char n_stask;
 /*
  * control functions
  */
-static void dsp_run(void)
-{
-       disable_irq(INT_DSP_MMU);
-       preempt_disable();
-       if (dsp_runstat == RUNSTAT_RESET) {
-               clk_use(api_ck_handle);
-               __dsp_run();
-               dsp_runstat = RUNSTAT_RUN;
-       }
-       preempt_enable();
-       enable_irq(INT_DSP_MMU);
-}
-
-static void dsp_reset(void)
-{
-       disable_irq(INT_DSP_MMU);
-       preempt_disable();
-       if (dsp_runstat > RUNSTAT_RESET) {
-               __dsp_reset();
-               if (dsp_runstat == RUNSTAT_RUN)
-                       clk_unuse(api_ck_handle);
-               dsp_runstat = RUNSTAT_RESET;
-       }
-       preempt_enable();
-       enable_irq(INT_DSP_MMU);
-}
-
 static short varread_val[5]; /* maximum */
 
 static int dsp_regread(unsigned short cmd_l, unsigned short adr,
@@ -102,7 +75,7 @@ static int dsp_regread(unsigned short cmd_l, unsigned short adr,
 
        ioctl_wait_cmd = MBCMD(REGRW);
        mbcmd_set(mb, MBCMD(REGRW), cmd_l, adr);
-       dsp_mbsend_and_wait(&mb, &ioctl_wait_q);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
 
        if (ioctl_wait_cmd != 0) {
                printk(KERN_ERR "omapdsp: register read error!\n");
@@ -128,7 +101,7 @@ static int dsp_regwrite(unsigned short cmd_l, unsigned short adr,
        };
 
        mbcmd_set(mb, MBCMD(REGRW), cmd_l, adr);
-       dsp_mbsend_exarg(&mb, &arg);
+       dsp_mbcmd_send_exarg(&mb, &arg);
        return 0;
 }
 
@@ -142,7 +115,7 @@ static int dsp_getvar(unsigned char varid, unsigned short *val, int sz)
 
        ioctl_wait_cmd = MBCMD(GETVAR);
        mbcmd_set(mb, MBCMD(GETVAR), varid, 0);
-       dsp_mbsend_and_wait(&mb, &ioctl_wait_q);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
 
        if (ioctl_wait_cmd != 0) {
                printk(KERN_ERR "omapdsp: variable read error!\n");
@@ -159,10 +132,7 @@ up_out:
 
 static int dsp_setvar(unsigned char varid, unsigned short val)
 {
-       struct mbcmd mb;
-
-       mbcmd_set(mb, MBCMD(SETVAR), varid, val);
-       dsp_mbsend(&mb);
+       dsp_mbsend(MBCMD(SETVAR), varid, val);
        return 0;
 }
 
@@ -182,6 +152,15 @@ static int dspcfg(void)
                goto up_out;
        }
 
+       /* for safety */
+       dsp_mem_usecount_clear();
+
+       /*
+        * DSPCFG command and dsp_mem_start() must be called
+        * while internal mem is on.
+        */
+       dsp_mem_enable((void *)dspmem_base);
+
        dsp_mb_start();
        dsp_twch_start();
        dsp_mem_start();
@@ -190,7 +169,7 @@ static int dspcfg(void)
        mbx_revision = -1;
        ioctl_wait_cmd = MBCMD(DSPCFG);
        mbcmd_set(mb, MBCMD(DSPCFG), OMAP_DSP_MBCMD_DSPCFG_REQ, 0);
-       dsp_mbsend_and_wait(&mb, &ioctl_wait_q);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
 
        if (ioctl_wait_cmd != 0) {
                printk(KERN_ERR "omapdsp: configuration error!\n");
@@ -199,16 +178,30 @@ static int dspcfg(void)
                goto up_out;
        }
 
+#ifdef 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);
+       }
+#endif
+
        if ((ret = dsp_task_config_all(n_stask)) < 0) {
                up(&ioctl_sem);
                dspuncfg();
+               dsp_mem_disable((void *)dspmem_base);
                return -EINVAL;
        }
 
        cfgstat = CFG_READY;
 
        /* send parameter */
-       if ((ret = dsp_setvar(OMAP_DSP_MBCMD_VARID_ICRMASK, dsp_icrmask)) < 0)
+       if ((ret = dsp_setvar(OMAP_DSP_MBCMD_VARID_ICRMASK,
+                             dsp_cpustat_get_icrmask())) < 0)
                goto up_out;
 
        /* create runtime sysfs entries */
@@ -216,6 +209,7 @@ static int dspcfg(void)
        device_create_file(&dsp_device.dev, &dev_attr_ipbuf);
 
 up_out:
+       dsp_mem_disable((void *)dspmem_base);
        up(&ioctl_sem);
        return ret;
 }
@@ -229,7 +223,7 @@ int dspuncfg(void)
 
        if (down_interruptible(&ioctl_sem))
                return -ERESTARTSYS;
-       
+
        /* FIXME: lock task module */
 
        /* remove runtime sysfs entries */
@@ -238,7 +232,9 @@ int dspuncfg(void)
 
        dsp_mb_stop();
        dsp_twch_stop();
+       dsp_mem_stop();
        dsp_err_stop();
+       dsp_dbg_stop();
        dsp_task_unconfig_all();
        ipbuf_stop();
        cfgstat = CFG_ERR;
@@ -252,33 +248,76 @@ int dsp_is_ready(void)
        return (cfgstat == CFG_READY) ? 1 : 0;
 }
 
-void dsp_runlevel(unsigned char level)
+/*
+ * polls all tasks
+ */
+int dsp_poll(void)
 {
        struct mbcmd mb;
+       int ret = 0;
 
-       mbcmd_set(mb, MBCMD(RUNLEVEL), level, 0);
+       if (down_interruptible(&ioctl_sem))
+               return -ERESTARTSYS;
+
+       ioctl_wait_cmd = MBCMD(POLL);
+       mbcmd_set(mb, MBCMD(POLL), 0, 0);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
+
+       if (ioctl_wait_cmd != 0) {
+               printk(KERN_ERR "omapdsp: poll error!\n");
+               ret = -EINVAL;
+               goto up_out;
+       }
+
+up_out:
+       up(&ioctl_sem);
+       return ret;
+}
+
+void dsp_runlevel(unsigned char level)
+{
        if (level == OMAP_DSP_MBCMD_RUNLEVEL_RECOVERY)
-               dsp_mbsend_recovery(&mb);
+               dsp_mbsend_recovery(MBCMD(RUNLEVEL), level, 0);
        else
-               dsp_mbsend(&mb);
+               dsp_mbsend(MBCMD(RUNLEVEL), level, 0);
 }
 
+static enum cfgstat cfgstat_save_suspend;
+
+/*
+ * 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;
 
+       if (cfgstat == CFG_SUSPEND) {
+               printk(KERN_ERR "omapdsp: DSP is already in suspend state.\n");
+               return -EINVAL;
+       }
+
        if (down_interruptible(&ioctl_sem))
                return -ERESTARTSYS;
 
+       cfgstat_save_suspend = cfgstat;
        if (!dsp_is_ready()) {
-               ret = -EINVAL;
-               goto up_out;
+               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_mbsend_and_wait(&mb, &ioctl_wait_q);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
 
        if (ioctl_wait_cmd != 0) {
                printk(KERN_ERR "omapdsp: DSP suspend error!\n");
@@ -287,6 +326,7 @@ int dsp_suspend(void)
        }
 
        udelay(100);
+transition:
        cfgstat = CFG_SUSPEND;
 up_out:
        up(&ioctl_sem);
@@ -295,29 +335,24 @@ up_out:
 
 int dsp_resume(void)
 {
-       if (cfgstat != CFG_SUSPEND)
-               return 0;
+       if (cfgstat != CFG_SUSPEND) {
+               printk(KERN_ERR "omapdsp: DSP is not in suspend state.\n");
+               return -EINVAL;
+       }
 
-       cfgstat = CFG_READY;
+       cfgstat = cfgstat_save_suspend;
        return 0;
 }
 
 static void dsp_fbctl_enable(void)
 {
-#ifdef CONFIG_FB_OMAP_EXTERNAL_LCDC
-       struct mbcmd mb;
-
-       mbcmd_set(mb, MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_FBCTL,
-                 OMAP_DSP_MBCMD_FBCTL_ENABLE);
-       dsp_mbsend(&mb);
-#endif
+       dsp_mbsend(MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_FBCTL,
+                  OMAP_DSP_MBCMD_FBCTL_ENABLE);
 }
 
 static int dsp_fbctl_disable(void)
 {
        int ret = 0;
-
-#ifdef CONFIG_FB_OMAP_EXTERNAL_LCDC
        struct mbcmd mb;
 
        if (down_interruptible(&ioctl_sem))
@@ -326,13 +361,12 @@ static int dsp_fbctl_disable(void)
        ioctl_wait_cmd = MBCMD(KFUNC);
        mbcmd_set(mb, MBCMD(KFUNC), OMAP_DSP_MBCMD_KFUNC_FBCTL,
                  OMAP_DSP_MBCMD_FBCTL_DISABLE);
-       dsp_mbsend_and_wait(&mb, &ioctl_wait_q);
+       dsp_mbcmd_send_and_wait(&mb, &ioctl_wait_q);
        if (ioctl_wait_cmd != 0) {
                printk(KERN_ERR "omapdsp: fb disable error!\n");
                ret = -EINVAL;
        }
        up(&ioctl_sem);
-#endif
 
        return ret;
 }
@@ -350,19 +384,23 @@ 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:
-               dsp_run();
+               dsp_cpustat_request(CPUSTAT_RUN);
                break;
 
        case OMAP_DSP_IOCTL_RESET:
-               dsp_reset();
+               dsp_cpustat_request(CPUSTAT_RESET);
                break;
 
        case OMAP_DSP_IOCTL_SETRSTVECT:
                ret = dsp_set_rstvect((unsigned long)arg);
                break;
 
-       case OMAP_DSP_IOCTL_IDLE:
-               dsp_idle();
+       case OMAP_DSP_IOCTL_CPU_IDLE:
+               dsp_cpustat_request(CPUSTAT_CPU_IDLE);
+               break;
+
+       case OMAP_DSP_IOCTL_GBL_IDLE:
+               dsp_cpustat_request(CPUSTAT_GBL_IDLE);
                break;
 
        case OMAP_DSP_IOCTL_MPUI_WORDSWAP_ON:
@@ -389,7 +427,7 @@ static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
                                return -EFAULT;
                        mb.cmd  = u_cmd.cmd;
                        mb.data = u_cmd.data;
-                       ret = dsp_mbsend((struct mbcmd *)&mb);
+                       ret = dsp_mbcmd_send((struct mbcmd *)&mb);
                        break;
                }
 
@@ -425,20 +463,27 @@ static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
                ret = dsp_task_count();
                break;
 
+       case OMAP_DSP_IOCTL_POLL:
+               ret = dsp_poll();
+               break;
+
        case OMAP_DSP_IOCTL_FBDIS:
                ret = dsp_fbctl_disable();
                break;
 
+       /*
+        * FIXME: cpu status control for suspend - resume
+        */
        case OMAP_DSP_IOCTL_SUSPEND:
                if ((ret = dsp_suspend()) < 0)
                        break;
-               dsp_reset();
+               dsp_cpustat_request(CPUSTAT_RESET);
                break;
 
        case OMAP_DSP_IOCTL_RESUME:
                if ((ret = dsp_resume()) < 0)
                        break;
-               dsp_run();
+               dsp_cpustat_request(CPUSTAT_RUN);
                break;
 
        case OMAP_DSP_IOCTL_REGMEMR:
@@ -547,7 +592,7 @@ void mbx1_dspcfg(struct mbcmd *mb)
 {
        unsigned char last   = mb->cmd_l & 0x80;
        unsigned char cfgcmd = mb->cmd_l & 0x7f;
-       static unsigned long tmp_ipbuf_sys_da;
+       static unsigned long tmp_ipb_adr;
 
        /* mailbox protocol check */
        if (cfgcmd == OMAP_DSP_MBCMD_DSPCFG_PROTREV) {
@@ -563,7 +608,8 @@ void mbx1_dspcfg(struct mbcmd *mb)
                if (mbx_revision == OMAP_DSP_MBPROT_REVISION)
                        return;
 #ifdef OLD_BINARY_SUPPORT
-               else if (mbx_revision == MBREV_3_0) {
+               else if ((mbx_revision == MBREV_3_0) ||
+                        (mbx_revision == MBREV_3_2)) {
                        printk(KERN_WARNING
                               "mbx: ***** old DSP binary *****\n"
                               "  Please update your DSP application.\n");
@@ -576,7 +622,7 @@ void mbx1_dspcfg(struct mbcmd *mb)
                               "  expected=0x%04x, received=0x%04x\n",
                               OMAP_DSP_MBPROT_REVISION, mb->data);
                        mbx_revision = -1;
-                       goto abort;
+                       goto abort1;
                }
        }
 
@@ -601,15 +647,15 @@ void mbx1_dspcfg(struct mbcmd *mb)
 
        switch (cfgcmd) {
        case OMAP_DSP_MBCMD_DSPCFG_SYSADRH:
-               tmp_ipbuf_sys_da = (unsigned long)mb->data << 16;
+               tmp_ipb_adr = (unsigned long)mb->data << 16;
                break;
 
        case OMAP_DSP_MBCMD_DSPCFG_SYSADRL:
-               tmp_ipbuf_sys_da |= mb->data;
+               tmp_ipb_adr |= mb->data;
                break;
 
        case OMAP_DSP_MBCMD_DSPCFG_ABORT:
-               goto abort;
+               goto abort1;
 
        default:
                printk(KERN_ERR
@@ -619,24 +665,23 @@ void mbx1_dspcfg(struct mbcmd *mb)
        }
 
        if (last) {
-               unsigned long badr;
+               void *badr;
                unsigned short bln;
                unsigned short bsz;
                volatile unsigned short *buf;
-               void *sync_seq;
+               void *ipb_sys_da, *ipb_sys_ad;
+               void *mbseq;
+               short *dbg_buf;
+               unsigned short dbg_buf_sz, dbg_line_sz;
+               struct mem_sync_struct mem_sync, *mem_syncp;
 
-               /* system IPBUF initialization */
-               if (tmp_ipbuf_sys_da & 0x1) {
-                       printk(KERN_ERR
-                              "mbx: system ipbuf address (0x%lx) "
-                              "is odd number!\n", tmp_ipbuf_sys_da);
-                       goto abort;
-               }
-               ipbuf_sys_da = dspword_to_virt(tmp_ipbuf_sys_da);
+               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) {
                        printk(KERN_ERR "mbx: DSPCFG - IPBUF sync failed!\n");
-                       return;
+                       goto abort1;
                }
                /*
                 * read configuration data on system IPBUF
@@ -646,47 +691,95 @@ void mbx1_dspcfg(struct mbcmd *mb)
                if (mbx_revision == OMAP_DSP_MBPROT_REVISION) {
 #endif
                        buf = ipbuf_sys_da->d;
-                       n_stask = buf[0];
-                       bln     = buf[1];
-                       bsz     = buf[2];
-                       badr    = MKLONG(buf[3], buf[4]);
-                       /*ipbuf_sys_da = dspword_to_virt(MKLONG(buf[5], buf[6])); */
-                       ipbuf_sys_ad = dspword_to_virt(MKLONG(buf[7], buf[8]));
-                       sync_seq = dspword_to_virt(MKLONG(buf[9], buf[10]));
+                       n_stask        = buf[0];
+                       bln            = buf[1];
+                       bsz            = buf[2];
+                       badr           = MKVIRT(buf[3], buf[4]);
+                       /* ipb_sys_da     = MKVIRT(buf[5], buf[6]); */
+                       ipb_sys_ad     = MKVIRT(buf[7], buf[8]);
+                       mbseq          = MKVIRT(buf[9], buf[10]);
+                       dbg_buf        = MKVIRT(buf[11], buf[12]);
+                       dbg_buf_sz     = buf[13];
+                       dbg_line_sz    = buf[14];
+                       mem_sync.DARAM = MKVIRT(buf[15], buf[16]);
+                       mem_sync.SARAM = MKVIRT(buf[17], buf[18]);
+                       mem_sync.SDRAM = MKVIRT(buf[19], buf[20]);
+                       mem_syncp = &mem_sync;
 #ifdef OLD_BINARY_SUPPORT
+               } else if (mbx_revision == MBREV_3_2) {
+                       buf = ipbuf_sys_da->d;
+                       n_stask     = buf[0];
+                       bln         = buf[1];
+                       bsz         = buf[2];
+                       badr        = MKVIRT(buf[3], buf[4]);
+                       /* ipb_sys_da  = MKVIRT(buf[5], buf[6]); */
+                       ipb_sys_ad  = MKVIRT(buf[7], buf[8]);
+                       mbseq       = MKVIRT(buf[9], buf[10]);
+                       dbg_buf     = NULL;
+                       dbg_buf_sz  = 0;
+                       dbg_line_sz = 0;
+                       mem_syncp   = NULL;
                } else if (mbx_revision == MBREV_3_0) {
                        buf = ipbuf_sys_da->d;
-                       n_stask = buf[0];
-                       bln     = buf[1];
-                       bsz     = buf[2];
-                       badr    = MKLONG(buf[3], buf[4]);
-                       /* bkeep   = buf[5]; */
-                       /*ipbuf_sys_da = dspword_to_virt(MKLONG(buf[6], buf[67)); */
-                       ipbuf_sys_ad = dspword_to_virt(MKLONG(buf[8], buf[9]));
-                       sync_seq = dspword_to_virt(MKLONG(buf[10], buf[11]));
+                       n_stask     = buf[0];
+                       bln         = buf[1];
+                       bsz         = buf[2];
+                       badr        = MKVIRT(buf[3], buf[4]);
+                       /* bkeep       = buf[5]; */
+                       /* ipb_sys_da  = MKVIRT(buf[6], buf[7]); */
+                       ipb_sys_ad  = MKVIRT(buf[8], buf[9]);
+                       mbseq       = MKVIRT(buf[10], buf[11]);
+                       dbg_buf     = NULL;
+                       dbg_buf_sz  = 0;
+                       dbg_line_sz = 0;
+                       mem_syncp   = NULL;
                } else /* should not occur */
-                       goto abort;
-#endif
-
-               /* ipbuf_config() should be done in interrupt routine. */
-               if (ipbuf_config(bln, bsz, badr) < 0)
-                       goto abort;
+                       goto abort1;
+#endif /* OLD_BINARY_SUPPORT */
 
-               ipbuf_sys_da->s = OMAP_DSP_TID_FREE;
+               release_ipbuf_pvt(ipbuf_sys_da);
 
-               /* mb_config() should be done in interrupt routine. */
-               dsp_mb_config(sync_seq);
+               /*
+                * following configurations need to be done before
+                * waking up the dspcfg initiator process.
+                */
+               if (ipbuf_sys_config(ipb_sys_ad, DIR_A2D) < 0)
+                       goto abort1;
+               if (ipbuf_config(bln, bsz, badr) < 0)
+                       goto abort1;
+               if (dsp_mb_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);
        }
        return;
 
-abort:
+abort2:
+       ipbuf_stop();
+abort1:
        wake_up_interruptible(&ioctl_wait_q);
        return;
 }
 
+void mbx1_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);
+}
+
 void mbx1_regrw(struct mbcmd *mb)
 {
        if (!waitqueue_active(&ioctl_wait_q) ||
@@ -743,7 +836,7 @@ void mbx1_getvar(struct mbcmd *mb)
                        for (i = 0; i < 5; i++) {
                                varread_val[i] = buf[i];
                        }
-                       ipbuf_sys_da->s = OMAP_DSP_TID_FREE;
+                       release_ipbuf_pvt(ipbuf_sys_da);
                        break;
                }
        }
@@ -765,51 +858,54 @@ 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
         */
 
        /*
         * print all supporting I/F VERSIONs, like followings.
         *
-        * len += sprintf(buf, "3.1\n");
         * len += sprintf(buf, "3.2\n");
+        * len += sprintf(buf, "3.3\n");
         */
        len += sprintf(buf + len, "3.2\n");
+       len += sprintf(buf + len, "3.3\n");
 
        return len;
 }
 
 static struct device_attribute dev_attr_ifver = __ATTR_RO(ifver);
 
-static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
+static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
                            char *buf)
 {
-#if 0
-       if (dsp_is_ready()) {
-               int ret;
-               unsigned short val;
+       return sprintf(buf, "%s\n", cpustat_name(dsp_cpustat_get_stat()));
+}
 
-               if ((ret = dsp_getvar(OMAP_DSP_MBCMD_VARID_ICRMASK, &val, 1)) < 0)
-                       return ret;
-               if (val != dsp_icrmask)
-                       printk(KERN_WARNING
-                              "omapdsp: icrmask value is inconsistent!\n");
-       }
-#endif
-       return sprintf(buf, "0x%04x\n", dsp_icrmask);
+static struct device_attribute dev_attr_cpustat = __ATTR_RO(cpustat);
+
+static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       return sprintf(buf, "0x%04x\n", dsp_cpustat_get_icrmask());
 }
 
 static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
                             const char *buf, size_t count)
 {
+       unsigned short mask;
        int ret;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       dsp_icrmask = simple_strtol(buf, NULL, 16);
+       mask = simple_strtol(buf, NULL, 16);
+       dsp_cpustat_set_icrmask(mask);
 
        if (dsp_is_ready()) {
-               ret = dsp_setvar(OMAP_DSP_MBCMD_VARID_ICRMASK, dsp_icrmask);
+               ret = dsp_setvar(OMAP_DSP_MBCMD_VARID_ICRMASK, mask);
                if (ret < 0)
                        return ret;
        }
@@ -848,7 +944,6 @@ static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
  * static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
  */
 
-#ifdef CONFIG_FB_OMAP_EXTERNAL_LCDC
 void mbx1_fbctl_disable(void)
 {
        if (!waitqueue_active(&ioctl_wait_q) ||
@@ -861,7 +956,6 @@ void mbx1_fbctl_disable(void)
        ioctl_wait_cmd = 0;
        wake_up_interruptible(&ioctl_wait_q);
 }
-#endif
 
 #ifdef CONFIG_PROC_FS
 /* for backward compatibility */
@@ -902,6 +996,7 @@ struct file_operations dsp_ctl_fops = {
 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();
@@ -911,6 +1006,7 @@ void __init dsp_ctl_init(void)
 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();
index 88df7cbba4b042879556f80f7bfdd17754dbdf9e..6eb85920b6ec6ff8ac86d7d804378b2ac57ef258 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2005/02/10:  DSP Gateway version 3.2
+ * 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/devfs_fs_kernel.h>
 #include <linux/init.h>
 #include <asm/arch/dsp.h>
 #include "hardware_dsp.h"
@@ -75,13 +74,12 @@ static struct file_operations dsp_ctl_core_fops = {
 static const struct dev_list {
        unsigned int    minor;
        char            *devname;
-       char            *devfs_name;
        umode_t         mode;
 } dev_list[] = {
-       {CTL_MINOR,  "dspctl",  "dspctl/ctl",  S_IRUSR | S_IWUSR},
-       {MEM_MINOR,  "dspmem",  "dspctl/mem",  S_IRUSR | S_IWUSR | S_IRGRP},
-       {TWCH_MINOR, "dsptwch", "dspctl/twch", S_IRUSR | S_IWUSR | S_IRGRP},
-       {ERR_MINOR,  "dsperr",  "dspctl/err",  S_IRUSR | S_IRGRP},
+       {CTL_MINOR,  "dspctl",  S_IRUSR | S_IWUSR},
+       {MEM_MINOR,  "dspmem",  S_IRUSR | S_IWUSR | S_IRGRP},
+       {TWCH_MINOR, "dsptwch", S_IRUSR | S_IWUSR | S_IRGRP},
+       {ERR_MINOR,  "dsperr",  S_IRUSR | S_IRGRP},
 };
 
 int __init dsp_ctl_core_init(void)
@@ -99,15 +97,11 @@ int __init dsp_ctl_core_init(void)
        }
 
        dsp_ctl_class = class_create(THIS_MODULE, "dspctl");
-       devfs_mk_dir("dspctl");
        for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
                class_device_create(dsp_ctl_class,
                                    MKDEV(OMAP_DSP_CTL_MAJOR,
                                          dev_list[i].minor),
                                    NULL, dev_list[i].devname);
-               devfs_mk_cdev(MKDEV(OMAP_DSP_CTL_MAJOR, dev_list[i].minor),
-                             S_IFCHR | dev_list[i].mode,
-                             dev_list[i].devfs_name);
        }
 
        return 0;
@@ -118,12 +112,10 @@ void dsp_ctl_core_exit(void)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
-               devfs_remove(dev_list[i].devfs_name);
                class_device_destroy(dsp_ctl_class,
                                     MKDEV(OMAP_DSP_CTL_MAJOR,
                                           dev_list[i].minor));
        }
-       devfs_remove("dspctl");
        class_destroy(dsp_ctl_class);
 
        unregister_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl");
index 972e54c52cb775cd72cf79fb8a2d410c69d80303..afae8ac6072454717154ac5a6f1022e22eab9450 100644 (file)
@@ -22,7 +22,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- * 2005/02/17:  DSP Gateway version 3.2
+ * 2005/06/09:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
@@ -42,8 +42,8 @@
 #include <asm/hardware/clock.h>
 #include <asm/arch/tc.h>
 #include <asm/arch/dsp.h>
+#include <asm/arch/dsp_common.h>
 #include "uaccess_dsp.h"
-#include "ipbuf.h"
 #include "dsp.h"
 
 #define SZ_1MB 0x100000
@@ -99,9 +99,12 @@ enum exmap_type {
 struct exmap_tbl {
        unsigned int valid:1;
        unsigned int cntnu:1;   /* grouping */
+       int usecount;           /* reference count by mmap */
        enum exmap_type type;
-       void *buf;
-       void *vadr;
+       void *buf;              /* virtual address of the buffer,
+                                * i.e. 0xc0000000 - */
+       void *vadr;             /* DSP shadow space,
+                                * i.e. 0xe0000000 - 0xe0ffffff */
        unsigned int order;
 };
 #define DSPMMU_TLB_LINES       32
@@ -112,6 +115,7 @@ static int dsp_exunmap(unsigned long dspadr);
 
 static void *dspvect_page;
 static unsigned long dsp_fault_adr;
+static struct mem_sync_struct mem_sync;
 
 static __inline__ unsigned long lineup_offset(unsigned long adr,
                                              unsigned long ref,
@@ -125,6 +129,47 @@ static __inline__ unsigned long lineup_offset(unsigned long adr,
        return newadr;
 }
 
+void dsp_mem_sync_inc(void)
+{
+       /*
+        * FIXME: dsp_mem_enable()!!!
+        */
+       if (mem_sync.DARAM)
+               mem_sync.DARAM->ad_arm++;
+       if (mem_sync.SARAM)
+               mem_sync.SARAM->ad_arm++;
+       if (mem_sync.SDRAM)
+               mem_sync.SDRAM->ad_arm++;
+}
+
+/*
+ * dsp_mem_sync_config() is called from mbx1 workqueue
+ */
+int dsp_mem_sync_config(struct mem_sync_struct *sync)
+{
+       size_t sync_seq_sz = sizeof(struct sync_seq);
+
+#ifdef OLD_BINARY_SUPPORT
+       if (sync == NULL) {
+               memset(&mem_sync, 0, sizeof(struct mem_sync_struct));
+               return 0;
+       }
+#endif
+       if ((dsp_mem_type(sync->DARAM, sync_seq_sz) != MEM_TYPE_DARAM) ||
+           (dsp_mem_type(sync->SARAM, sync_seq_sz) != MEM_TYPE_SARAM) ||
+           (dsp_mem_type(sync->SDRAM, sync_seq_sz) != MEM_TYPE_EXTERN)) {
+               printk(KERN_ERR
+                      "omapdsp: mem_sync address validation failure!\n"
+                      "  mem_sync.DARAM = 0x%p,\n"
+                      "  mem_sync.SARAM = 0x%p,\n"
+                      "  mem_sync.SDRAM = 0x%p,\n",
+                      sync->DARAM, sync->SARAM, sync->SDRAM);
+               return -1;
+       }
+       memcpy(&mem_sync, sync, sizeof(struct mem_sync_struct));
+       return 0;
+}
+
 /*
  * kmem_reserve(), kmem_release():
  * reserve or release kernel memory for exmap().
@@ -262,11 +307,21 @@ static unsigned long dsp_mem_get_dma_pages(unsigned int order)
        return __get_dma_pages(GFP_KERNEL, order);
 }
 
-static void dsp_mem_free_pages(unsigned int buf, unsigned int order)
+static void dsp_mem_free_pages(unsigned long buf, unsigned int order)
 {
        struct kmem_pool *pool;
+       struct page *page, *ps, *pe;
        int i;
 
+       ps = virt_to_page(buf);
+       pe = virt_to_page(buf + (1 << (PAGE_SHIFT + order)));
+       for (page = ps; page < pe; page++) {
+               ClearPageReserved(page);
+       }
+
+       /*
+        * return buffer to kmem_pool or paging system
+        */
        switch (order) {
                case ORDER_1MB:
                        pool = &kmem_pool_1M;
@@ -358,6 +413,7 @@ static void exmap_clear_armmmu(unsigned long virt, unsigned long size)
 
 static int exmap_valid(void *vadr, size_t len)
 {
+       /* exmap_sem should be held before calling this function */
        int i;
 
 start:
@@ -389,6 +445,107 @@ start:
        return 0;
 }
 
+enum dsp_mem_type_e dsp_mem_type(void *vadr, size_t len)
+{
+       void *ds = (void *)daram_base;
+       void *de = (void *)daram_base + daram_size;
+       void *ss = (void *)saram_base;
+       void *se = (void *)saram_base + saram_size;
+       int ret;
+
+       if ((vadr >= ds) && (vadr < de)) {
+               if (vadr + len > de)
+                       return MEM_TYPE_CROSSING;
+               else
+                       return MEM_TYPE_DARAM;
+       } else if ((vadr >= ss) && (vadr < se)) {
+               if (vadr + len > se)
+                       return MEM_TYPE_CROSSING;
+               else
+                       return MEM_TYPE_SARAM;
+       } else {
+               down_read(&exmap_sem);
+               if (exmap_valid(vadr, len))
+                       ret = MEM_TYPE_EXTERN;
+               else
+                       ret = MEM_TYPE_NONE;
+               up_read(&exmap_sem);
+               return ret;
+       }
+}
+
+int dsp_address_validate(void *p, size_t len, char *fmt, ...)
+{
+       if (dsp_mem_type(p, len) <= 0) {
+               if (fmt != NULL) {
+                       char s[64];
+                       va_list args;
+
+                       va_start(args, fmt);
+                       vsprintf(s, fmt, args);
+                       va_end(args);
+                       printk(KERN_ERR
+                              "omapdsp: %s address(0x%p) and size(0x%x) is "
+                              "not valid!\n"
+                              "         (crossing different type of memories, or \n"
+                              "          external memory space where no "
+                              "actual memory is mapped)\n",
+                              s, p, len);
+               }
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * exmap_use(), unuse(): 
+ * when the mapped area is exported to user space with mmap,
+ * the usecount is incremented.
+ * while the usecount > 0, that area can't be released.
+ */
+void exmap_use(void *vadr, size_t len)
+{
+       int i;
+
+       down_write(&exmap_sem);
+       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+               void *mapadr;
+               unsigned long mapsize;
+               struct exmap_tbl *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)) {
+                       ent->usecount++;
+               }
+       }
+       up_write(&exmap_sem);
+}
+
+void exmap_unuse(void *vadr, size_t len)
+{
+       int i;
+
+       down_write(&exmap_sem);
+       for (i = 0; i < DSPMMU_TLB_LINES; i++) {
+               void *mapadr;
+               unsigned long mapsize;
+               struct exmap_tbl *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)) {
+                       ent->usecount--;
+               }
+       }
+       up_write(&exmap_sem);
+}
+
 /*
  * dsp_virt_to_phys()
  * returns physical address, and sets len to valid length
@@ -744,12 +901,13 @@ found_free:
                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->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;
 
        if ((_size -= unit) == 0) {     /* normal completion */
                up_write(&exmap_sem);
@@ -812,6 +970,14 @@ static int dsp_exunmap(unsigned long dspadr)
        return -EINVAL;
 
 found_map:
+       if (ent->usecount > 0) {
+               printk(KERN_ERR
+                      "omapdsp: exmap reference count is not 0.\n"
+                      "   idx=%d, vadr=%p, order=%d, usecount=%d\n",
+                      idx, ent->vadr, ent->order, ent->usecount);
+               up_write(&exmap_sem);
+               return -EINVAL;
+       }
        /* clearing DSP TLB entry */
        dsp_mmu_clear_tlb(dspadr);
 
@@ -871,11 +1037,6 @@ static void exmap_flush(void)
        /* flush TLB */
        flush_tlb_kernel_range(dspmem_base + dspmem_size,
                               dspmem_base + DSPSPACE_SIZE);
-       /*
-        * we should clear processes' mm as well,
-        * because processes might had accessed to those spaces
-        * with old table in the past.
-        */
        up_write(&exmap_sem);
 }
 
@@ -998,11 +1159,12 @@ static void dsp_mmu_init(void)
        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].order = 0;
-       exmap_tbl[0].valid = 1;
-       exmap_tbl[0].cntnu = 0;
+       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);
@@ -1020,88 +1182,66 @@ static void dsp_mmu_shutdown(void)
 }
 
 /*
- * dsp_mem_enable() / disable():
+ * intmem_enable() / disable():
  * if the address is in DSP internal memories,
  * we send PM mailbox commands so that DSP DMA domain won't go in idle
  * when ARM is accessing to those memories.
- * if the address is in external memory, acquire exmap_sem.
- *
- * __dsp_mem_enable() / disable() should be called only from __dsp_mbsend().
  */
-static int dsp_mem_en_count;
-
-int dsp_mem_enable(void *adr)
+static int intmem_enable(void)
 {
-       struct mbcmd mb;
-       int ret;
+       int ret = 0;
 
-       if (is_dsp_internal_mem(adr)) {
-               if (dsp_is_ready() && (!dsp_mem_en_count) &&
-                   (dsp_icrmask & DSPREG_ICR_DMA_IDLE_DOMAIN)) {
-                       mbcmd_set(mb, MBCMD(PM), OMAP_DSP_MBCMD_PM_ENABLE,
-                                 DSPREG_ICR_DMA_IDLE_DOMAIN);
-                       if ((ret = dsp_mbsend(&mb)) < 0)
-                               return ret;
-                       dsp_mem_en_count++;
-               }
-       } else
-               down_read(&exmap_sem);
-       return 0;
-}
+       if (dsp_is_ready())
+               ret = dsp_mbsend(MBCMD(PM), OMAP_DSP_MBCMD_PM_ENABLE,
+                                DSPREG_ICR_DMA_IDLE_DOMAIN);
 
-int dsp_mem_disable(void *adr)
-{
-       struct mbcmd mb;
-       int ret;
+       return ret;
+}
 
-       if (is_dsp_internal_mem(adr)) {
-               if (dsp_is_ready() && dsp_mem_en_count) {
-                       mbcmd_set(mb, MBCMD(PM), OMAP_DSP_MBCMD_PM_DISABLE,
-                                 DSPREG_ICR_DMA_IDLE_DOMAIN);
-                       if ((ret = dsp_mbsend(&mb)) < 0)
-                               return ret;
-                       dsp_mem_en_count--;
-               }
-       } else
-               up_read(&exmap_sem);
-       return 0;
+static void intmem_disable(void) {
+       if (dsp_is_ready())
+               dsp_mbsend(MBCMD(PM), OMAP_DSP_MBCMD_PM_DISABLE,
+                          DSPREG_ICR_DMA_IDLE_DOMAIN);
 }
 
-int __dsp_mem_enable(void *adr)
+/*
+ * dsp_mem_enable() / disable()
+ */
+int intmem_usecount;
+
+int dsp_mem_enable(void *adr)
 {
-       struct mbcmd mb;
-       int ret;
+       int ret = 0;
 
        if (is_dsp_internal_mem(adr)) {
-               if (dsp_is_ready() && (!dsp_mem_en_count) &&
-                   (dsp_icrmask & DSPREG_ICR_DMA_IDLE_DOMAIN)) {
-                       mbcmd_set(mb, MBCMD(PM), OMAP_DSP_MBCMD_PM_ENABLE,
-                                 DSPREG_ICR_DMA_IDLE_DOMAIN);
-                       if ((ret = __mbsend(&mb)) < 0)
-                               return ret;
-                       dsp_mem_en_count++;
-               }
+               if (intmem_usecount++ == 0)
+                       ret = omap_dsp_request_mem();
        } else
                down_read(&exmap_sem);
-       return 0;
+
+       return ret;
 }
 
-int __dsp_mem_disable(void *adr)
+void dsp_mem_disable(void *adr)
 {
-       struct mbcmd mb;
-       int ret;
-
        if (is_dsp_internal_mem(adr)) {
-               if (dsp_is_ready() && dsp_mem_en_count) {
-                       mbcmd_set(mb, MBCMD(PM), OMAP_DSP_MBCMD_PM_DISABLE,
-                                 DSPREG_ICR_DMA_IDLE_DOMAIN);
-                       if ((ret = __mbsend(&mb)) < 0)
-                               return ret;
-                       dsp_mem_en_count--;
-               }
+               if (--intmem_usecount == 0)
+                       omap_dsp_release_mem();
        } else
                up_read(&exmap_sem);
-       return 0;
+}
+
+/* for safety */
+void dsp_mem_usecount_clear(void)
+{
+       if (intmem_usecount != 0) {
+               printk(KERN_WARNING
+                      "omapdsp: unbalanced memory request/release detected.\n"
+                      "         intmem_usecount is not zero at where "
+                      "it should be! ... fixed to be zero.\n");
+               intmem_usecount = 0;
+               omap_dsp_release_mem();
+       }
 }
 
 /*
@@ -1144,10 +1284,10 @@ static ssize_t intmem_read(struct file *file, char *buf, size_t count,
                read = size - p;
        if (copy_to_user(buf, vadr, read)) {
                read = -EFAULT;
-               goto finish;
+               goto out;
        }
        *ppos += read;
-finish:
+out:
        clk_unuse(api_ck_handle);
        return read;
 }
@@ -1157,39 +1297,37 @@ static ssize_t exmem_read(struct file *file, char *buf, size_t count,
 {
        unsigned long p = *ppos;
        void *vadr = dspbyte_to_virt(p);
-       ssize_t ret;
 
-       down_read(&exmap_sem);
        if (!exmap_valid(vadr, count)) {
                printk(KERN_ERR
                       "omapdsp: DSP address %08lx / size %08x "
                       "is not valid!\n", p, count);
-               ret = -EFAULT;
-               goto up_out;
+               return -EFAULT;
        }
        if (count > DSPSPACE_SIZE - p)
                count = DSPSPACE_SIZE - p;
-       if (copy_to_user(buf, vadr, count)) {
-               ret = -EFAULT;
-               goto up_out;
-       }
+       if (copy_to_user(buf, vadr, count))
+               return -EFAULT;
        *ppos += count;
 
-       up_read(&exmap_sem);
        return count;
-
-up_out:
-       up_read(&exmap_sem);
-       return ret;
 }
 
 static ssize_t dsp_mem_read(struct file *file, char *buf, size_t count,
                            loff_t *ppos)
 {
+       int ret;
+       void *vadr = dspbyte_to_virt(*(unsigned long *)ppos);
+
+       if (dsp_mem_enable(vadr) < 0)
+               return -EBUSY;
        if (is_dspbyte_internal_mem(*ppos))
-               return intmem_read(file, buf, count, ppos);
+               ret = intmem_read(file, buf, count, ppos);
        else
-               return exmem_read(file, buf, count, ppos);
+               ret = exmem_read(file, buf, count, ppos);
+       dsp_mem_disable(vadr);
+
+       return ret;
 }
 
 static ssize_t intmem_write(struct file *file, const char *buf, size_t count,
@@ -1208,10 +1346,10 @@ static ssize_t intmem_write(struct file *file, const char *buf, size_t count,
                written = size - p;
        if (copy_from_user(vadr, buf, written)) {
                written = -EFAULT;
-               goto finish;
+               goto out;
        }
        *ppos += written;
-finish:
+out:
        clk_unuse(api_ck_handle);
        return written;
 }
@@ -1221,39 +1359,37 @@ static ssize_t exmem_write(struct file *file, const char *buf, size_t count,
 {
        unsigned long p = *ppos;
        void *vadr = dspbyte_to_virt(p);
-       ssize_t ret;
 
-       down_read(&exmap_sem);
        if (!exmap_valid(vadr, count)) {
                printk(KERN_ERR
                       "omapdsp: DSP address %08lx / size %08x "
                       "is not valid!\n", p, count);
-               ret = -EFAULT;
-               goto up_out;
+               return -EFAULT;
        }
        if (count > DSPSPACE_SIZE - p)
                count = DSPSPACE_SIZE - p;
-       if (copy_from_user(vadr, buf, count)) {
-               ret = -EFAULT;
-               goto up_out;
-       }
+       if (copy_from_user(vadr, buf, count))
+               return -EFAULT;
        *ppos += count;
 
-       up_read(&exmap_sem);
        return count;
-
-up_out:
-       up_read(&exmap_sem);
-       return ret;
 }
 
 static ssize_t dsp_mem_write(struct file *file, const char *buf, size_t count,
                             loff_t *ppos)
 {
+       int ret;
+       void *vadr = dspbyte_to_virt(*(unsigned long *)ppos);
+
+       if (dsp_mem_enable(vadr) < 0)
+               return -EBUSY;
        if (is_dspbyte_internal_mem(*ppos))
-               return intmem_write(file, buf, count, ppos);
+               ret = intmem_write(file, buf, count, ppos);
        else
-               return exmem_write(file, buf, count, ppos);
+               ret = exmem_write(file, buf, count, ppos);
+       dsp_mem_disable(vadr);
+
+       return ret;
 }
 
 static int dsp_mem_ioctl(struct inode *inode, struct file *file,
@@ -1325,15 +1461,12 @@ static int dsp_mem_open(struct inode *inode, struct file *file)
 {
        if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
-       if (dsp_mem_enable((void *)dspmem_base) < 0)
-               return -EBUSY;
 
        return 0;
 }
 
 static int dsp_mem_release(struct inode *inode, struct file *file)
 {
-       dsp_mem_disable((void *)dspmem_base);
        return 0;
 }
 
@@ -1414,16 +1547,16 @@ static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
 
        down_read(&exmap_sem);
        len = sprintf(buf, "v: valid,  c: cntnu\n"
-                          "ety           vadr        buf od\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\n",
+               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->vadr, ent->buf, ent->order, ent->usecount);
        }
 
        up_read(&exmap_sem);
@@ -1432,6 +1565,19 @@ static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
 
 static struct device_attribute dev_attr_exmap = __ATTR_RO(exmap);
 
+static ssize_t kmem_pool_show(struct device *dev, char *buf)
+{
+       int count_1M, count_64K, total;
+
+       count_1M = kmem_pool_1M.count;
+       count_64K = kmem_pool_64K.count;
+       total = count_1M * SZ_1MB + count_64K * SZ_64KB;
+
+       return sprintf(buf, "0x%x %d %d\n", total, count_1M, count_64K);
+}
+
+static struct device_attribute dev_attr_kmem_pool = __ATTR_RO(kmem_pool);
+
 /*
  * DSP MMU interrupt handler
  */
@@ -1516,9 +1662,11 @@ irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                /* FIXME */
                dsp_err_mmu_set(dsp_fault_adr);
        } else {
+               disable_irq(INT_DSP_MMU);
+               __dsp_mmu_itack();
                printk(KERN_INFO "Resetting DSP...\n");
-               __dsp_reset();
-               clk_unuse(api_ck_handle);
+               dsp_cpustat_request(CPUSTAT_RESET);
+               enable_irq(INT_DSP_MMU);
                /*
                 * if we enable followings, semaphore lock should be avoided.
                 *
@@ -1547,7 +1695,13 @@ struct file_operations dsp_mem_fops = {
 
 void dsp_mem_start(void)
 {
-       dsp_mem_en_count = 0;
+       dsp_register_mem_cb(intmem_enable, intmem_disable);
+}
+
+void dsp_mem_stop(void)
+{
+       memset(&mem_sync, 0, sizeof(struct mem_sync_struct));
+       dsp_unregister_mem_cb();
 }
 
 int __init dsp_mem_init(void)
@@ -1570,6 +1724,7 @@ int __init dsp_mem_init(void)
 
        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);
 
        return 0;
 }
@@ -1581,19 +1736,18 @@ void dsp_mem_exit(void)
 
        if (dspvect_page != NULL) {
                unsigned long virt;
-               pmd_t *pmdp;
-               pte_t *ptep;
 
+               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;
 
-               virt = (unsigned long)dspbyte_to_virt(DSP_INIT_PAGE);
-               pmdp = pmd_offset(pgd_offset_k(virt), virt);
-               ptep = pte_offset_kernel(pmdp, 0);
-               pmd_clear(pmdp);
-               pte_free_kernel(ptep);
+               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);
 }
index ac6d8d84d9bd3a8e0131b8510dcb45db9f112d5e..dd7d7c4594bcbabdcf75e59c0191e706e2cdc6cb 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2004/11/22:  DSP Gateway version 3.2
+ * 2005/03/11:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
@@ -138,15 +138,22 @@ int dsp_err_wdt_isset(void)
 /*
  * functions called from mailbox1 interrupt routine
  */
-void mbx1_wdt(struct mbcmd *mb)
+static void mbx1_err_wdt(unsigned short data)
 {
-       printk(KERN_WARNING "omapdsp: DSP WDT expired!\n");
        errcode |= OMAP_DSP_ERRDT_WDT;
        errcnt++;
-       wdtval = mb->data;
+       wdtval = data;
        wake_up_interruptible(&err_wait_q);
 }
 
+#ifdef OLD_BINARY_SUPPORT
+/* v3.3 obsolete */
+void mbx1_wdt(struct mbcmd *mb)
+{
+       mbx1_err_wdt(mb->data);
+}
+#endif
+
 extern void mbx1_err_ipbfull(void);
 extern void mbx1_err_fatal(unsigned char tid);
 
@@ -174,6 +181,10 @@ void mbx1_err(struct mbcmd *mb)
                tid = mb->data & 0x00ff;
                mbx1_err_fatal(tid);
                break;
+
+       case OMAP_DSP_EID_WDT:
+               mbx1_err_wdt(mb->data);
+               break;
        }
 }
 
index 0f890697810ff12c77a94b64be2afb5f27bd5b8d..46fc33ccc80ae45a56170d64a07cf0abe4794e47 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2005/02/24:  DSP Gateway version 3.2
+ * 2005/02/24:  DSP Gateway version 3.3
  */
 
 struct fifo_struct {
index 4c70dd1ccf834d777040c1ccf87c11ee66e8e1bf..b27d085879052b58ce428da2e752c275b5504954 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2004/09/30:  DSP Gateway version 3.2
+ * 2005/05/30:  DSP Gateway version 3.3
  */
 
 #ifndef __OMAP_DSP_HARDWARE_DSP_H
 #define __OMAP_DSP_HARDWARE_DSP_H
 
+#ifdef CONFIG_ARCH_OMAP1510
+#define OMAP1510_DARAM_BASE    0xe0000000
+#define OMAP1510_DARAM_SIZE    0x10000
+#define OMAP1510_SARAM_BASE    0xe0010000
+#define OMAP1510_SARAM_SIZE    0x18000
+#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
+#endif
+
 /*
  * MAJOR device number: !! allocated arbitrary !!
  */
 /*
  * 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
index 305ce68917225f10f97c66d6de1322a43e2419bb..ebb482b05f04d467665952fa0eabbfba44170ee2 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2005/02/17:  DSP Gateway version 3.2
+ * 2005/06/06:  DSP Gateway version 3.3
  */
 
 #include <linux/init.h>
@@ -38,51 +38,51 @@ struct ipbuf **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;
 
 void ipbuf_stop(void)
 {
+       int i;
+
+       spin_lock(&ipb_free.lock);
+       INIT_IPBLINK(&ipb_free);
+       spin_unlock(&ipb_free.lock);
+
        ipbcfg.ln = 0;
        if (ipbuf) {
                kfree(ipbuf);
                ipbuf = NULL;
        }
+       for (i = 0; i < ipbuf_sys_hold_mem_active; i++) {
+               dsp_mem_disable((void *)daram_base);
+       }
+       ipbuf_sys_hold_mem_active = 0;
 }
 
-/*
- * ipbuf_config() is called by mailbox workqueue
- */
-int ipbuf_config(unsigned short ln, unsigned short lsz, unsigned long adr)
+int ipbuf_config(unsigned short ln, unsigned short lsz, void *base)
 {
-       void *base;
        unsigned long lsz_byte = ((unsigned long)lsz) << 1;
        size_t size;
        int ret = 0;
        int i;
 
-       spin_lock(&ipb_free.lock);
-       INIT_IPBLINK(&ipb_free);
-       spin_unlock(&ipb_free.lock);
-
        /*
         * global IPBUF
         */
-       if (adr & 0x1) {
+       if (((unsigned long)base) & 0x3) {
                printk(KERN_ERR
-                      "mbx: global ipbuf address (0x%08lx) is odd number!\n",
-                      adr);
+                      "omapdsp: global ipbuf address(0x%p) is not "
+                      "32-bit aligned!\n", base);
                return -EINVAL;
        }
        size = lsz_byte * ln;
-       if (adr + size > DSPSPACE_SIZE) {
-               printk(KERN_ERR
-                      "mbx: ipbuf address (0x%08lx) and size (0x%08x) is "
-                      "illegal!\n", adr, size);
+       if (dsp_address_validate(base, size, "global ipbuf") < 0)
                return -EINVAL;
-       }
-       base = dspword_to_virt(adr);
+
        ipbuf = kmalloc(sizeof(void *) * ln, GFP_KERNEL);
        if (ipbuf == NULL) {
-               printk(KERN_ERR "mbx: memory allocation for ipbuf failed.\n");
+               printk(KERN_ERR
+                      "omapdsp: memory allocation for ipbuf failed.\n");
                return -ENOMEM;
        }
        for (i = 0; i < ln; i++) {
@@ -101,20 +101,75 @@ int ipbuf_config(unsigned short ln, unsigned short lsz, unsigned long adr)
                               "omapdsp: ipbuf[%d] crosses 64k-word boundary!\n"
                               "  @0x%p, size=0x%08lx\n", i, top, lsz_byte);
                        ret = -EINVAL;
+                       goto free_out;
                }
        }
        ipbcfg.ln       = ln;
        ipbcfg.lsz      = lsz;
-       ipbcfg.adr      = adr;
+       ipbcfg.base     = base;
        ipbcfg.bsycnt   = ln;   /* DSP holds all ipbufs initially. */
        ipbcfg.cnt_full = 0;
 
        printk(KERN_INFO
               "omapdsp: IPBUF configuration\n"
               "           %d words * %d lines at 0x%p.\n",
-              ipbcfg.lsz, ipbcfg.ln, dspword_to_virt(ipbcfg.adr));
+              ipbcfg.lsz, ipbcfg.ln, ipbcfg.base);
 
        return ret;
+
+free_out:
+       kfree(ipbuf);
+       ipbuf = NULL;
+       return ret;
+}
+
+int ipbuf_sys_config(void *p, enum arm_dsp_dir dir)
+{
+       char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D";
+
+       if (((unsigned long)p) & 0x3) {
+               printk(KERN_ERR
+                      "omapdsp: system ipbuf(%s) address(0x%p) is "
+                      "not 32-bit aligned!\n", dir_str, p);
+               return -1;
+       }
+       if (dsp_address_validate(p, sizeof(struct ipbuf_sys),
+                                "system ipbuf(%s)", dir_str) < 0)
+               return -1;
+       if (dsp_mem_type(p, sizeof(struct ipbuf_sys)) != MEM_TYPE_EXTERN) {
+               printk(KERN_WARNING
+                      "omapdsp: system ipbuf(%s) is placed in"
+                      " DSP internal memory.\n"
+                      "         It will prevent DSP from idling.\n", dir_str);
+               ipbuf_sys_hold_mem_active++;
+               /*
+                * dsp_mem_enable() never fails because
+                * it has been already enabled in dspcfg process and
+                * this will just increment the usecount.
+                */
+               dsp_mem_enable((void *)daram_base);
+       }
+
+       if (dir == DIR_D2A)
+               ipbuf_sys_da = p;
+       else
+               ipbuf_sys_ad = p;
+       
+       return 0;
+}
+
+int ipbuf_p_validate(void *p, enum arm_dsp_dir dir)
+{
+       char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D";
+
+       if (((unsigned long)p) & 0x3) {
+               printk(KERN_ERR
+                      "omapdsp: private ipbuf(%s) address(0x%p) is "
+                      "not 32-bit aligned!\n", dir_str, p);
+               return -1;
+       }
+       return dsp_address_validate(p, sizeof(struct ipbuf_p),
+                                   "private ipbuf(%s)", dir_str);
 }
 
 /*
@@ -124,19 +179,22 @@ unsigned short get_free_ipbuf(unsigned char tid)
 {
        unsigned short bid;
 
-       if (ipblink_empty(&ipb_free)) {
-               /* FIXME: wait on queue when not available.  */
+       if (dsp_mem_enable_ipbuf() < 0)
                return OMAP_DSP_BID_NULL;
-       }
 
-       /*
-        * FIXME: dsp_enable_dspmem!
-        */
        spin_lock(&ipb_free.lock);
+
+       if (ipblink_empty(&ipb_free)) {
+               /* FIXME: wait on queue when not available.  */
+               bid = OMAP_DSP_BID_NULL;
+               goto out;
+       }
        bid = ipb_free.top;
        ipbuf[bid]->la = tid;   /* lock */
        ipblink_del_top(&ipb_free, ipbuf);
+out:
        spin_unlock(&ipb_free.lock);
+       dsp_mem_disable_ipbuf();
 
        return bid;
 }
@@ -161,12 +219,10 @@ void release_ipbuf(unsigned short bid)
 
 static int try_yld(unsigned short bid)
 {
-       struct mbcmd mb;
        int status;
 
        ipbuf[bid]->sa = OMAP_DSP_TID_ANON;
-       mbcmd_set(mb, MBCMD(BKYLD), 0, bid);
-       status = dsp_mbsend(&mb);
+       status = dsp_mbsend(MBCMD(BKYLD), 0, bid);
        if (status < 0) {
                /* DSP is busy and ARM keeps this line. */
                release_ipbuf(bid);
index c70f7964a29718aa61ac7495531ac20080971a32..77826f443d2cda5482c85f2529e52956a4d9b271 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2005/02/17:  DSP Gateway version 3.2
+ * 2005/05/17:  DSP Gateway version 3.3
  */
 
 struct ipbuf {
@@ -43,13 +43,13 @@ struct ipbuf_p {
 
 struct ipbuf_sys {
        unsigned short s;       /* sync word */
-       unsigned short d[15];   /* data */
+       unsigned short d[31];   /* data */
 };
 
 struct ipbcfg {
        unsigned short ln;
        unsigned short lsz;
-       unsigned long adr;
+       void *base;
        unsigned short bsycnt;
        unsigned long cnt_full; /* count of IPBFULL error */
 };
@@ -72,8 +72,8 @@ extern struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
                enable_irq(INT_D2A_MB1); \
        } while(0)
 
-#define dsp_mem_enable_ipbuf() dsp_mem_enable(dspword_to_virt(ipbcfg.adr))
-#define dsp_mem_disable_ipbuf()        dsp_mem_disable(dspword_to_virt(ipbcfg.adr))
+#define dsp_mem_enable_ipbuf() dsp_mem_enable(ipbcfg.base)
+#define dsp_mem_disable_ipbuf()        dsp_mem_disable(ipbcfg.base)
 
 struct ipblink {
        spinlock_t lock;
@@ -89,6 +89,7 @@ struct ipblink {
 
 #define INIT_IPBLINK(link) \
        do { \
+               spin_lock_init(&(link)->lock); \
                (link)->top  = OMAP_DSP_BID_NULL; \
                (link)->tail = OMAP_DSP_BID_NULL; \
        } while(0)
index 69d42c82f20d6204fd56dea829fbbf9fe18af42f..a4e7cd05417f5cd8e5da12c53ce251d8151b5de9 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2005/02/17:  DSP Gateway version 3.2
+ * 2005/05/18:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
@@ -98,6 +98,7 @@ char *subcmd_name(struct mbcmd *mb)
                    (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":
@@ -124,7 +125,7 @@ struct mblogent {
        unsigned long jiffies;
        unsigned short cmd;
        unsigned short data;
-       enum mblog_dir dir;
+       enum arm_dsp_dir dir;
 };
 
 static struct {
@@ -134,7 +135,7 @@ static struct {
        struct mblogent ent[MBLOG_DEPTH];
 } mblog;
 
-void mblog_add(struct mbcmd *mb, enum mblog_dir dir)
+void mblog_add(struct mbcmd *mb, enum arm_dsp_dir dir)
 {
        struct mbcmd_hw *mb_hw = (struct mbcmd_hw *)mb;
        struct mblogent *ent;
@@ -148,11 +149,11 @@ void mblog_add(struct mbcmd *mb, enum mblog_dir dir)
        if (mblog.cnt < 0xffffffff)
                mblog.cnt++;
        switch (dir) {
-       case MBLOG_DIR_AD:
+       case DIR_A2D:
                if (mblog.cnt_ad < 0xffffffff)
                        mblog.cnt_ad++;
                break;
-       case MBLOG_DIR_DA:
+       case DIR_D2A:
                if (mblog.cnt_da < 0xffffffff)
                        mblog.cnt_da++;
                break;
@@ -197,7 +198,7 @@ static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
                const struct cmdinfo *ci = cmdinfo[mb.sw.cmd_h];
 
                len += sprintf(buf + len,
-                              (ent->dir == MBLOG_DIR_AD) ?
+                              (ent->dir == DIR_A2D) ?
                                "%08lx %d %04x %04x             ":
                                "%08lx             %d %04x %04x ",
                               ent->jiffies, mb.sw.seq, ent->cmd, ent->data);
@@ -230,13 +231,13 @@ done:
 static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
 
 #ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
-void mblog_printcmd(struct mbcmd *mb, enum mblog_dir dir)
+void mblog_printcmd(struct mbcmd *mb, enum arm_dsp_dir dir)
 {
        const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
        char *dir_str;
        char *subname;
 
-       dir_str = (dir == MBLOG_DIR_AD) ? "sending" : "receiving";
+       dir_str = (dir == DIR_A2D) ? "sending" : "receiving";
        switch (ci->cmd_l_type) {
        case CMD_L_TYPE_SUBCMD:
                if ((subname = subcmd_name(mb)) == NULL)
index 723e5b09d273fefa5fe7c532f466e52cdc5acbf9..7214317686d0de1d016bb8e1dc4bd7620c9af17a 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2004/11/22:  DSP Gateway version 3.2
+ * 2004/11/22:  DSP Gateway version 3.3
  */
 
 struct proc_list {
index fe028a09e8fcc87a3264c7db5be8eab0d7f73800..e5c60dde43756678ae2e1972b4db6af29b4c93c5 100644 (file)
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2005/02/22:  DSP Gateway version 3.2
+ * 2005/07/26:  DSP Gateway version 3.3
  */
 
 #include <linux/kernel.h>
@@ -32,7 +32,6 @@
 #include <linux/fs.h>
 #include <linux/poll.h>
 #include <linux/device.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include "fifo.h"
 #include "proclist.h"
 
+#define is_aligned(adr,align)  (!((adr)&((align)-1)))
+
 /*
- * device state machine
+ * taskdev.state: 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.
- * KILLREQ:    requesting for tkill.
  * 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")
 
 struct taskdev {
        struct bus_type *bus;
@@ -147,6 +162,7 @@ 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 ssize_t devname_show(struct device *d, struct device_attribute *attr,
                            char *buf);
@@ -345,23 +361,27 @@ static int dsp_task_config(struct dsptask *task, unsigned char tid)
 {
        unsigned short ttyp;
        struct mbcmd mb;
+       int ret;
 
-       dsptask[tid] = task;
        task->tid = tid;
+       dsptask[tid] = task;
 
        /* TCFG request */
        task->state = TASK_STATE_CFGREQ;
-       if (down_interruptible(&cfg_sem))
-               return -ERESTARTSYS;
+       if (down_interruptible(&cfg_sem)) {
+               ret = -ERESTARTSYS;
+               goto fail_out;
+       }
        cfg_cmd = MBCMD(TCFG);
        mbcmd_set(mb, MBCMD(TCFG), tid, 0);
-       dsp_mbsend_and_wait(&mb, &cfg_wait_q);
+       dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
        cfg_cmd = 0;
        up(&cfg_sem);
 
        if (task->state != TASK_STATE_READY) {
                printk(KERN_ERR "omapdsp: task %d configuration error!\n", tid);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto fail_out;
        }
 
        if (strlen(task->name) <= 1)
@@ -370,35 +390,49 @@ static int dsp_task_config(struct dsptask *task, unsigned char tid)
 
        ttyp = task->ttyp;
 
+       /*
+        * task info sanity check
+        */
+
        /* task type check */
        if (rcvtyp_psv(ttyp) && rcvtyp_pvt(ttyp)) {
-               printk(KERN_ERR "mbx: illegal task type(0x%04x), tid=%d\n",
+               printk(KERN_ERR "omapdsp: illegal task type(0x%04x), tid=%d\n",
                       tid, ttyp);
+               ret = -EINVAL;
+               goto fail_out;
        }
 
        /* private buffer address check */
-       if (sndtyp_pvt(ttyp)) {
-               void *p = task->rcvdt.bk.ipbuf_pvt_r;
-
-               if ((unsigned long)p & 0x1) {
-                       printk(KERN_ERR
-                              "mbx: private ipbuf (DSP->ARM) address (0x%p) "
-                              "is odd number!\n", p);
-                       return -EINVAL;
-               }
+       if (sndtyp_pvt(ttyp) &&
+           (ipbuf_p_validate(task->rcvdt.bk.ipbuf_pvt_r, DIR_D2A) < 0)) {
+               ret = -EINVAL;
+               goto fail_out;
        }
-
-       if (rcvtyp_pvt(ttyp)) {
-               void *p = task->ipbuf_pvt_w;
-
-               if ((unsigned long)p & 0x1) {
-                       printk(KERN_ERR
-                              "mbx: private ipbuf (ARM->DSP) address (0x%p) "
-                              "is odd number!\n", p);
-                       return -EINVAL;
-               }
+       if (rcvtyp_pvt(ttyp) &&
+           (ipbuf_p_validate(task->ipbuf_pvt_w, DIR_A2D) < 0)) {
+               ret = -EINVAL;
+               goto fail_out;
+       }
+       
+       /* mmap buffer configuration check */
+       if ((task->map_length > 0) &&
+           ((!is_aligned((unsigned long)task->map_base, PAGE_SIZE)) ||
+            (!is_aligned(task->map_length, PAGE_SIZE)) ||
+            (dsp_mem_type(task->map_base, task->map_length) != MEM_TYPE_EXTERN))) {
+               printk(KERN_ERR
+                      "omapdsp: illegal mmap buffer address(0x%p) or "
+                      "length(0x%x).\n"
+                      "  It needs to be page-aligned and located at "
+                      "external memory.\n",
+                      task->map_base, task->map_length);
+               ret = -EINVAL;
+               goto fail_out;
        }
 
+       /*
+        * initialization
+        */
+
        /* read initialization */
        if (sndtyp_wd(ttyp)) {
                /* word */
@@ -410,11 +444,11 @@ static int dsp_task_config(struct dsptask *task, unsigned char tid)
                        printk(KERN_ERR
                               "omapdsp: unable to allocate receive buffer. "
                               "(%d bytes for %s)\n", fifosz, task->name);
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto fail_out;
                }
        } else {
                /* block */
-               spin_lock_init(&task->rcvdt.bk.link.lock);
                INIT_IPBLINK(&task->rcvdt.bk.link);
                task->rcvdt.bk.rp = 0;
        }
@@ -426,14 +460,15 @@ static int dsp_task_config(struct dsptask *task, unsigned char tid)
                                       ipbcfg.lsz*2;    /* passive block */
 
        return 0;
+
+fail_out:
+       dsptask[tid] = NULL;
+       return ret;
 }
 
 static void dsp_task_init(struct dsptask *task)
 {
-       struct mbcmd mb;
-
-       mbcmd_set(mb, MBCMD(TCTL), task->tid, OMAP_DSP_MBCMD_TCTL_TINIT);
-       dsp_mbsend(&mb);
+       dsp_mbsend(MBCMD(TCTL), task->tid, OMAP_DSP_MBCMD_TCTL_TINIT);
 }
 
 int dsp_task_config_all(unsigned char n)
@@ -558,11 +593,22 @@ int dsp_taskmod_busy(void)
 
        for (minor = 0; minor < TASKDEV_MAX; minor++) {
                dev = taskdev[minor];
-               if (dev &&
-                   ((dev->usecount > 0) ||
-                    (dev->state == OMAP_DSP_DEVSTATE_ADDREQ) ||
-                    (dev->state == OMAP_DSP_DEVSTATE_DELREQ)))
+               if (dev == NULL)
+                       continue;
+               if (dev->usecount > 0) {
+                       printk("dsp_taskmod_busy(): %s: usecount=%d\n",
+                              dev->name, dev->usecount);
                        return 1;
+               }
+/*
+               if ((dev->state & (OMAP_DSP_DEVSTATE_ADDREQ |
+                                  OMAP_DSP_DEVSTATE_DELREQ)) {
+*/
+               if (dev->state & OMAP_DSP_DEVSTATE_ADDREQ) {
+                       printk("dsp_taskmod_busy(): %s is in %s\n",
+                              dev->name, devstate_name(dev->state));
+                       return 1;
+               }
        }
        return 0;
 }
@@ -704,13 +750,19 @@ static ssize_t dsp_task_read_bk_acv(struct file *file, char *buf, size_t count,
                                ret = -ERESTARTSYS;
                                goto up_out;
                        }
-                       base = dspword_to_virt(MKLONG(ipbp->ah, ipbp->al));
-                       src = base + rcvdt->rp;
+                       base = MKVIRT(ipbp->ah, ipbp->al);
+                       bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp;
+                       if (dsp_address_validate(base, bkcnt,
+                                                "task %s read buffer",
+                                                dev->task->name) < 0) {
+                               ret = -ERESTARTSYS;
+                               goto pv_out1;
+                       }
                        if (dsp_mem_enable(base) < 0) {
                                ret = -ERESTARTSYS;
                                goto pv_out1;
                        }
-                       bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp;
+                       src = base + rcvdt->rp;
                        if (bkcnt > count) {
                                if (copy_to_user_dsp(buf, src, count)) {
                                        ret = -EFAULT;
@@ -813,7 +865,7 @@ static ssize_t dsp_task_read_wd_psv(struct file *file, char *buf, size_t count,
        devstate_unlock(dev);
 
        mbcmd_set(mb, MBCMD(WDREQ), tid, 0);
-       dsp_mbsend_and_wait(&mb, &dev->read_wait_q);
+       dsp_mbcmd_send_and_wait(&mb, &dev->read_wait_q);
 
        if (signal_pending(current)) {
                ret = -ERESTARTSYS;
@@ -868,7 +920,7 @@ static ssize_t dsp_task_read_bk_psv(struct file *file, char *buf, size_t count,
        devstate_unlock(dev);
 
        mbcmd_set(mb, MBCMD(BKREQ), tid, count/2);
-       dsp_mbsend_and_wait(&mb, &dev->read_wait_q);
+       dsp_mbcmd_send_and_wait(&mb, &dev->read_wait_q);
 
        if (signal_pending(current)) {
                ret = -ERESTARTSYS;
@@ -896,12 +948,17 @@ static ssize_t dsp_task_read_bk_psv(struct file *file, char *buf, size_t count,
                        ret = -ERESTARTSYS;
                        goto unlock_out;
                }
-               src = dspword_to_virt(MKLONG(ipbp->ah, ipbp->al));
+               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;
+                       goto pv_out1;
+               }
                if (dsp_mem_enable(src) < 0) {
                        ret = -ERESTARTSYS;
                        goto pv_out1;
                }
-               rcvcnt = ((unsigned long)ipbp->c) * 2;
                if (count > rcvcnt)
                        count = rcvcnt;
                if (copy_to_user_dsp(buf, src, count)) {
@@ -955,7 +1012,6 @@ static ssize_t dsp_task_write_wd(struct file *file, const char *buf,
 {
        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        struct taskdev *dev = taskdev[minor];
-       struct mbcmd mb;
        unsigned short wd;
        int have_devstate_lock = 0;
        int ret = 0;
@@ -1013,9 +1069,8 @@ static ssize_t dsp_task_write_wd(struct file *file, const char *buf,
                goto up_out;
        }
 
-       mbcmd_set(mb, MBCMD(WDSND), dev->task->tid, wd);
        spin_lock(&dev->task->wsz_lock);
-       if (dsp_mbsend(&mb) < 0) {
+       if (dsp_mbsend(MBCMD(WDSND), dev->task->tid, wd) < 0) {
                spin_unlock(&dev->task->wsz_lock);
                goto up_out;
        }
@@ -1036,7 +1091,6 @@ static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
 {
        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        struct taskdev *dev = taskdev[minor];
-       struct mbcmd mb;
        int have_devstate_lock = 0;
        int ret = 0;
 
@@ -1102,7 +1156,12 @@ static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
                        ret = -ERESTARTSYS;
                        goto up_out;
                }
-               dst = dspword_to_virt(MKLONG(ipbp->ah, ipbp->al));
+               dst = MKVIRT(ipbp->ah, ipbp->al);
+               if (dsp_address_validate(dst, count, "task %s write buffer",
+                                        dev->task->name) < 0) {
+                       ret = -ERESTARTSYS;
+                       goto pv_out1;
+               }
                if (dsp_mem_enable(dst) < 0) {
                        ret = -ERESTARTSYS;
                        goto pv_out1;
@@ -1113,9 +1172,8 @@ static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
                }
                ipbp->c = count/2;
                ipbp->s = dev->task->tid;
-               mbcmd_set(mb, MBCMD(BKSNDP), dev->task->tid, 0);
                spin_lock(&dev->task->wsz_lock);
-               if (dsp_mbsend(&mb) == 0) {
+               if (dsp_mbsend(MBCMD(BKSNDP), dev->task->tid, 0) == 0) {
                        if (rcvtyp_acv(dev->task->ttyp))
                                dev->task->wsz = 0;
                        ret = count;
@@ -1145,9 +1203,8 @@ pv_out1:
                }
                ipbp->c  = count/2;
                ipbp->sa = dev->task->tid;
-               mbcmd_set(mb, MBCMD(BKSND), dev->task->tid, bid);
                spin_lock(&dev->task->wsz_lock);
-               if (dsp_mbsend(&mb) == 0) {
+               if (dsp_mbsend(MBCMD(BKSND), dev->task->tid, bid) == 0) {
                        if (rcvtyp_acv(dev->task->ttyp))
                                dev->task->wsz = 0;
                        ret = count;
@@ -1226,6 +1283,9 @@ static int dsp_task_ioctl(struct inode *inode, struct file *file,
                 * 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) {
@@ -1315,7 +1375,7 @@ static int dsp_task_ioctl(struct inode *inode, struct file *file,
                dev->task->tctl_stat = -ERESTARTSYS;
                devstate_unlock(dev);
 
-               dsp_mbsend_and_wait_exarg(&mb, mbargp, &dev->ioctl_wait_q);
+               dsp_mbcmd_send_and_wait_exarg(&mb, mbargp, &dev->ioctl_wait_q);
                if (signal_pending(current)) {
                        ret = -ERESTARTSYS;
                        goto up_out;
@@ -1330,7 +1390,7 @@ static int dsp_task_ioctl(struct inode *inode, struct file *file,
                        goto unlock_out;
                }
        } else {
-               dsp_mbsend_exarg(&mb, mbargp);
+               dsp_mbcmd_send_exarg(&mb, mbargp);
                ret = 0;
        }
 
@@ -1341,18 +1401,42 @@ up_out:
        return ret;
 }
 
+static void dsp_task_mmap_open(struct vm_area_struct *vma)
+{
+       struct taskdev *dev = (struct taskdev *)vma->vm_private_data;
+       struct dsptask *task;
+       size_t len = vma->vm_end - vma->vm_start;
+
+       BUG_ON(!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED));
+       task = dev->task;
+       exmap_use(task->map_base, len);
+}
+
+static void dsp_task_mmap_close(struct vm_area_struct *vma)
+{
+       struct taskdev *dev = (struct taskdev *)vma->vm_private_data;
+       struct dsptask *task;
+       size_t len = vma->vm_end - vma->vm_start;
+
+       BUG_ON(!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED));
+       task = dev->task;
+       exmap_unuse(task->map_base, len);
+}
+
 /**
  * On demand page allocation is not allowed. The mapping area is defined by
  * corresponding DSP tasks.
  */
-static struct page *dsp_task_nopage_mmap(struct vm_area_struct *vma,
+static struct page *dsp_task_mmap_nopage(struct vm_area_struct *vma,
                                         unsigned long address, int *type)
 {
        return NOPAGE_SIGBUS;
 }
 
 static struct vm_operations_struct dsp_task_vm_ops = {
-       .nopage = dsp_task_nopage_mmap,
+       .open = dsp_task_mmap_open,
+       .close = dsp_task_mmap_close,
+       .nopage = dsp_task_mmap_nopage,
 };
 
 static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
@@ -1368,21 +1452,6 @@ static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
        if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0)
                return -ERESTARTSYS;
        task = dev->task;
-       if (task->map_length == 0) {
-               printk(KERN_ERR
-                      "omapdsp: task %s doesn't have mmap buffer.\n",
-                      task->name);
-               ret = -EINVAL;
-               goto unlock_out;
-       }
-       if (is_dsp_internal_mem(task->map_base)) {
-               printk(KERN_ERR
-                      "omapdsp: task %s: map_base = %p\n"
-                      "    DARAM/SARAM can't be used as mmap buffer.\n",
-                      task->name, task->map_base);
-               ret = -EINVAL;
-               goto unlock_out;
-       }
 
        /*
         * Don't swap this area out
@@ -1430,6 +1499,9 @@ static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
        } while (req_len);
 
        vma->vm_ops = &dsp_task_vm_ops;
+       vma->vm_private_data = dev;
+       exmap_use(task->map_base, vma->vm_end - vma->vm_start);
+
 unlock_out:
        devstate_unlock(dev);
        return ret;
@@ -1441,12 +1513,8 @@ static int dsp_task_open(struct inode *inode, struct file *file)
        struct taskdev *dev;
        int ret = 0;
 
-       if (minor >= TASKDEV_MAX)
-               return -ENODEV;
-       dev = taskdev[minor];
-       if (dev == NULL)
+       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;
@@ -1457,15 +1525,20 @@ static int dsp_task_open(struct inode *inode, struct file *file)
        }
 #endif
 
-       if (dev->state == OMAP_DSP_DEVSTATE_NOTASK) {
+       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)
+                                      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) {
+               }
+               if (dev->state & OMAP_DSP_DEVSTATE_ADDFAIL) {
                        printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
                               dev->name);
                        ret = -EBUSY;
@@ -1496,10 +1569,10 @@ static int dsp_task_release(struct inode *inode, struct file *file)
        /* state_lock covers usecount, proc_list as well. */
        spin_lock(&dev->state_lock);
 
-       /* state can be ATTACHED, KILLREQ or GARBAGE here. */
-       switch (dev->state) {
+       /* state can be ATTACHED, KILLING or GARBAGE here. */
+       switch (dev->state & OMAP_DSP_DEVSTATE_STATE_MASK) {
 
-       case OMAP_DSP_DEVSTATE_KILLREQ:
+       case OMAP_DSP_DEVSTATE_KILLING:
                dev->usecount--;
                break;
 
@@ -1582,11 +1655,10 @@ int dsp_rmdev(char *name)
 static int dsp_rmdev_minor(unsigned char minor)
 {
        struct taskdev *dev = taskdev[minor];
-       struct dsptask *task = dev->task;
 
        spin_lock(&dev->state_lock);
 
-       switch (dev->state) {
+       switch (dev->state & OMAP_DSP_DEVSTATE_STATE_MASK) {
 
        case OMAP_DSP_DEVSTATE_NOTASK:
                /* fine */
@@ -1598,6 +1670,7 @@ static int dsp_rmdev_minor(unsigned char minor)
                        siginfo_t info;
                        struct proc_list *pl;
 
+                       dev->state = OMAP_DSP_DEVSTATE_KILLING;
                        info.si_signo = SIGBUS;
                        info.si_errno = 0;
                        info.si_code = SI_KERNEL;
@@ -1605,12 +1678,10 @@ static int dsp_rmdev_minor(unsigned char minor)
                        list_for_each_entry(pl, &dev->proc_list, list_head) {
                                send_sig_info(SIGBUS, &info, pl->tsk);
                        }
-                       taskdev_detach_task(dev);
-                       dsp_task_unconfig(task);
-                       kfree(task);
-                       dev->state = OMAP_DSP_DEVSTATE_GARBAGE;
+                       spin_unlock(&dev->state_lock);
+                       dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_KILL);
+                       goto invalidate;
                }
-               break;
 
        case OMAP_DSP_DEVSTATE_ADDREQ:
                /* open() is waiting. drain it. */
@@ -1624,7 +1695,9 @@ static int dsp_rmdev_minor(unsigned char minor)
                wake_up_interruptible_all(&dev->state_wait_q);
                break;
 
-       case OMAP_DSP_DEVSTATE_KILLREQ:
+       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:
                /* transient state. wait for a moment. */
@@ -1634,12 +1707,13 @@ static int dsp_rmdev_minor(unsigned char minor)
 
        spin_unlock(&dev->state_lock);
 
+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) {
+       if (!(dev->state & OMAP_DSP_DEVSTATE_NOTASK)) {
                printk(KERN_WARNING
-                      "omapdsp: illegal device state on rmdev %s.\n",
-                      dev->name);
+                      "omapdsp: illegal device state (%s) on rmdev %s.\n",
+                      devstate_name(dev->state), dev->name);
        }
        dev->state = OMAP_DSP_DEVSTATE_INVALID;
        devstate_unlock(dev);
@@ -1656,7 +1730,6 @@ struct file_operations dsp_task_fops = {
        .ioctl   = dsp_task_ioctl,
        .open    = dsp_task_open,
        .release = dsp_task_release,
-       .mmap    = dsp_task_mmap,
 };
 
 static void dsptask_dev_release(struct device *dev)
@@ -1694,8 +1767,6 @@ static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
        device_create_file(&dev->dev, &dev_attr_proc_list);
        class_device_create(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor),
                            NULL, "dsptask%d", minor);
-       devfs_mk_cdev(MKDEV(OMAP_DSP_TASK_MAJOR, minor),
-                     S_IFCHR | S_IRUGO | S_IWUGO, "dsptask%d", minor);
 
        init_waitqueue_head(&dev->state_wait_q);
        spin_lock_init(&dev->state_lock);
@@ -1712,9 +1783,7 @@ static void taskdev_delete(unsigned char minor)
        device_remove_file(&dev->dev, &dev_attr_devname);
        device_remove_file(&dev->dev, &dev_attr_devstate);
        device_remove_file(&dev->dev, &dev_attr_proc_list);
-
        class_device_destroy(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor));
-       devfs_remove("dsptask%d", minor);
        device_unregister(&dev->dev);
        proc_list_flush(&dev->proc_list);
        taskdev[minor] = NULL;
@@ -1736,6 +1805,8 @@ static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
        dev->fops.write =
                rcvtyp_wd(ttyp) ? dsp_task_write_wd:
                /* rcvbyp_bk */   dsp_task_write_bk;
+       if (task->map_length)
+               dev->fops.mmap = dsp_task_mmap;
 
        device_create_file(&dev->dev, &dev_attr_taskname);
        device_create_file(&dev->dev, &dev_attr_ttyp);
@@ -1781,7 +1852,7 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
        struct dsptask *task;
        struct mbcmd mb;
        struct mb_exarg arg;
-       unsigned char tid;
+       unsigned char tid, tid_response;
        unsigned short argv[2];
        int ret = minor;
 
@@ -1790,16 +1861,17 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
                       "omapdsp: no task device with minor %d\n", minor);
                return -EINVAL;
        }
-       /*
-        * we don't need to lock state_lock because
-        * only tadd is allowed when devstate is ADDREQ.
-        */
-       if (dev->state != OMAP_DSP_DEVSTATE_ADDREQ) {
+
+       spin_lock(&dev->state_lock);
+       if (!(dev->state & OMAP_DSP_DEVSTATE_ADDREQ)) {
                printk(KERN_ERR
-                      "omapdsp: taskdev %s is not requesting for tadd.\n",
-                      dev->name);
+                      "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);
 
        if (adr == OMAP_DSP_TADD_ABORTADR) {
                /* aborting tadd intentionally */
@@ -1828,7 +1900,8 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
        arg.argc = 2;
        arg.argv = argv;
 
-       dsp_mbsend_and_wait_exarg(&mb, &arg, &cfg_wait_q);
+       dsp_mem_sync_inc();
+       dsp_mbcmd_send_and_wait_exarg(&mb, &arg, &cfg_wait_q);
 
        tid = cfg_tid;
        cfg_tid = OMAP_DSP_TID_ANON;
@@ -1847,7 +1920,7 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
        }
        if ((task = kmalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
                ret = -ENOMEM;
-               goto fail_out;
+               goto del_out;
        }
        memset(task, 0, sizeof(struct dsptask));
 
@@ -1860,9 +1933,7 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
                       "omapdsp: task name (%s) doesn't match with "
                       "device name (%s).\n", task->name, dev->name);
                ret = -EINVAL;
-               dev->state = OMAP_DSP_DEVSTATE_DELREQ;
-               dsp_twch_touch();
-               return -EINVAL;
+               goto free_out;
        }
 
        dsp_task_init(task);
@@ -1873,6 +1944,30 @@ int dsp_tadd(unsigned char minor, unsigned long adr)
 
 free_out:
        kfree(task);
+
+del_out:
+       printk(KERN_ERR "omapdsp: deleting the task...\n");
+
+       dev->state = OMAP_DSP_DEVSTATE_DELING;
+
+       if (down_interruptible(&cfg_sem)) {
+               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);
+       tid_response = cfg_tid;
+       cfg_tid = OMAP_DSP_TID_ANON;
+       cfg_cmd = 0;
+       up(&cfg_sem);
+
+       if (tid_response != tid)
+               printk(KERN_ERR "omapdsp: tdel failed. "
+                               "DSP side could be corrupted.\n");
+
 fail_out:
        dev->state = OMAP_DSP_DEVSTATE_ADDFAIL;
        wake_up_interruptible_all(&dev->state_wait_q);
@@ -1882,64 +1977,31 @@ fail_out:
 int dsp_tdel(unsigned char minor)
 {
        struct taskdev *dev;
-       struct dsptask *task;
-       struct mbcmd mb;
-       unsigned char tid, tid_response;
-       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;
        }
-       /*
-        * we don't need to lock state_lock because
-        * only tdel is allowed when devstate is DELREQ.
-        */
-       if (dev->state != OMAP_DSP_DEVSTATE_DELREQ) {
+       spin_lock(&dev->state_lock);
+       if (!(dev->state & OMAP_DSP_DEVSTATE_DELREQ)) {
                printk(KERN_ERR
-                      "omapdsp: taskdev %s is not requesting for tdel.\n",
-                      dev->name);
+                      "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);
 
-       task = dev->task;
-       tid = task->tid;
-       if (down_interruptible(&cfg_sem)) {
-               return -ERESTARTSYS;
-       }
-       cfg_tid = OMAP_DSP_TID_ANON;
-       cfg_cmd = MBCMD(TDEL);
-       mbcmd_set(mb, MBCMD(TDEL), tid, OMAP_DSP_MBCMD_TDEL_SAFE);
-       dsp_mbsend_and_wait(&mb, &cfg_wait_q);
-       tid_response = cfg_tid;
-       cfg_tid = OMAP_DSP_TID_ANON;
-       cfg_cmd = 0;
-       up(&cfg_sem);
-
-       taskdev_detach_task(dev);
-       dsp_task_unconfig(task);
-       kfree(task);
-       dev->state = OMAP_DSP_DEVSTATE_NOTASK;
-       wake_up_interruptible_all(&dev->state_wait_q);
-
-       if (tid_response != tid) {
-               printk(KERN_ERR "omapdsp: tdel failed!\n");
-               ret = -EINVAL;
-       }
-
-       return ret;
+       return dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_SAFE);
 }
 
 int dsp_tkill(unsigned char minor)
 {
        struct taskdev *dev;
-       struct dsptask *task;
-       struct mbcmd mb;
-       unsigned char tid, tid_response;
        siginfo_t info;
        struct proc_list *pl;
-       int ret = minor;
 
        if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
                printk(KERN_ERR
@@ -1947,14 +2009,14 @@ int dsp_tkill(unsigned char minor)
                return -EINVAL;
        }
        spin_lock(&dev->state_lock);
-       if (dev->state != OMAP_DSP_DEVSTATE_ATTACHED) {
+       if (!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED)) {
                printk(KERN_ERR
                       "omapdsp: task has not been attached for taskdev %s\n",
                       dev->name);
                spin_unlock(&dev->state_lock);
                return -EINVAL;
        }
-       dev->state = OMAP_DSP_DEVSTATE_KILLREQ;
+       dev->state = OMAP_DSP_DEVSTATE_KILLING;
        info.si_signo = SIGBUS;
        info.si_errno = 0;
        info.si_code = SI_KERNEL;
@@ -1964,17 +2026,33 @@ int dsp_tkill(unsigned char minor)
        }
        spin_unlock(&dev->state_lock);
 
+       return dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_KILL);
+}
+
+static int dsp_tdel_bh(unsigned char minor, unsigned short type)
+{
+       struct taskdev *dev = taskdev[minor];
+       struct dsptask *task;
+       struct mbcmd mb;
+       unsigned char tid, tid_response;
+       int ret = minor;
+
        task = dev->task;
        tid = task->tid;
        if (down_interruptible(&cfg_sem)) {
-               tid_response = OMAP_DSP_TID_ANON;
-               ret = -ERESTARTSYS;
-               goto detach_out;
+               if (type == OMAP_DSP_MBCMD_TDEL_SAFE) {
+                       dev->state = OMAP_DSP_DEVSTATE_DELREQ;
+                       return -ERESTARTSYS;
+               } else {
+                       tid_response = OMAP_DSP_TID_ANON;
+                       ret = -ERESTARTSYS;
+                       goto detach_out;
+               }
        }
        cfg_tid = OMAP_DSP_TID_ANON;
        cfg_cmd = MBCMD(TDEL);
-       mbcmd_set(mb, MBCMD(TDEL), tid, OMAP_DSP_MBCMD_TDEL_KILL);
-       dsp_mbsend_and_wait(&mb, &cfg_wait_q);
+       mbcmd_set(mb, MBCMD(TDEL), tid, type);
+       dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
        tid_response = cfg_tid;
        cfg_tid = OMAP_DSP_TID_ANON;
        cfg_cmd = 0;
@@ -1985,9 +2063,11 @@ detach_out:
        dsp_task_unconfig(task);
        kfree(task);
 
-       if (tid_response != tid)
-               printk(KERN_ERR "omapdsp: tkill failed!\n");
-
+       if (tid_response != tid) {
+               printk(KERN_ERR "omapdsp: %s failed!\n",
+                      (type == OMAP_DSP_MBCMD_TDEL_SAFE) ? "tdel" : "tkill");
+               ret = -EINVAL;
+       }
        spin_lock(&dev->state_lock);
        dev->state = (dev->usecount > 0) ? OMAP_DSP_DEVSTATE_GARBAGE :
                                           OMAP_DSP_DEVSTATE_NOTASK;
@@ -2000,10 +2080,14 @@ detach_out:
 /*
  * state inquiry
  */
-long taskdev_state(unsigned char minor)
+long taskdev_state_stale(unsigned char minor)
 {
-       return taskdev[minor] ? taskdev[minor]->state :
-                               OMAP_DSP_DEVSTATE_NOTASK;
+       if (taskdev[minor]) {
+               long state = taskdev[minor]->state;
+               taskdev[minor]->state |= OMAP_DSP_DEVSTATE_STALE;
+               return state;
+       } else
+               return OMAP_DSP_DEVSTATE_NOTASK;
 }
 
 /*
@@ -2271,9 +2355,6 @@ void mbx1_tcfg(struct mbcmd *mb)
 {
        unsigned char tid = mb->cmd_l;
        struct dsptask *task = dsptask[tid];
-       unsigned long tmp_ipbp_r, tmp_ipbp_w;
-       unsigned long tmp_mapstart, tmp_maplen;
-       unsigned long tmp_tnm;
        unsigned short *tnm;
        volatile unsigned short *buf;
        int i;
@@ -2289,25 +2370,29 @@ void mbx1_tcfg(struct mbcmd *mb)
 
        if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
                printk(KERN_ERR "mbx: TCFG - IPBUF sync failed!\n");
-               return;
+               goto out;
        }
 
        /*
         * read configuration data on system IPBUF
         */
        buf = ipbuf_sys_da->d;
-       task->ttyp   = buf[0];
-       tmp_ipbp_r   = MKLONG(buf[1], buf[2]);
-       tmp_ipbp_w   = MKLONG(buf[3], buf[4]);
-       tmp_mapstart = MKLONG(buf[5], buf[6]);
-       tmp_maplen   = MKLONG(buf[7], buf[8]);
-       tmp_tnm      = MKLONG(buf[9], buf[10]);
-
-       task->rcvdt.bk.ipbuf_pvt_r = dspword_to_virt(tmp_ipbp_r);
-       task->ipbuf_pvt_w          = dspword_to_virt(tmp_ipbp_w);
-       task->map_base   = dspword_to_virt(tmp_mapstart);
-       task->map_length = tmp_maplen << 1;     /* word -> byte */
-       tnm = dspword_to_virt(tmp_tnm);
+       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]);
+       release_ipbuf_pvt(ipbuf_sys_da);
+
+       /*
+        * copy task name string
+        */
+       if (dsp_address_validate(tnm, OMAP_DSP_TNM_LEN, "task name buffer") <0) {
+               task->name[0] = '\0';
+               goto out;
+       }
+
        for (i = 0; i < OMAP_DSP_TNM_LEN-1; i++) {
                /* avoiding byte access */
                unsigned short tmp = tnm[i];
@@ -2317,8 +2402,8 @@ void mbx1_tcfg(struct mbcmd *mb)
        }
        task->name[OMAP_DSP_TNM_LEN-1] = '\0';
 
-       release_ipbuf_pvt(ipbuf_sys_da);
        task->state = TASK_STATE_READY;
+out:
        wake_up_interruptible(&cfg_wait_q);
 }
 
@@ -2368,7 +2453,117 @@ void mbx1_err_fatal(unsigned char tid)
        spin_unlock(&task->dev->state_lock);
 }
 
+static short *dbg_buf;
+static unsigned short dbg_buf_sz, dbg_line_sz;
+static int dbg_rp;
+
+int dsp_dbg_config(short *buf, unsigned short sz, unsigned short lsz)
+{
+#ifdef OLD_BINARY_SUPPORT
+       if ((mbx_revision == MBREV_3_0) || (mbx_revision == MBREV_3_2)) {
+               dbg_buf = NULL;
+               dbg_buf_sz = 0;
+               dbg_line_sz = 0;
+               dbg_rp = 0;
+               return 0;
+       }
+#endif
+
+       if (dsp_address_validate(buf, sz, "debug buffer") < 0)
+               return -1;
+
+       if (lsz > sz) {
+               printk(KERN_ERR
+                      "omapdsp: dbg_buf lsz (%d) is greater than its "
+                      "buffer size (%d)\n", lsz, sz);
+               return -1;
+       }
+
+       dbg_buf = buf;
+       dbg_buf_sz = sz;
+       dbg_line_sz = lsz;
+       dbg_rp = 0;
+
+       return 0;
+}
+
+void dsp_dbg_stop(void)
+{
+       dbg_buf = NULL;
+}
+
+#ifdef OLD_BINARY_SUPPORT
+static void mbx1_dbg_old(struct mbcmd *mb);
+#endif
+
 void mbx1_dbg(struct mbcmd *mb)
+{
+       unsigned char tid = mb->cmd_l;
+       int cnt = mb->data;
+       char s[80], *s_end = &s[79], *p;
+       unsigned short *src;
+       int i;
+
+#ifdef OLD_BINARY_SUPPORT
+       if ((mbx_revision == MBREV_3_0) || (mbx_revision == MBREV_3_2)) {
+               mbx1_dbg_old(mb);
+               return;
+       }
+#endif
+
+       if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
+           (tid != OMAP_DSP_TID_ANON)) {
+               printk(KERN_ERR "mbx: DBG with illegal tid! %d\n", tid);
+               return;
+       }
+       if (dbg_buf == NULL) {
+               printk(KERN_ERR "mbx: DBG command received, but "
+                      "dbg_buf has not been configured yet.\n");
+               return;
+       }
+
+       if (dsp_mem_enable(dbg_buf) < 0)
+               return;
+
+       src = &dbg_buf[dbg_rp];
+       p = s;
+       for (i = 0; i < cnt; i++) {
+               unsigned short tmp;
+               /*
+                * Be carefull that dbg_buf should not be read with
+                * 1-byte access since it might be placed in DARAM/SARAM
+                * and it can cause unexpected byteswap.
+                * For example,
+                *   *(p++) = *(src++) & 0xff;
+                * causes 1-byte access!
+                */
+               tmp = *src++;
+               *(p++) = tmp & 0xff;
+               if (*(p-1) == '\n') {
+                       *p = '\0';
+                       printk(KERN_INFO "%s", s);
+                       p = s;
+                       continue;
+               }
+               if (p == s_end) {
+                       *p = '\0';
+                       printk(KERN_INFO "%s\n", s);
+                       p = s;
+                       continue;
+               }
+       }
+       if (p > s) {
+               *p = '\0';
+               printk(KERN_INFO "%s\n", s);
+       }
+       if ((dbg_rp += cnt + 1) > dbg_buf_sz - dbg_line_sz)
+               dbg_rp = 0;
+
+       dsp_mem_disable(dbg_buf);
+}
+
+#ifdef OLD_BINARY_SUPPORT
+static void mbx1_dbg_old(struct mbcmd *mb)
 {
        unsigned char tid = mb->cmd_l;
        char s[80], *s_end = &s[79], *p;
@@ -2388,7 +2583,13 @@ void mbx1_dbg(struct mbcmd *mb)
        }
        buf = ipbuf_sys_da->d;
        cnt = buf[0];
-       src = dspword_to_virt(MKLONG(buf[1], buf[2]));
+       src = MKVIRT(buf[1], buf[2]);
+       if (dsp_address_validate(src, cnt, "dbg buffer") < 0)
+               return;
+
+       if (dsp_mem_enable(src) < 0)
+               return;
+
        p = s;
        for (i = 0; i < cnt; i++) {
                unsigned short tmp;
@@ -2421,8 +2622,9 @@ void mbx1_dbg(struct mbcmd *mb)
        }
 
        release_ipbuf_pvt(ipbuf_sys_da);
+       dsp_mem_disable(src);
 }
-
+#endif /* OLD_BINARY_SUPPORT */
 
 /*
  * sysfs files
@@ -2434,17 +2636,6 @@ static ssize_t devname_show(struct device *d, struct device_attribute *attr,
        return sprintf(buf, "%s\n", dev->name);
 }
 
-#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_KILLREQ)  ? "KILLREQ" :\
-       ((stat) == OMAP_DSP_DEVSTATE_ADDFAIL)  ? "ADDFAIL" :\
-                                                "unknown")
-
 static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
                             char *buf)
 {
@@ -2622,14 +2813,12 @@ int __init dsp_taskmod_init(void)
                return -EINVAL;
        }
        dsp_task_class = class_create(THIS_MODULE, "dsptask");
-       devfs_mk_dir("dsptask");
 
        return 0;
 }
 
 void dsp_taskmod_exit(void)
 {
-       devfs_remove("dsptask");
        class_destroy(dsp_task_class);
        driver_unregister(&dsptask_driver);
        bus_unregister(&dsptask_bus);
index fb96c78494618c4ff586250d8f66ecf8f4912448..b09c59d51d8bc67298d3e7f316fea6075022e0e9 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2004/12/01:  DSP Gateway version 3.2
+ * 200%/05/16:  DSP Gateway version 3.3
  */
 
 #include <linux/module.h>
@@ -83,7 +83,12 @@ static ssize_t dsp_twch_read(struct file *file, char *buf, size_t count,
        count = devcount * sizeof(long);
        change_cnt = 0;
        for (i = 0; i < devcount; i++) {
-               taskstat[i] = taskdev_state(i);
+               /*
+                * once the device state is read, the 'STALE' bit will be set
+                * so that the Dynamic Loader can distinguish the new request
+                * from the old one.
+                */
+               taskstat[i] = taskdev_state_stale(i);
        }
 
        if (copy_to_user(buf, taskstat, count))
index 07639038d29925174f8a068028b02ac012d892a2..3257b705064f8a490ca01d797d09aaa743ea2eb7 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2004/06/29:  DSP Gateway version 3.2
+ * 2004/06/29:  DSP Gateway version 3.3
  */
 
 #include <linux/linkage.h>
index d1f445340bd4aa891a3cf87fdbedc19f6359a0de..2217a1042e50a79c7c525c0d9aa65fdd0f0b3ab3 100644 (file)
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2004/06/29:  DSP Gateway version 3.2
+ * 2004/06/29:  DSP Gateway version 3.3
  */
 
 #ifndef _OMAP_DSP_UACCESS_DSP_H
index f4fc4a87c2980a2f0750497d681f41f239321d99..51b8a5bcc7c9a0055ae7ec1d785e3b3f3c792ce7 100644 (file)
@@ -191,7 +191,7 @@ static int omap_mcbsp_check(unsigned int id)
 static void omap_mcbsp_dsp_request(void)
 {
        if (cpu_is_omap1510() || cpu_is_omap16xx()) {
-               omap_dsp_request_idle();
+               omap_dsp_request_mem();
                clk_use(mcbsp_dsp_ck);
                clk_use(mcbsp_api_ck);
 
@@ -210,6 +210,7 @@ static void omap_mcbsp_dsp_request(void)
 static void omap_mcbsp_dsp_free(void)
 {
        if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+               omap_dsp_release_mem();
                clk_unuse(mcbsp_dspxor_ck);
                clk_unuse(mcbsp_dsp_ck);
                clk_unuse(mcbsp_api_ck);
index a4a17ba1514f3eee36da3e550e191ed30d6a6afe..57bf4f39ca580db55612fca034381eb7e999c814 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2005/01/17:  DSP Gateway version 3.2
+ * 2005/06/01:  DSP Gateway version 3.3
  */
 
 #ifndef ASM_ARCH_DSP_H
 #define OMAP_DSP_IOCTL_RESET                   1
 #define OMAP_DSP_IOCTL_RUN                     2
 #define OMAP_DSP_IOCTL_SETRSTVECT              3
-#define OMAP_DSP_IOCTL_IDLE                    4
+#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
@@ -97,8 +99,12 @@ struct omap_dsp_mapinfo {
 #define OMAP_DSP_DEVSTATE_INVALID      0x00000008
 #define OMAP_DSP_DEVSTATE_ADDREQ       0x00000100
 #define OMAP_DSP_DEVSTATE_DELREQ       0x00000200
-#define OMAP_DSP_DEVSTATE_KILLREQ      0x00000400
 #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;
@@ -133,7 +139,7 @@ struct omap_dsp_varinfo {
        unsigned short val[0];
 };
 
-#define OMAP_DSP_MBPROT_REVISION       0x0018
+#define OMAP_DSP_MBPROT_REVISION       0x0019
 
 #define OMAP_DSP_MBCMD_WDSND   0x10
 #define OMAP_DSP_MBCMD_WDREQ   0x11
@@ -144,7 +150,8 @@ struct omap_dsp_varinfo {
 #define OMAP_DSP_MBCMD_BKREQP  0x25
 #define OMAP_DSP_MBCMD_TCTL    0x30
 #define OMAP_DSP_MBCMD_TCTLDATA        0x31
-#define OMAP_DSP_MBCMD_WDT     0x50
+#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
@@ -217,6 +224,7 @@ struct omap_dsp_varinfo {
 #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
index 9931e325ebc0b3d921c7108cfd20bf5b2ca9062f..4fcce6944056e4f1377735a010783be986f583ac 100644 (file)
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * 2004/09/22:  DSP Gateway version 3.2
+ * 2005/06/03:  DSP Gateway version 3.3
  */
 
 #ifndef ASM_ARCH_DSP_COMMON_H
@@ -29,6 +29,9 @@
 
 void omap_dsp_pm_suspend(void);
 void omap_dsp_pm_resume(void);
-void omap_dsp_request_idle(void);
+void omap_dsp_request_mpui(void);
+void omap_dsp_release_mpui(void);
+int omap_dsp_request_mem(void);
+int omap_dsp_release_mem(void);
 
 #endif /* ASM_ARCH_DSP_COMMON_H */