* [PATCH 1/2] DSP: Move code to use only one dsp_common.h
@ 2007-11-28 5:18 Tony Lindgren
2007-11-28 5:20 ` [PATCH 2/2] DSP: Move dspgateway to drivers/dsp/dspgateway Tony Lindgren
2007-11-28 9:54 ` [PATCH 1/2] DSP: Move code to use only one dsp_common.h Hiroshi DOYU
0 siblings, 2 replies; 11+ messages in thread
From: Tony Lindgren @ 2007-11-28 5:18 UTC (permalink / raw)
To: linux-omap, linux-omap-open-source; +Cc: Hiroshi DOYU
[-- Attachment #1: Type: text/plain, Size: 324 bytes --]
Hi all,
As discussed earlier, here are the patches to move dspgateway
to under drivers.
Hiroshi san & Toshihiro san, can you take a quick look at these
two patches and ack?
I've only compile tested on osk and n800. There should not be any
functional changes. Some inline functions I had to export though.
Regards,
Tony
[-- Attachment #2: 0001-DSP-Move-code-to-use-only-one-dsp_common.h.patch --]
[-- Type: text/x-diff, Size: 23329 bytes --]
>From a4945cb4c9427fd5bcf699607bab1d9cc9f32dae Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Tue, 27 Nov 2007 20:37:53 -0800
Subject: [PATCH] DSP: Move code to use only one dsp_common.h
Remove arch-arm/plat-omap/dsp/dsp_common.h, and move
definitions to include/asm-arm/arch-omap/dsp_common.h.
This is done in order to prepare dsp for moving to live
under drivers. No functional changes.
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap1/board-nokia770.c | 3 +-
arch/arm/mach-omap1/mmu.c | 2 +
arch/arm/mach-omap1/mmu.h | 3 -
arch/arm/mach-omap1/pm.c | 1 -
arch/arm/mach-omap2/board-n800-audio.c | 2 +-
arch/arm/mach-omap2/board-n800-dsp.c | 3 +-
arch/arm/mach-omap2/mmu.h | 3 -
arch/arm/plat-omap/devices.c | 3 +-
arch/arm/plat-omap/dsp/dsp.h | 144 +++++++++++++++++++-
arch/arm/plat-omap/dsp/dsp_common.c | 4 +-
arch/arm/plat-omap/dsp/dsp_common.h | 241 --------------------------------
arch/arm/plat-omap/dsp/dsp_core.c | 37 +++++-
arch/arm/plat-omap/dsp/uaccess_dsp.h | 3 +-
arch/arm/plat-omap/mcbsp.c | 2 +-
arch/arm/plat-omap/mmu.c | 1 +
include/asm-arm/arch-omap/dsp_common.h | 39 +++++
16 files changed, 231 insertions(+), 260 deletions(-)
delete mode 100644 arch/arm/plat-omap/dsp/dsp_common.h
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index da0b90f..54502b1 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -36,8 +36,7 @@
#include <asm/arch/omapfb.h>
#include <asm/arch/hwa742.h>
#include <asm/arch/lcd_mipid.h>
-
-#include "../plat-omap/dsp/dsp_common.h"
+#include <asm/arch/dsp_common.h>
#define ADS7846_PENDOWN_GPIO 15
diff --git a/arch/arm/mach-omap1/mmu.c b/arch/arm/mach-omap1/mmu.c
index f1b682a..a254410 100644
--- a/arch/arm/mach-omap1/mmu.c
+++ b/arch/arm/mach-omap1/mmu.c
@@ -32,6 +32,8 @@
#include <linux/err.h>
#include "mmu.h"
#include <asm/tlbflush.h>
+#include <asm/arch/dsp.h>
+#include <asm/arch/dsp_common.h>
static void *dspvect_page;
#define DSP_INIT_PAGE 0xfff000
diff --git a/arch/arm/mach-omap1/mmu.h b/arch/arm/mach-omap1/mmu.h
index 75966b2..9ab2d99 100644
--- a/arch/arm/mach-omap1/mmu.h
+++ b/arch/arm/mach-omap1/mmu.h
@@ -118,9 +118,6 @@ static inline void omap_mmu_write_reg(struct omap_mmu *mmu,
__raw_writew(val, mmu->base + reg);
}
-int omap_dsp_request_mem(void);
-void omap_dsp_release_mem(void);
-
static inline void omap_mmu_itack(struct omap_mmu *mmu)
{
omap_mmu_write_reg(mmu, OMAP_MMU_IT_ACK_IT_ACK, OMAP_MMU_IT_ACK);
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 10aa872..afc4874 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -57,7 +57,6 @@
#include <asm/arch/pm.h>
#include <asm/arch/mux.h>
#include <asm/arch/dma.h>
-#include <asm/arch/dsp_common.h>
#include <asm/arch/dmtimer.h>
static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
diff --git a/arch/arm/mach-omap2/board-n800-audio.c b/arch/arm/mach-omap2/board-n800-audio.c
index 5940f61..75c4e4e 100644
--- a/arch/arm/mach-omap2/board-n800-audio.c
+++ b/arch/arm/mach-omap2/board-n800-audio.c
@@ -29,7 +29,7 @@
#include <asm/io.h>
#include <asm/arch/eac.h>
-#include "../plat-omap/dsp/dsp_common.h"
+#include <asm/arch/dsp_common.h>
#if defined(CONFIG_SPI_TSC2301_AUDIO) && defined(CONFIG_SND_OMAP24XX_EAC)
#define AUDIO_ENABLED
diff --git a/arch/arm/mach-omap2/board-n800-dsp.c b/arch/arm/mach-omap2/board-n800-dsp.c
index b6da02f..d524b62 100644
--- a/arch/arm/mach-omap2/board-n800-dsp.c
+++ b/arch/arm/mach-omap2/board-n800-dsp.c
@@ -30,8 +30,7 @@
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/board.h>
-
-#include "../plat-omap/dsp/dsp_common.h"
+#include <asm/arch/dsp_common.h>
#if defined(CONFIG_OMAP_DSP)
diff --git a/arch/arm/mach-omap2/mmu.h b/arch/arm/mach-omap2/mmu.h
index c4922d1..736932e 100644
--- a/arch/arm/mach-omap2/mmu.h
+++ b/arch/arm/mach-omap2/mmu.h
@@ -59,9 +59,6 @@
#define IOMAP_VAL 0x3f
-#define omap_dsp_request_mem() do { } while (0)
-#define omap_dsp_release_mem() do { } while (0)
-
#define INIT_TLB_ENTRY(ent,v,p,ps) \
do { \
(ent)->va = (v); \
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index c25070b..aa5c6ca 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -25,6 +25,7 @@
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
#include <asm/arch/menelaus.h>
+#include <asm/arch/dsp_common.h>
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
# include "../mach-omap2/control.h"
@@ -32,8 +33,6 @@
#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
-#include "../plat-omap/dsp/dsp_common.h"
-
static struct dsp_platform_data dsp_pdata = {
.kdev_list = LIST_HEAD_INIT(dsp_pdata.kdev_list),
};
diff --git a/arch/arm/plat-omap/dsp/dsp.h b/arch/arm/plat-omap/dsp/dsp.h
index a5512db..a7eee1d 100644
--- a/arch/arm/plat-omap/dsp/dsp.h
+++ b/arch/arm/plat-omap/dsp/dsp.h
@@ -25,9 +25,17 @@
#define __PLAT_OMAP_DSP_DSP_H
#include "hardware_dsp.h"
-#include "dsp_common.h"
+#include <asm/arch/dsp_common.h>
#include <asm/arch/mmu.h>
+
+#ifdef CONFIG_ARCH_OMAP2
+#include "../../mach-omap2/prm.h"
+#include "../../mach-omap2/prm_regbits_24xx.h"
+#include "../../mach-omap2/cm.h"
+#include "../../mach-omap2/cm_regbits_24xx.h"
+#endif
+
/*
* MAJOR device number: !! allocated arbitrary !!
*/
@@ -119,6 +127,8 @@ struct mb_exarg {
u16 *argv;
};
+typedef u32 dsp_long_t; /* must have ability to carry TADD_ABORTADR */
+
extern void dsp_mbox_start(void);
extern void dsp_mbox_stop(void);
extern int dsp_mbox_config(void *p);
@@ -246,4 +256,136 @@ extern struct omap_mmu dsp_mmu;
#define dsp_mem_enable(addr) omap_mmu_mem_enable(&dsp_mmu, (addr))
#define dsp_mem_disable(addr) omap_mmu_mem_disable(&dsp_mmu, (addr))
+#define DSPSPACE_SIZE 0x1000000
+
+#define omap_set_bit_regw(b,r) \
+ do { omap_writew(omap_readw(r) | (b), (r)); } while(0)
+#define omap_clr_bit_regw(b,r) \
+ do { omap_writew(omap_readw(r) & ~(b), (r)); } while(0)
+#define omap_set_bit_regl(b,r) \
+ do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
+#define omap_clr_bit_regl(b,r) \
+ do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
+#define omap_set_bits_regl(val,mask,r) \
+ do { omap_writel((omap_readl(r) & ~(mask)) | (val), (r)); } while(0)
+
+#define dspword_to_virt(dw) ((void *)(dspmem_base + ((dw) << 1)))
+#define dspbyte_to_virt(db) ((void *)(dspmem_base + (db)))
+#define virt_to_dspword(va) \
+ ((dsp_long_t)(((unsigned long)(va) - dspmem_base) >> 1))
+#define virt_to_dspbyte(va) \
+ ((dsp_long_t)((unsigned long)(va) - dspmem_base))
+#define is_dsp_internal_mem(va) \
+ (((unsigned long)(va) >= dspmem_base) && \
+ ((unsigned long)(va) < dspmem_base + dspmem_size))
+#define is_dspbyte_internal_mem(db) ((db) < dspmem_size)
+#define is_dspword_internal_mem(dw) (((dw) << 1) < dspmem_size)
+
+#ifdef CONFIG_ARCH_OMAP1
+/*
+ * MPUI byteswap/wordswap on/off
+ * default setting: wordswap = all, byteswap = APIMEM only
+ */
+#define mpui_wordswap_on() \
+ omap_set_bits_regl(MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL_WORDSWAP_MASK, \
+ MPUI_CTRL)
+
+#define mpui_wordswap_off() \
+ omap_set_bits_regl(MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL_WORDSWAP_MASK, \
+ MPUI_CTRL)
+
+#define mpui_byteswap_on() \
+ omap_set_bits_regl(MPUI_CTRL_BYTESWAP_API, MPUI_CTRL_BYTESWAP_MASK, \
+ MPUI_CTRL)
+
+#define mpui_byteswap_off() \
+ omap_set_bits_regl(MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL_BYTESWAP_MASK, \
+ 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() omap_clr_bit_regl(TC_ENDIANISM_EN, TC_ENDIANISM)
+
+/*
+ * enable priority registers, EMIF, MPUI control logic
+ */
+#define __dsp_enable() omap_set_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
+#define __dsp_disable() omap_clr_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
+#define __dsp_run() omap_set_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
+#define __dsp_reset() omap_clr_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
+#endif /* CONFIG_ARCH_OMAP1 */
+
+#ifdef CONFIG_ARCH_OMAP2
+/*
+ * PRCM / IPI control logic
+ *
+ * REVISIT: these macros should probably be static inline functions
+ */
+#define __dsp_core_enable() \
+ do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
+ & ~OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
+#define __dsp_core_disable() \
+ do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
+ | OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
+#define __dsp_per_enable() \
+ do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
+ & ~OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
+#define __dsp_per_disable() \
+ do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
+ | OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
+#endif /* CONFIG_ARCH_OMAP2 */
+
+#if defined(CONFIG_ARCH_OMAP1)
+extern struct clk *dsp_ck_handle;
+extern struct clk *api_ck_handle;
+#elif defined(CONFIG_ARCH_OMAP2)
+extern struct clk *dsp_fck_handle;
+extern struct clk *dsp_ick_handle;
+#endif
+extern dsp_long_t dspmem_base, dspmem_size,
+ daram_base, daram_size,
+ saram_base, saram_size;
+
+enum cpustat_e {
+ CPUSTAT_RESET = 0,
+#ifdef CONFIG_ARCH_OMAP1
+ CPUSTAT_GBL_IDLE,
+ CPUSTAT_CPU_IDLE,
+#endif
+ CPUSTAT_RUN,
+ CPUSTAT_MAX
+};
+
+int dsp_set_rstvect(dsp_long_t adr);
+dsp_long_t dsp_get_rstvect(void);
+void dsp_set_idle_boot_base(dsp_long_t adr, size_t size);
+void dsp_reset_idle_boot_base(void);
+void dsp_cpustat_request(enum cpustat_e req);
+enum cpustat_e dsp_cpustat_get_stat(void);
+u16 dsp_cpustat_get_icrmask(void);
+void dsp_cpustat_set_icrmask(u16 mask);
+void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void));
+void dsp_unregister_mem_cb(void);
+
+#if defined(CONFIG_ARCH_OMAP1)
+#define command_dvfs_stop(m) (0)
+#define command_dvfs_start(m) (0)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define command_dvfs_stop(m) \
+ (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_STOP))
+#define command_dvfs_start(m) \
+ (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_START))
+#endif
+
+extern struct omap_dsp *omap_dsp;
+
+extern int dsp_late_init(void);
+
#endif /* __PLAT_OMAP_DSP_DSP_H */
diff --git a/arch/arm/plat-omap/dsp/dsp_common.c b/arch/arm/plat-omap/dsp/dsp_common.c
index b7a7ed3..99be995 100644
--- a/arch/arm/plat-omap/dsp/dsp_common.c
+++ b/arch/arm/plat-omap/dsp/dsp_common.c
@@ -33,10 +33,12 @@
#include <asm/io.h>
#include <asm/tlbflush.h>
#include <asm/irq.h>
+#include <asm/arch/dsp_common.h>
+#include "dsp.h"
+
#ifdef CONFIG_ARCH_OMAP1
#include <asm/arch/tc.h>
#endif
-#include "dsp_common.h"
#if defined(CONFIG_ARCH_OMAP1)
#define dsp_boot_config(mode) omap_writew((mode), MPUI_DSP_BOOT_CONFIG)
diff --git a/arch/arm/plat-omap/dsp/dsp_common.h b/arch/arm/plat-omap/dsp/dsp_common.h
deleted file mode 100644
index 2ef1e58..0000000
--- a/arch/arm/plat-omap/dsp/dsp_common.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef DRIVER_DSP_COMMON_H
-#define DRIVER_DSP_COMMON_H
-
-#include <linux/clk.h>
-#include <asm/arch/mmu.h>
-#include "hardware_dsp.h"
-
-#ifdef CONFIG_ARCH_OMAP2
-#include "../../mach-omap2/prm.h"
-#include "../../mach-omap2/prm_regbits_24xx.h"
-#include "../../mach-omap2/cm.h"
-#include "../../mach-omap2/cm_regbits_24xx.h"
-#endif
-
-#define DSPSPACE_SIZE 0x1000000
-
-#define omap_set_bit_regw(b,r) \
- do { omap_writew(omap_readw(r) | (b), (r)); } while(0)
-#define omap_clr_bit_regw(b,r) \
- do { omap_writew(omap_readw(r) & ~(b), (r)); } while(0)
-#define omap_set_bit_regl(b,r) \
- do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
-#define omap_clr_bit_regl(b,r) \
- do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
-#define omap_set_bits_regl(val,mask,r) \
- do { omap_writel((omap_readl(r) & ~(mask)) | (val), (r)); } while(0)
-
-#define dspword_to_virt(dw) ((void *)(dspmem_base + ((dw) << 1)))
-#define dspbyte_to_virt(db) ((void *)(dspmem_base + (db)))
-#define virt_to_dspword(va) \
- ((dsp_long_t)(((unsigned long)(va) - dspmem_base) >> 1))
-#define virt_to_dspbyte(va) \
- ((dsp_long_t)((unsigned long)(va) - dspmem_base))
-#define is_dsp_internal_mem(va) \
- (((unsigned long)(va) >= dspmem_base) && \
- ((unsigned long)(va) < dspmem_base + dspmem_size))
-#define is_dspbyte_internal_mem(db) ((db) < dspmem_size)
-#define is_dspword_internal_mem(dw) (((dw) << 1) < dspmem_size)
-
-#ifdef CONFIG_ARCH_OMAP1
-/*
- * MPUI byteswap/wordswap on/off
- * default setting: wordswap = all, byteswap = APIMEM only
- */
-#define mpui_wordswap_on() \
- omap_set_bits_regl(MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL_WORDSWAP_MASK, \
- MPUI_CTRL)
-
-#define mpui_wordswap_off() \
- omap_set_bits_regl(MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL_WORDSWAP_MASK, \
- MPUI_CTRL)
-
-#define mpui_byteswap_on() \
- omap_set_bits_regl(MPUI_CTRL_BYTESWAP_API, MPUI_CTRL_BYTESWAP_MASK, \
- MPUI_CTRL)
-
-#define mpui_byteswap_off() \
- omap_set_bits_regl(MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL_BYTESWAP_MASK, \
- 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() omap_clr_bit_regl(TC_ENDIANISM_EN, TC_ENDIANISM)
-
-/*
- * enable priority registers, EMIF, MPUI control logic
- */
-#define __dsp_enable() omap_set_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
-#define __dsp_disable() omap_clr_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
-#define __dsp_run() omap_set_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
-#define __dsp_reset() omap_clr_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
-#endif /* CONFIG_ARCH_OMAP1 */
-
-#ifdef CONFIG_ARCH_OMAP2
-/*
- * PRCM / IPI control logic
- *
- * REVISIT: these macros should probably be static inline functions
- */
-#define __dsp_core_enable() \
- do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
- & ~OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
-#define __dsp_core_disable() \
- do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
- | OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
-#define __dsp_per_enable() \
- do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
- & ~OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
-#define __dsp_per_disable() \
- do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
- | OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
-#endif /* CONFIG_ARCH_OMAP2 */
-
-typedef u32 dsp_long_t; /* must have ability to carry TADD_ABORTADR */
-
-#if defined(CONFIG_ARCH_OMAP1)
-extern struct clk *dsp_ck_handle;
-extern struct clk *api_ck_handle;
-#elif defined(CONFIG_ARCH_OMAP2)
-extern struct clk *dsp_fck_handle;
-extern struct clk *dsp_ick_handle;
-#endif
-extern dsp_long_t dspmem_base, dspmem_size,
- daram_base, daram_size,
- saram_base, saram_size;
-
-enum cpustat_e {
- CPUSTAT_RESET = 0,
-#ifdef CONFIG_ARCH_OMAP1
- CPUSTAT_GBL_IDLE,
- CPUSTAT_CPU_IDLE,
-#endif
- CPUSTAT_RUN,
- CPUSTAT_MAX
-};
-
-int dsp_set_rstvect(dsp_long_t adr);
-dsp_long_t dsp_get_rstvect(void);
-void dsp_set_idle_boot_base(dsp_long_t adr, size_t size);
-void dsp_reset_idle_boot_base(void);
-void dsp_cpustat_request(enum cpustat_e req);
-enum cpustat_e dsp_cpustat_get_stat(void);
-u16 dsp_cpustat_get_icrmask(void);
-void dsp_cpustat_set_icrmask(u16 mask);
-void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void));
-void dsp_unregister_mem_cb(void);
-
-#if defined(CONFIG_ARCH_OMAP1)
-static inline void dsp_clk_enable(void) {}
-static inline void dsp_clk_disable(void) {}
-#elif defined(CONFIG_ARCH_OMAP2)
-static inline void dsp_clk_enable(void)
-{
- u32 r;
-
- /*XXX should be handled in mach-omap[1,2] XXX*/
- prm_write_mod_reg(OMAP24XX_FORCESTATE | (1 << OMAP_POWERSTATE_SHIFT),
- OMAP24XX_DSP_MOD, PM_PWSTCTRL);
-
- r = cm_read_mod_reg(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
- r |= OMAP2420_AUTO_DSP_IPI;
- cm_write_mod_reg(r, OMAP24XX_DSP_MOD, CM_AUTOIDLE);
-
- r = cm_read_mod_reg(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
- r |= OMAP24XX_AUTOSTATE_DSP;
- cm_write_mod_reg(r, OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
-
- clk_enable(dsp_fck_handle);
- clk_enable(dsp_ick_handle);
- __dsp_per_enable();
-}
-static inline void dsp_clk_disable(void)
-{
- __dsp_per_disable();
- clk_disable(dsp_ick_handle);
- clk_disable(dsp_fck_handle);
-
- prm_write_mod_reg(OMAP24XX_FORCESTATE | (3 << OMAP_POWERSTATE_SHIFT),
- OMAP24XX_DSP_MOD, PM_PWSTCTRL);
-}
-#endif
-
-struct dsp_kfunc_device {
- char *name;
- struct clk *fck;
- struct clk *ick;;
- spinlock_t lock;
- int enabled;
- int type;
-#define DSP_KFUNC_DEV_TYPE_COMMON 1
-#define DSP_KFUNC_DEV_TYPE_AUDIO 2
-
- struct list_head entry;
-
- int (*probe)(struct dsp_kfunc_device *, int);
- int (*remove)(struct dsp_kfunc_device *, int);
- int (*enable)(struct dsp_kfunc_device *, int);
- int (*disable)(struct dsp_kfunc_device *, int);
-};
-
-extern int dsp_kfunc_device_register(struct dsp_kfunc_device *);
-
-struct dsp_platform_data {
- struct list_head kdev_list;
-};
-
-struct omap_dsp {
- struct mutex lock;
- int enabled; /* stored peripheral status */
- struct omap_mmu *mmu;
- struct omap_mbox *mbox;
- struct device *dev;
- struct list_head *kdev_list;
- int initialized;
-};
-
-#if defined(CONFIG_ARCH_OMAP1)
-#define command_dvfs_stop(m) (0)
-#define command_dvfs_start(m) (0)
-#elif defined(CONFIG_ARCH_OMAP2)
-#define command_dvfs_stop(m) \
- (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_STOP))
-#define command_dvfs_start(m) \
- (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_START))
-#endif
-
-extern struct omap_dsp *omap_dsp;
-
-extern int dsp_late_init(void);
-
-#endif /* DRIVER_DSP_COMMON_H */
diff --git a/arch/arm/plat-omap/dsp/dsp_core.c b/arch/arm/plat-omap/dsp/dsp_core.c
index f3a91d0..05274be 100644
--- a/arch/arm/plat-omap/dsp/dsp_core.c
+++ b/arch/arm/plat-omap/dsp/dsp_core.c
@@ -30,11 +30,11 @@
#include <linux/clk.h>
#include <asm/delay.h>
#include <asm/arch/mailbox.h>
+#include <asm/arch/dsp.h>
#include <asm/arch/dsp_common.h>
#include "dsp_mbcmd.h"
#include "dsp.h"
#include "ipbuf.h"
-#include "dsp_common.h"
MODULE_AUTHOR("Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>");
MODULE_DESCRIPTION("OMAP DSP driver module");
@@ -454,6 +454,41 @@ static void mbox_kfunc(struct mbcmd *mb)
}
}
+#if defined(CONFIG_ARCH_OMAP1)
+static inline void dsp_clk_enable(void) {}
+static inline void dsp_clk_disable(void) {}
+#elif defined(CONFIG_ARCH_OMAP2)
+static inline void dsp_clk_enable(void)
+{
+ u32 r;
+
+ /*XXX should be handled in mach-omap[1,2] XXX*/
+ prm_write_mod_reg(OMAP24XX_FORCESTATE | (1 << OMAP_POWERSTATE_SHIFT),
+ OMAP24XX_DSP_MOD, PM_PWSTCTRL);
+
+ r = cm_read_mod_reg(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
+ r |= OMAP2420_AUTO_DSP_IPI;
+ cm_write_mod_reg(r, OMAP24XX_DSP_MOD, CM_AUTOIDLE);
+
+ r = cm_read_mod_reg(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
+ r |= OMAP24XX_AUTOSTATE_DSP;
+ cm_write_mod_reg(r, OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
+
+ clk_enable(dsp_fck_handle);
+ clk_enable(dsp_ick_handle);
+ __dsp_per_enable();
+}
+static inline void dsp_clk_disable(void)
+{
+ __dsp_per_disable();
+ clk_disable(dsp_ick_handle);
+ clk_disable(dsp_fck_handle);
+
+ prm_write_mod_reg(OMAP24XX_FORCESTATE | (3 << OMAP_POWERSTATE_SHIFT),
+ OMAP24XX_DSP_MOD, PM_PWSTCTRL);
+}
+#endif
+
int dsp_late_init(void)
{
int ret;
diff --git a/arch/arm/plat-omap/dsp/uaccess_dsp.h b/arch/arm/plat-omap/dsp/uaccess_dsp.h
index 9291930..028814f 100644
--- a/arch/arm/plat-omap/dsp/uaccess_dsp.h
+++ b/arch/arm/plat-omap/dsp/uaccess_dsp.h
@@ -25,7 +25,8 @@
#define _OMAP_DSP_UACCESS_DSP_H
#include <asm/uaccess.h>
-#include "dsp_common.h"
+#include <asm/arch/dsp_common.h>
+#include "dsp.h"
#define HAVE_ASM_COPY_FROM_USER_DSP_2B
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index f2ebad2..a17b5ae 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -28,8 +28,8 @@
#include <asm/arch/dma.h>
#include <asm/arch/mux.h>
#include <asm/arch/irqs.h>
-#include <asm/arch/dsp_common.h>
#include <asm/arch/mcbsp.h>
+#include <asm/arch/dsp_common.h>
#ifdef CONFIG_MCBSP_DEBUG
#define DBG(x...) printk(x)
diff --git a/arch/arm/plat-omap/mmu.c b/arch/arm/plat-omap/mmu.c
index 890a9c8..c92afd6 100644
--- a/arch/arm/plat-omap/mmu.c
+++ b/arch/arm/plat-omap/mmu.c
@@ -38,6 +38,7 @@
#include <asm/pgtable.h>
#include <asm/arch/mmu.h>
#include <asm/sizes.h>
+#include <asm/arch/dsp_common.h>
#if defined(CONFIG_ARCH_OMAP1)
#include "../mach-omap1/mmu.h"
diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h
index c61f868..a11deed 100644
--- a/include/asm-arm/arch-omap/dsp_common.h
+++ b/include/asm-arm/arch-omap/dsp_common.h
@@ -24,11 +24,50 @@
#ifndef ASM_ARCH_DSP_COMMON_H
#define ASM_ARCH_DSP_COMMON_H
+#include <linux/clk.h>
+
+struct dsp_kfunc_device {
+ char *name;
+ struct clk *fck;
+ struct clk *ick;;
+ spinlock_t lock;
+ int enabled;
+ int type;
+#define DSP_KFUNC_DEV_TYPE_COMMON 1
+#define DSP_KFUNC_DEV_TYPE_AUDIO 2
+
+ struct list_head entry;
+
+ int (*probe)(struct dsp_kfunc_device *, int);
+ int (*remove)(struct dsp_kfunc_device *, int);
+ int (*enable)(struct dsp_kfunc_device *, int);
+ int (*disable)(struct dsp_kfunc_device *, int);
+};
+
+extern int dsp_kfunc_device_register(struct dsp_kfunc_device *);
+
+struct dsp_platform_data {
+ struct list_head kdev_list;
+};
+
+struct omap_dsp {
+ struct mutex lock;
+ int enabled; /* stored peripheral status */
+ struct omap_mmu *mmu;
+ struct omap_mbox *mbox;
+ struct device *dev;
+ struct list_head *kdev_list;
+ int initialized;
+};
+
#ifdef CONFIG_ARCH_OMAP1
extern void omap_dsp_request_mpui(void);
extern void omap_dsp_release_mpui(void);
extern int omap_dsp_request_mem(void);
extern int omap_dsp_release_mem(void);
+#elif defined(CONFIG_ARCH_OMAP2)
+#define omap_dsp_request_mem() do { } while (0)
+#define omap_dsp_release_mem() do { } while (0)
#endif
#endif /* ASM_ARCH_DSP_COMMON_H */
--
1.5.3.6.GIT
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] DSP: Move dspgateway to drivers/dsp/dspgateway
2007-11-28 5:18 [PATCH 1/2] DSP: Move code to use only one dsp_common.h Tony Lindgren
@ 2007-11-28 5:20 ` Tony Lindgren
2007-11-28 9:54 ` [PATCH 1/2] DSP: Move code to use only one dsp_common.h Hiroshi DOYU
1 sibling, 0 replies; 11+ messages in thread
From: Tony Lindgren @ 2007-11-28 5:20 UTC (permalink / raw)
To: linux-omap, linux-omap-open-source; +Cc: Hiroshi DOYU
[-- Attachment #1: Type: text/plain, Size: 56 bytes --]
This patch does the actual moving of the files.
Tony
[-- Attachment #2: 0002-DSP-Move-dspgateway-to-drivers-dsp-dspgateway.patch --]
[-- Type: text/x-diff, Size: 452102 bytes --]
>From c43c710df9b75494ce931f8e4b730a7f54d56d05 Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Tue, 27 Nov 2007 21:13:02 -0800
Subject: [PATCH] DSP: Move dspgateway to drivers/dsp/dspgateway
Move dspgateway to drivers/dsp/dspgateway
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/Kconfig | 1 +
arch/arm/mach-omap1/mmu.c | 6 +
arch/arm/mach-omap1/mmu.h | 7 -
arch/arm/mach-omap2/mmu.h | 6 +-
arch/arm/plat-omap/Kconfig | 2 -
arch/arm/plat-omap/Makefile | 3 -
arch/arm/plat-omap/dsp/Kconfig | 24 -
arch/arm/plat-omap/dsp/Makefile | 15 -
arch/arm/plat-omap/dsp/dsp.h | 391 -----
arch/arm/plat-omap/dsp/dsp_common.c | 627 -------
arch/arm/plat-omap/dsp/dsp_core.c | 663 -------
arch/arm/plat-omap/dsp/dsp_ctl.c | 1069 ------------
arch/arm/plat-omap/dsp/dsp_ctl_core.c | 132 --
arch/arm/plat-omap/dsp/dsp_mbcmd.h | 147 --
arch/arm/plat-omap/dsp/dsp_mem.c | 482 ------
arch/arm/plat-omap/dsp/error.c | 227 ---
arch/arm/plat-omap/dsp/hardware_dsp.h | 34 -
arch/arm/plat-omap/dsp/ipbuf.c | 353 ----
arch/arm/plat-omap/dsp/ipbuf.h | 193 ---
arch/arm/plat-omap/dsp/mblog.c | 280 ---
arch/arm/plat-omap/dsp/mmu.h | 140 --
arch/arm/plat-omap/dsp/omap1_dsp.h | 114 --
arch/arm/plat-omap/dsp/omap2_dsp.h | 95 -
arch/arm/plat-omap/dsp/proclist.h | 87 -
arch/arm/plat-omap/dsp/task.c | 3042 ---------------------------------
arch/arm/plat-omap/dsp/taskwatch.c | 163 --
arch/arm/plat-omap/dsp/uaccess_dsp.S | 77 -
arch/arm/plat-omap/dsp/uaccess_dsp.h | 176 --
drivers/Makefile | 1 +
drivers/dsp/dspgateway/Kconfig | 24 +
drivers/dsp/dspgateway/Makefile | 15 +
drivers/dsp/dspgateway/dsp.h | 391 +++++
drivers/dsp/dspgateway/dsp_common.c | 627 +++++++
drivers/dsp/dspgateway/dsp_core.c | 663 +++++++
drivers/dsp/dspgateway/dsp_ctl.c | 1069 ++++++++++++
drivers/dsp/dspgateway/dsp_ctl_core.c | 132 ++
drivers/dsp/dspgateway/dsp_mbcmd.h | 147 ++
drivers/dsp/dspgateway/dsp_mem.c | 484 ++++++
drivers/dsp/dspgateway/error.c | 227 +++
drivers/dsp/dspgateway/hardware_dsp.h | 34 +
drivers/dsp/dspgateway/ipbuf.c | 353 ++++
drivers/dsp/dspgateway/ipbuf.h | 193 +++
drivers/dsp/dspgateway/mblog.c | 280 +++
drivers/dsp/dspgateway/mmu.h | 140 ++
drivers/dsp/dspgateway/omap1_dsp.h | 114 ++
drivers/dsp/dspgateway/omap2_dsp.h | 95 +
drivers/dsp/dspgateway/proclist.h | 87 +
drivers/dsp/dspgateway/task.c | 3042 +++++++++++++++++++++++++++++++++
drivers/dsp/dspgateway/taskwatch.c | 163 ++
drivers/dsp/dspgateway/uaccess_dsp.S | 77 +
drivers/dsp/dspgateway/uaccess_dsp.h | 176 ++
include/asm-arm/arch-omap/mmu.h | 10 +
52 files changed, 8552 insertions(+), 8548 deletions(-)
delete mode 100644 arch/arm/plat-omap/dsp/Kconfig
delete mode 100644 arch/arm/plat-omap/dsp/Makefile
delete mode 100644 arch/arm/plat-omap/dsp/dsp.h
delete mode 100644 arch/arm/plat-omap/dsp/dsp_common.c
delete mode 100644 arch/arm/plat-omap/dsp/dsp_core.c
delete mode 100644 arch/arm/plat-omap/dsp/dsp_ctl.c
delete mode 100644 arch/arm/plat-omap/dsp/dsp_ctl_core.c
delete mode 100644 arch/arm/plat-omap/dsp/dsp_mbcmd.h
delete mode 100644 arch/arm/plat-omap/dsp/dsp_mem.c
delete mode 100644 arch/arm/plat-omap/dsp/error.c
delete mode 100644 arch/arm/plat-omap/dsp/hardware_dsp.h
delete mode 100644 arch/arm/plat-omap/dsp/ipbuf.c
delete mode 100644 arch/arm/plat-omap/dsp/ipbuf.h
delete mode 100644 arch/arm/plat-omap/dsp/mblog.c
delete mode 100644 arch/arm/plat-omap/dsp/mmu.h
delete mode 100644 arch/arm/plat-omap/dsp/omap1_dsp.h
delete mode 100644 arch/arm/plat-omap/dsp/omap2_dsp.h
delete mode 100644 arch/arm/plat-omap/dsp/proclist.h
delete mode 100644 arch/arm/plat-omap/dsp/task.c
delete mode 100644 arch/arm/plat-omap/dsp/taskwatch.c
delete mode 100644 arch/arm/plat-omap/dsp/uaccess_dsp.S
delete mode 100644 arch/arm/plat-omap/dsp/uaccess_dsp.h
create mode 100644 drivers/dsp/dspgateway/Kconfig
create mode 100644 drivers/dsp/dspgateway/Makefile
create mode 100644 drivers/dsp/dspgateway/dsp.h
create mode 100644 drivers/dsp/dspgateway/dsp_common.c
create mode 100644 drivers/dsp/dspgateway/dsp_core.c
create mode 100644 drivers/dsp/dspgateway/dsp_ctl.c
create mode 100644 drivers/dsp/dspgateway/dsp_ctl_core.c
create mode 100644 drivers/dsp/dspgateway/dsp_mbcmd.h
create mode 100644 drivers/dsp/dspgateway/dsp_mem.c
create mode 100644 drivers/dsp/dspgateway/error.c
create mode 100644 drivers/dsp/dspgateway/hardware_dsp.h
create mode 100644 drivers/dsp/dspgateway/ipbuf.c
create mode 100644 drivers/dsp/dspgateway/ipbuf.h
create mode 100644 drivers/dsp/dspgateway/mblog.c
create mode 100644 drivers/dsp/dspgateway/mmu.h
create mode 100644 drivers/dsp/dspgateway/omap1_dsp.h
create mode 100644 drivers/dsp/dspgateway/omap2_dsp.h
create mode 100644 drivers/dsp/dspgateway/proclist.h
create mode 100644 drivers/dsp/dspgateway/task.c
create mode 100644 drivers/dsp/dspgateway/taskwatch.c
create mode 100644 drivers/dsp/dspgateway/uaccess_dsp.S
create mode 100644 drivers/dsp/dspgateway/uaccess_dsp.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d589397..f468fee 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1081,6 +1081,7 @@ source "drivers/dma/Kconfig"
if ARCH_OMAP
source "drivers/cbus/Kconfig"
+source "drivers/dsp/dspgateway/Kconfig"
endif
endmenu
diff --git a/arch/arm/mach-omap1/mmu.c b/arch/arm/mach-omap1/mmu.c
index a254410..c7cb4ff 100644
--- a/arch/arm/mach-omap1/mmu.c
+++ b/arch/arm/mach-omap1/mmu.c
@@ -81,6 +81,12 @@ void dsp_mem_usecount_clear(void)
}
EXPORT_SYMBOL_GPL(dsp_mem_usecount_clear);
+void omap_mmu_itack(struct omap_mmu *mmu)
+{
+ omap_mmu_write_reg(mmu, OMAP_MMU_IT_ACK_IT_ACK, OMAP_MMU_IT_ACK);
+}
+EXPORT_SYMBOL(omap_mmu_itack);
+
static int omap1_mmu_mem_enable(struct omap_mmu *mmu, void *addr)
{
int ret = 0;
diff --git a/arch/arm/mach-omap1/mmu.h b/arch/arm/mach-omap1/mmu.h
index 9ab2d99..521c3bf 100644
--- a/arch/arm/mach-omap1/mmu.h
+++ b/arch/arm/mach-omap1/mmu.h
@@ -95,8 +95,6 @@ do { \
(ent)->ap = OMAP_MMU_RAM_L_AP_FA; \
} while (0)
-extern struct omap_mmu_ops omap1_mmu_ops;
-
struct omap_mmu_tlb_entry {
unsigned long va;
unsigned long pa;
@@ -118,9 +116,4 @@ static inline void omap_mmu_write_reg(struct omap_mmu *mmu,
__raw_writew(val, mmu->base + reg);
}
-static inline void omap_mmu_itack(struct omap_mmu *mmu)
-{
- omap_mmu_write_reg(mmu, OMAP_MMU_IT_ACK_IT_ACK, OMAP_MMU_IT_ACK);
-}
-
#endif /* __MACH_OMAP1_MMU_H */
diff --git a/arch/arm/mach-omap2/mmu.h b/arch/arm/mach-omap2/mmu.h
index 736932e..818ea8c 100644
--- a/arch/arm/mach-omap2/mmu.h
+++ b/arch/arm/mach-omap2/mmu.h
@@ -93,8 +93,6 @@ do { \
(ent)->mixed = 0; \
} while (0)
-extern struct omap_mmu_ops omap2_mmu_ops;
-
struct omap_mmu_tlb_entry {
unsigned long va;
unsigned long pa;
@@ -115,7 +113,5 @@ static inline void omap_mmu_write_reg(struct omap_mmu *mmu,
{
__raw_writel(val, mmu->base + reg);
}
-static inline void omap_mmu_itack(struct omap_mmu *mmu)
-{
-}
+
#endif /* __MACH_OMAP2_MMU_H */
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index d1558df..3cb9545 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -211,8 +211,6 @@ config OMAP_SERIAL_WAKE
to data on the serial RX line. This allows you to wake the
system from serial console.
-source "arch/arm/plat-omap/dsp/Kconfig"
-
endmenu
endif
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 4eaef7e..c1ada8f 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -32,6 +32,3 @@ obj-$(CONFIG_OMAP_MMU_FWK) += mmu.o
# OMAP mailbox framework
obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
-# DSP subsystem
-obj-y += dsp/
-obj-$(CONFIG_OMAP_DSP) += mailbox.o
diff --git a/arch/arm/plat-omap/dsp/Kconfig b/arch/arm/plat-omap/dsp/Kconfig
deleted file mode 100644
index 122164a..0000000
--- a/arch/arm/plat-omap/dsp/Kconfig
+++ /dev/null
@@ -1,24 +0,0 @@
-
-config OMAP_DSP
- tristate "OMAP DSP driver (DSP Gateway)"
- depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP24XX
- select OMAP_MMU_FWK
- select OMAP_MBOX_FWK
- help
- This enables OMAP DSP driver, DSP Gateway.
-
-config OMAP_DSP_MBCMD_VERBOSE
- bool "Mailbox Command Verbose LOG"
- depends on OMAP_DSP
- help
- This enables kernel log output in the Mailbox command exchanges
- in the DSP Gateway driver.
-
-config OMAP_DSP_FBEXPORT
- bool "Framebuffer export to DSP"
- depends on OMAP_DSP && FB
- help
- This enables to map the frame buffer to DSP.
- By doing this, DSP can access the frame buffer directly without
- bothering ARM.
-
diff --git a/arch/arm/plat-omap/dsp/Makefile b/arch/arm/plat-omap/dsp/Makefile
deleted file mode 100644
index c7d86f3..0000000
--- a/arch/arm/plat-omap/dsp/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# Makefile for the OMAP DSP driver.
-#
-
-# The target object and module list name.
-
-obj-y := dsp_common.o
-
-obj-$(CONFIG_OMAP_DSP) += dsp.o
-
-# Declare multi-part drivers
-
-dsp-objs := dsp_core.o ipbuf.o mblog.o task.o \
- dsp_ctl_core.o dsp_ctl.o taskwatch.o error.o dsp_mem.o \
- uaccess_dsp.o
diff --git a/arch/arm/plat-omap/dsp/dsp.h b/arch/arm/plat-omap/dsp/dsp.h
deleted file mode 100644
index a7eee1d..0000000
--- a/arch/arm/plat-omap/dsp/dsp.h
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __PLAT_OMAP_DSP_DSP_H
-#define __PLAT_OMAP_DSP_DSP_H
-
-#include "hardware_dsp.h"
-#include <asm/arch/dsp_common.h>
-#include <asm/arch/mmu.h>
-
-
-#ifdef CONFIG_ARCH_OMAP2
-#include "../../mach-omap2/prm.h"
-#include "../../mach-omap2/prm_regbits_24xx.h"
-#include "../../mach-omap2/cm.h"
-#include "../../mach-omap2/cm_regbits_24xx.h"
-#endif
-
-/*
- * MAJOR device number: !! allocated arbitrary !!
- */
-#define OMAP_DSP_CTL_MAJOR 96
-#define OMAP_DSP_TASK_MAJOR 97
-
-#define OLD_BINARY_SUPPORT y
-
-#ifdef OLD_BINARY_SUPPORT
-#define MBREV_3_0 0x0017
-#define MBREV_3_2 0x0018
-#endif
-
-#define DSP_INIT_PAGE 0xfff000
-
-#ifdef CONFIG_ARCH_OMAP1
-/* idle program will be placed at IDLEPG_BASE. */
-#define IDLEPG_BASE 0xfffe00
-#define IDLEPG_SIZE 0x100
-#endif /* CONFIG_ARCH_OMAP1 */
-
-/* timeout value for DSP response */
-#define DSP_TIMEOUT (10 * HZ)
-
-enum dsp_mem_type_e {
- MEM_TYPE_CROSSING = -1,
- MEM_TYPE_NONE = 0,
- MEM_TYPE_DARAM,
- MEM_TYPE_SARAM,
- MEM_TYPE_EXTERN,
-};
-
-
-typedef int __bitwise arm_dsp_dir_t;
-#define DIR_A2D ((__force arm_dsp_dir_t) 1)
-#define DIR_D2A ((__force arm_dsp_dir_t) 2)
-
-enum cfgstat_e {
- CFGSTAT_CLEAN = 0,
- CFGSTAT_READY,
- CFGSTAT_SUSPEND,
- CFGSTAT_RESUME, /* request only */
- CFGSTAT_MAX
-};
-
-enum errcode_e {
- ERRCODE_WDT = 0,
- ERRCODE_MMU,
- ERRCODE_MAX
-};
-
-/* keep 2 entries for TID_FREE and TID_ANON */
-#define TASKDEV_MAX 254
-
-#define MK32(uw,lw) (((u32)(uw)) << 16 | (lw))
-#define MKLONG(uw,lw) (((unsigned long)(uw)) << 16 | (lw))
-#define MKVIRT(uw,lw) dspword_to_virt(MKLONG((uw), (lw)));
-
-struct sync_seq {
- u16 da_dsp;
- u16 da_arm;
- u16 ad_dsp;
- u16 ad_arm;
-};
-
-struct mem_sync_struct {
- struct sync_seq *DARAM;
- struct sync_seq *SARAM;
- struct sync_seq *SDRAM;
-};
-
-/* struct mbcmd and union mbcmd_hw must be compatible */
-struct mbcmd {
- u32 data:16;
- u32 cmd_l:8;
- u32 cmd_h:7;
- u32 seq:1;
-};
-
-#define MBCMD_INIT(h, l, d) { \
- .cmd_h = (h), \
- .cmd_l = (l), \
- .data = (d), \
- }
-
-struct mb_exarg {
- u8 tid;
- int argc;
- u16 *argv;
-};
-
-typedef u32 dsp_long_t; /* must have ability to carry TADD_ABORTADR */
-
-extern void dsp_mbox_start(void);
-extern void dsp_mbox_stop(void);
-extern int dsp_mbox_config(void *p);
-extern int sync_with_dsp(u16 *syncwd, u16 tid, int try_cnt);
-extern int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
- int recovery_flag);
-#define dsp_mbcmd_send(mb) __dsp_mbcmd_send_exarg((mb), NULL, 0)
-#define dsp_mbcmd_send_exarg(mb, arg) __dsp_mbcmd_send_exarg((mb), (arg), 0)
-extern int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg,
- wait_queue_head_t *q);
-#define dsp_mbcmd_send_and_wait(mb, q) \
- dsp_mbcmd_send_and_wait_exarg((mb), NULL, (q))
-
-static inline int __mbcompose_send_exarg(u8 cmd_h, u8 cmd_l, u16 data,
- struct mb_exarg *arg,
- int recovery_flag)
-{
- struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
- return __dsp_mbcmd_send_exarg(&mb, arg, recovery_flag);
-}
-#define mbcompose_send(cmd_h, cmd_l, data) \
- __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 0)
-#define mbcompose_send_exarg(cmd_h, cmd_l, data, arg) \
- __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), arg, 0)
-#define mbcompose_send_recovery(cmd_h, cmd_l, data) \
- __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 1)
-
-static inline int __mbcompose_send_and_wait_exarg(u8 cmd_h, u8 cmd_l,
- u16 data,
- struct mb_exarg *arg,
- wait_queue_head_t *q)
-{
- struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
- return dsp_mbcmd_send_and_wait_exarg(&mb, arg, q);
-}
-#define mbcompose_send_and_wait(cmd_h, cmd_l, data, q) \
- __mbcompose_send_and_wait_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), \
- NULL, (q))
-#define mbcompose_send_and_wait_exarg(cmd_h, cmd_l, data, arg, q) \
- __mbcompose_send_and_wait_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), \
- (arg), (q))
-
-extern struct ipbuf_head *bid_to_ipbuf(u16 bid);
-extern void ipbuf_start(void);
-extern void ipbuf_stop(void);
-extern int ipbuf_config(u16 ln, u16 lsz, void *base);
-extern int ipbuf_sys_config(void *p, arm_dsp_dir_t dir);
-extern int ipbuf_p_validate(void *p, arm_dsp_dir_t dir);
-extern struct ipbuf_head *get_free_ipbuf(u8 tid);
-extern void release_ipbuf(struct ipbuf_head *ipb_h);
-extern void balance_ipbuf(void);
-extern void unuse_ipbuf(struct ipbuf_head *ipb_h);
-extern void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h);
-
-#define release_ipbuf_pvt(ipbuf_pvt) \
- do { \
- (ipbuf_pvt)->s = TID_FREE; \
- } while(0)
-
-extern int mbox_revision;
-
-extern int dsp_cfgstat_request(enum cfgstat_e st);
-extern enum cfgstat_e dsp_cfgstat_get_stat(void);
-extern int dsp_set_runlevel(u8 level);
-
-extern int dsp_task_config_all(u8 n);
-extern void dsp_task_unconfig_all(void);
-extern u8 dsp_task_count(void);
-extern int dsp_taskmod_busy(void);
-extern int dsp_mkdev(char *name);
-extern int dsp_rmdev(char *name);
-extern int dsp_tadd_minor(unsigned char minor, dsp_long_t adr);
-extern int dsp_tdel_minor(unsigned char minor);
-extern int dsp_tkill_minor(unsigned char minor);
-extern long taskdev_state_stale(unsigned char minor);
-extern int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz);
-extern void dsp_dbg_stop(void);
-
-extern int ipbuf_is_held(u8 tid, u16 bid);
-
-extern int dsp_mem_sync_inc(void);
-extern int dsp_mem_sync_config(struct mem_sync_struct *sync);
-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, ...);
-#ifdef CONFIG_ARCH_OMAP1
-extern void dsp_mem_usecount_clear(void);
-#endif
-extern void exmap_use(void *vadr, size_t len);
-extern void exmap_unuse(void *vadr, size_t len);
-extern unsigned long dsp_virt_to_phys(void *vadr, size_t *len);
-extern void dsp_mem_start(void);
-extern void dsp_mem_stop(void);
-
-extern void dsp_twch_start(void);
-extern void dsp_twch_stop(void);
-extern void dsp_twch_touch(void);
-
-extern void dsp_err_start(void);
-extern void dsp_err_stop(void);
-extern void dsp_err_set(enum errcode_e code, unsigned long arg);
-extern void dsp_err_clear(enum errcode_e code);
-extern int dsp_err_isset(enum errcode_e code);
-
-enum cmd_l_type_e {
- CMD_L_TYPE_NULL,
- CMD_L_TYPE_TID,
- CMD_L_TYPE_SUBCMD,
-};
-
-struct cmdinfo {
- char *name;
- enum cmd_l_type_e cmd_l_type;
- void (*handler)(struct mbcmd *mb);
-};
-
-extern const struct cmdinfo *cmdinfo[];
-
-#define cmd_name(mb) (cmdinfo[(mb).cmd_h]->name)
-extern char *subcmd_name(struct mbcmd *mb);
-
-extern void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir);
-
-extern struct omap_mmu dsp_mmu;
-
-#define dsp_mem_enable(addr) omap_mmu_mem_enable(&dsp_mmu, (addr))
-#define dsp_mem_disable(addr) omap_mmu_mem_disable(&dsp_mmu, (addr))
-
-#define DSPSPACE_SIZE 0x1000000
-
-#define omap_set_bit_regw(b,r) \
- do { omap_writew(omap_readw(r) | (b), (r)); } while(0)
-#define omap_clr_bit_regw(b,r) \
- do { omap_writew(omap_readw(r) & ~(b), (r)); } while(0)
-#define omap_set_bit_regl(b,r) \
- do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
-#define omap_clr_bit_regl(b,r) \
- do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
-#define omap_set_bits_regl(val,mask,r) \
- do { omap_writel((omap_readl(r) & ~(mask)) | (val), (r)); } while(0)
-
-#define dspword_to_virt(dw) ((void *)(dspmem_base + ((dw) << 1)))
-#define dspbyte_to_virt(db) ((void *)(dspmem_base + (db)))
-#define virt_to_dspword(va) \
- ((dsp_long_t)(((unsigned long)(va) - dspmem_base) >> 1))
-#define virt_to_dspbyte(va) \
- ((dsp_long_t)((unsigned long)(va) - dspmem_base))
-#define is_dsp_internal_mem(va) \
- (((unsigned long)(va) >= dspmem_base) && \
- ((unsigned long)(va) < dspmem_base + dspmem_size))
-#define is_dspbyte_internal_mem(db) ((db) < dspmem_size)
-#define is_dspword_internal_mem(dw) (((dw) << 1) < dspmem_size)
-
-#ifdef CONFIG_ARCH_OMAP1
-/*
- * MPUI byteswap/wordswap on/off
- * default setting: wordswap = all, byteswap = APIMEM only
- */
-#define mpui_wordswap_on() \
- omap_set_bits_regl(MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL_WORDSWAP_MASK, \
- MPUI_CTRL)
-
-#define mpui_wordswap_off() \
- omap_set_bits_regl(MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL_WORDSWAP_MASK, \
- MPUI_CTRL)
-
-#define mpui_byteswap_on() \
- omap_set_bits_regl(MPUI_CTRL_BYTESWAP_API, MPUI_CTRL_BYTESWAP_MASK, \
- MPUI_CTRL)
-
-#define mpui_byteswap_off() \
- omap_set_bits_regl(MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL_BYTESWAP_MASK, \
- 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() omap_clr_bit_regl(TC_ENDIANISM_EN, TC_ENDIANISM)
-
-/*
- * enable priority registers, EMIF, MPUI control logic
- */
-#define __dsp_enable() omap_set_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
-#define __dsp_disable() omap_clr_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
-#define __dsp_run() omap_set_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
-#define __dsp_reset() omap_clr_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
-#endif /* CONFIG_ARCH_OMAP1 */
-
-#ifdef CONFIG_ARCH_OMAP2
-/*
- * PRCM / IPI control logic
- *
- * REVISIT: these macros should probably be static inline functions
- */
-#define __dsp_core_enable() \
- do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
- & ~OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
-#define __dsp_core_disable() \
- do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
- | OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
-#define __dsp_per_enable() \
- do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
- & ~OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
-#define __dsp_per_disable() \
- do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
- | OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
-#endif /* CONFIG_ARCH_OMAP2 */
-
-#if defined(CONFIG_ARCH_OMAP1)
-extern struct clk *dsp_ck_handle;
-extern struct clk *api_ck_handle;
-#elif defined(CONFIG_ARCH_OMAP2)
-extern struct clk *dsp_fck_handle;
-extern struct clk *dsp_ick_handle;
-#endif
-extern dsp_long_t dspmem_base, dspmem_size,
- daram_base, daram_size,
- saram_base, saram_size;
-
-enum cpustat_e {
- CPUSTAT_RESET = 0,
-#ifdef CONFIG_ARCH_OMAP1
- CPUSTAT_GBL_IDLE,
- CPUSTAT_CPU_IDLE,
-#endif
- CPUSTAT_RUN,
- CPUSTAT_MAX
-};
-
-int dsp_set_rstvect(dsp_long_t adr);
-dsp_long_t dsp_get_rstvect(void);
-void dsp_set_idle_boot_base(dsp_long_t adr, size_t size);
-void dsp_reset_idle_boot_base(void);
-void dsp_cpustat_request(enum cpustat_e req);
-enum cpustat_e dsp_cpustat_get_stat(void);
-u16 dsp_cpustat_get_icrmask(void);
-void dsp_cpustat_set_icrmask(u16 mask);
-void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void));
-void dsp_unregister_mem_cb(void);
-
-#if defined(CONFIG_ARCH_OMAP1)
-#define command_dvfs_stop(m) (0)
-#define command_dvfs_start(m) (0)
-#elif defined(CONFIG_ARCH_OMAP2)
-#define command_dvfs_stop(m) \
- (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_STOP))
-#define command_dvfs_start(m) \
- (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_START))
-#endif
-
-extern struct omap_dsp *omap_dsp;
-
-extern int dsp_late_init(void);
-
-#endif /* __PLAT_OMAP_DSP_DSP_H */
diff --git a/arch/arm/plat-omap/dsp/dsp_common.c b/arch/arm/plat-omap/dsp/dsp_common.c
deleted file mode 100644
index 99be995..0000000
--- a/arch/arm/plat-omap/dsp/dsp_common.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <asm/tlbflush.h>
-#include <asm/irq.h>
-#include <asm/arch/dsp_common.h>
-#include "dsp.h"
-
-#ifdef CONFIG_ARCH_OMAP1
-#include <asm/arch/tc.h>
-#endif
-
-#if defined(CONFIG_ARCH_OMAP1)
-#define dsp_boot_config(mode) omap_writew((mode), MPUI_DSP_BOOT_CONFIG)
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-#define dsp_boot_config(mode) writel((mode), DSP_IPI_DSPBOOTCONFIG)
-#endif
-
-struct omap_dsp *omap_dsp;
-
-#if defined(CONFIG_ARCH_OMAP1)
-struct clk *dsp_ck_handle;
-struct clk *api_ck_handle;
-#elif defined(CONFIG_ARCH_OMAP2)
-struct clk *dsp_fck_handle;
-struct clk *dsp_ick_handle;
-#endif
-dsp_long_t dspmem_base, dspmem_size,
- daram_base, daram_size,
- saram_base, saram_size;
-
-static struct cpustat {
- struct mutex lock;
- enum cpustat_e stat;
- enum cpustat_e req;
- u16 icrmask;
-#ifdef CONFIG_ARCH_OMAP1
- struct {
- int mpui;
- int mem;
- int mem_delayed;
- } usecount;
- int (*mem_req_cb)(void);
- void (*mem_rel_cb)(void);
-#endif
-} cpustat = {
- .stat = CPUSTAT_RESET,
- .icrmask = 0xffff,
-};
-
-int dsp_set_rstvect(dsp_long_t adr)
-{
- unsigned long *dst_adr;
-
- if (adr >= DSPSPACE_SIZE)
- return -EINVAL;
-
- dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT);
- /* word swap */
- *dst_adr = ((adr & 0xffff) << 16) | (adr >> 16);
- /* fill 8 bytes! */
- *(dst_adr + 1) = 0;
- /* direct boot */
- dsp_boot_config(DSP_BOOT_CONFIG_DIRECT);
-
- return 0;
-}
-
-dsp_long_t dsp_get_rstvect(void)
-{
- unsigned long *dst_adr;
-
- dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT);
- return ((*dst_adr & 0xffff) << 16) | (*dst_adr >> 16);
-}
-
-#ifdef CONFIG_ARCH_OMAP1
-static void simple_load_code(unsigned char *src_c, u16 *dst, int len)
-{
- int i;
- u16 *src = (u16 *)src_c;
- int len_w;
-
- /* len must be multiple of 2. */
- if (len & 1)
- BUG();
-
- len_w = len / 2;
- for (i = 0; i < len_w; i++) {
- /* byte swap copy */
- *dst = ((*src & 0x00ff) << 8) |
- ((*src & 0xff00) >> 8);
- src++;
- dst++;
- }
-}
-
-/* program size must be multiple of 2 */
-#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 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 */ \
- 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 /* 0x20: nop */ \
-}
-
-/*
- * idle_boot base:
- * Initialized with DSP_BOOT_ADR_MPUI (=0x010000).
- * This value is used before DSP Gateway driver is initialized.
- * DSP Gateway driver will overwrite this value with other value,
- * to avoid confliction with the user program.
- */
-static dsp_long_t idle_boot_base = DSP_BOOT_ADR_MPUI;
-
-static void dsp_gbl_idle(void)
-{
- unsigned char idle_text[GBL_IDLE_TEXT_SIZE] = GBL_IDLE_TEXT_INIT;
-
- __dsp_reset();
- clk_enable(api_ck_handle);
-
-#if 0
- dsp_boot_config(DSP_BOOT_CONFIG_IDLE);
-#endif
- simple_load_code(idle_text, dspbyte_to_virt(idle_boot_base),
- GBL_IDLE_TEXT_SIZE);
- if (idle_boot_base == DSP_BOOT_ADR_MPUI)
- dsp_boot_config(DSP_BOOT_CONFIG_MPUI);
- else
- dsp_set_rstvect(idle_boot_base);
-
- __dsp_run();
- udelay(100); /* to make things stable */
- clk_disable(api_ck_handle);
-}
-
-static void dsp_cpu_idle(void)
-{
- u16 icr_tmp;
- unsigned char icrh, icrl;
-
- __dsp_reset();
- clk_enable(api_ck_handle);
-
- /*
- * icr settings:
- * DMA should not sleep for DARAM/SARAM access
- * DPLL should not sleep while any other domain is active
- */
- icr_tmp = cpustat.icrmask & ~(DSPREG_ICR_DMA | DSPREG_ICR_DPLL);
- icrh = icr_tmp >> 8;
- icrl = icr_tmp & 0xff;
- {
- 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),
- CPU_IDLE_TEXT_SIZE);
- }
- if (idle_boot_base == DSP_BOOT_ADR_MPUI)
- dsp_boot_config(DSP_BOOT_CONFIG_MPUI);
- else
- dsp_set_rstvect(idle_boot_base);
- __dsp_run();
- udelay(100); /* to make things stable */
- clk_disable(api_ck_handle);
-}
-
-void dsp_set_idle_boot_base(dsp_long_t adr, size_t size)
-{
- if (adr == idle_boot_base)
- return;
- idle_boot_base = adr;
- if ((size < GBL_IDLE_TEXT_SIZE) ||
- (size < CPU_IDLE_TEXT_SIZE)) {
- printk(KERN_ERR
- "omapdsp: size for idle program is not enough!\n");
- BUG();
- }
-
- /* 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();
-}
-
-void dsp_reset_idle_boot_base(void)
-{
- idle_boot_base = DSP_BOOT_ADR_MPUI;
-}
-#else
-void dsp_reset_idle_boot_base(void) { }
-#endif /* CONFIG_ARCH_OMAP1 */
-
-static int init_done;
-
-static int omap_dsp_init(void)
-{
- mutex_init(&cpustat.lock);
-
- dspmem_size = 0;
-#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap15xx()) {
- 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
-#ifdef CONFIG_ARCH_OMAP24XX
- if (cpu_is_omap24xx()) {
- dspmem_base = DSP_MEM_24XX_VIRT;
- dspmem_size = DSP_MEM_24XX_SIZE;
- daram_base = OMAP24XX_DARAM_BASE;
- daram_size = OMAP24XX_DARAM_SIZE;
- saram_base = OMAP24XX_SARAM_BASE;
- saram_size = OMAP24XX_SARAM_SIZE;
- }
-#endif
-#ifdef CONFIG_ARCH_OMAP34XX
- /* To be Revisited for 3430 */
- if (cpu_is_omap34xx()) {
- return -ENODEV;
- }
-#endif
- if (dspmem_size == 0) {
- printk(KERN_ERR "omapdsp: unsupported omap architecture.\n");
- return -ENODEV;
- }
-
-#if defined(CONFIG_ARCH_OMAP1)
- dsp_ck_handle = clk_get(NULL, "dsp_ck");
- if (IS_ERR(dsp_ck_handle)) {
- printk(KERN_ERR "omapdsp: could not acquire dsp_ck handle.\n");
- return PTR_ERR(dsp_ck_handle);
- }
-
- api_ck_handle = clk_get(NULL, "api_ck");
- if (IS_ERR(api_ck_handle)) {
- printk(KERN_ERR "omapdsp: could not acquire api_ck handle.\n");
- if (dsp_ck_handle != NULL)
- clk_put(dsp_ck_handle);
- return PTR_ERR(api_ck_handle);
- }
-
- /* This is needed for McBSP init, released in late_initcall */
- clk_enable(api_ck_handle);
-
- __dsp_enable();
- mpui_byteswap_off();
- mpui_wordswap_on();
- tc_wordswap();
-#elif defined(CONFIG_ARCH_OMAP2)
- dsp_fck_handle = clk_get(NULL, "dsp_fck");
- if (IS_ERR(dsp_fck_handle)) {
- printk(KERN_ERR "omapdsp: could not acquire dsp_fck handle.\n");
- return PTR_ERR(dsp_fck_handle);
- }
-
- dsp_ick_handle = clk_get(NULL, "dsp_ick");
- if (IS_ERR(dsp_ick_handle)) {
- printk(KERN_ERR "omapdsp: could not acquire dsp_ick handle.\n");
- if (dsp_fck_handle != NULL)
- clk_put(dsp_fck_handle);
- return PTR_ERR(dsp_ick_handle);
- }
-#endif
-
- init_done = 1;
- pr_info("omap_dsp_init() done\n");
- return 0;
-}
-
-#if defined(CONFIG_ARCH_OMAP1)
-static int __dsp_late_init(void)
-{
- clk_disable(api_ck_handle);
- return 0;
-}
-late_initcall(__dsp_late_init);
-#endif
-
-static void dsp_cpustat_update(void)
-{
- if (!init_done)
- omap_dsp_init();
-
- if (cpustat.req == CPUSTAT_RUN) {
- if (cpustat.stat < CPUSTAT_RUN) {
-#if defined(CONFIG_ARCH_OMAP1)
- __dsp_reset();
- clk_enable(api_ck_handle);
- udelay(10);
- __dsp_run();
-#elif defined(CONFIG_ARCH_OMAP2)
- __dsp_core_disable();
- udelay(10);
- __dsp_core_enable();
-#endif
- cpustat.stat = CPUSTAT_RUN;
- }
- return;
- }
-
- /* cpustat.req < CPUSTAT_RUN */
-
- if (cpustat.stat == CPUSTAT_RUN) {
-#ifdef CONFIG_ARCH_OMAP1
- clk_disable(api_ck_handle);
-#endif
- }
-
-#ifdef CONFIG_ARCH_OMAP1
- /*
- * (1) when ARM wants DARAM access, MPUI should be SAM and
- * DSP needs to be on.
- * (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;
- }
-#endif /* CONFIG_ARCH_OMAP1 */
-
- /*
- * no user, no request
- */
- if (cpustat.stat != CPUSTAT_RESET) {
-#if defined(CONFIG_ARCH_OMAP1)
- __dsp_reset();
-#elif defined(CONFIG_ARCH_OMAP2)
- __dsp_core_disable();
-#endif
- cpustat.stat = CPUSTAT_RESET;
- }
-}
-
-void dsp_cpustat_request(enum cpustat_e req)
-{
- mutex_lock(&cpustat.lock);
- cpustat.req = req;
- dsp_cpustat_update();
- mutex_unlock(&cpustat.lock);
-}
-
-enum cpustat_e dsp_cpustat_get_stat(void)
-{
- return cpustat.stat;
-}
-
-u16 dsp_cpustat_get_icrmask(void)
-{
- return cpustat.icrmask;
-}
-
-void dsp_cpustat_set_icrmask(u16 mask)
-{
- mutex_lock(&cpustat.lock);
- cpustat.icrmask = mask;
- dsp_cpustat_update();
- mutex_unlock(&cpustat.lock);
-}
-
-#ifdef CONFIG_ARCH_OMAP1
-void omap_dsp_request_mpui(void)
-{
- mutex_lock(&cpustat.lock);
- if (cpustat.usecount.mpui++ == 0)
- dsp_cpustat_update();
- mutex_unlock(&cpustat.lock);
-}
-
-void omap_dsp_release_mpui(void)
-{
- mutex_lock(&cpustat.lock);
- 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();
- mutex_unlock(&cpustat.lock);
-}
-
-int omap_dsp_request_mem(void)
-{
- int ret = 0;
-
- mutex_lock(&cpustat.lock);
- 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:
- mutex_unlock(&cpustat.lock);
-
- return ret;
-}
-
-/*
- * release_mem will be delayed.
- */
-static void do_release_mem(struct work_struct *dummy)
-{
- mutex_lock(&cpustat.lock);
- cpustat.usecount.mem_delayed = 0;
- if (cpustat.usecount.mem == 0) {
- dsp_cpustat_update();
- if (cpustat.mem_rel_cb)
- cpustat.mem_rel_cb();
- }
- mutex_unlock(&cpustat.lock);
-}
-
-static DECLARE_DELAYED_WORK(mem_rel_work, do_release_mem);
-
-int omap_dsp_release_mem(void)
-{
- mutex_lock(&cpustat.lock);
-
- /* 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);
- }
-
- mutex_unlock(&cpustat.lock);
-
- return 0;
-}
-
-void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void))
-{
- mutex_lock(&cpustat.lock);
-
- 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);
-
- mutex_unlock(&cpustat.lock);
-}
-
-void dsp_unregister_mem_cb(void)
-{
- mutex_lock(&cpustat.lock);
- cpustat.mem_req_cb = NULL;
- cpustat.mem_rel_cb = NULL;
- mutex_unlock(&cpustat.lock);
-}
-#else
-void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void)) { }
-void dsp_unregister_mem_cb(void) { }
-#endif /* CONFIG_ARCH_OMAP1 */
-
-arch_initcall(omap_dsp_init);
-
-#ifdef CONFIG_ARCH_OMAP1
-EXPORT_SYMBOL(omap_dsp_request_mpui);
-EXPORT_SYMBOL(omap_dsp_release_mpui);
-EXPORT_SYMBOL(omap_dsp_request_mem);
-EXPORT_SYMBOL(omap_dsp_release_mem);
-#endif /* CONFIG_ARCH_OMAP1 */
-
-#ifdef CONFIG_OMAP_DSP_MODULE
-#if defined(CONFIG_ARCH_OMAP1)
-EXPORT_SYMBOL(dsp_ck_handle);
-EXPORT_SYMBOL(api_ck_handle);
-#elif defined(CONFIG_ARCH_OMAP2)
-EXPORT_SYMBOL(dsp_fck_handle);
-EXPORT_SYMBOL(dsp_ick_handle);
-#endif
-EXPORT_SYMBOL(omap_dsp);
-EXPORT_SYMBOL(dspmem_base);
-EXPORT_SYMBOL(dspmem_size);
-EXPORT_SYMBOL(daram_base);
-EXPORT_SYMBOL(daram_size);
-EXPORT_SYMBOL(saram_base);
-EXPORT_SYMBOL(saram_size);
-EXPORT_SYMBOL(dsp_set_rstvect);
-EXPORT_SYMBOL(dsp_get_rstvect);
-#ifdef CONFIG_ARCH_OMAP1
-EXPORT_SYMBOL(dsp_set_idle_boot_base);
-EXPORT_SYMBOL(dsp_reset_idle_boot_base);
-#endif /* CONFIG_ARCH_OMAP1 */
-EXPORT_SYMBOL(dsp_cpustat_request);
-EXPORT_SYMBOL(dsp_cpustat_get_stat);
-EXPORT_SYMBOL(dsp_cpustat_get_icrmask);
-EXPORT_SYMBOL(dsp_cpustat_set_icrmask);
-EXPORT_SYMBOL(dsp_register_mem_cb);
-EXPORT_SYMBOL(dsp_unregister_mem_cb);
-
-EXPORT_SYMBOL(__cpu_flush_kern_tlb_range);
-EXPORT_SYMBOL(cpu_architecture);
-EXPORT_SYMBOL(pmd_clear_bad);
-#endif
diff --git a/arch/arm/plat-omap/dsp/dsp_core.c b/arch/arm/plat-omap/dsp/dsp_core.c
deleted file mode 100644
index 05274be..0000000
--- a/arch/arm/plat-omap/dsp/dsp_core.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/mutex.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <asm/delay.h>
-#include <asm/arch/mailbox.h>
-#include <asm/arch/dsp.h>
-#include <asm/arch/dsp_common.h>
-#include "dsp_mbcmd.h"
-#include "dsp.h"
-#include "ipbuf.h"
-
-MODULE_AUTHOR("Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>");
-MODULE_DESCRIPTION("OMAP DSP driver module");
-MODULE_LICENSE("GPL");
-
-static struct sync_seq *mbseq;
-static u16 mbseq_expect_tmp;
-static u16 *mbseq_expect = &mbseq_expect_tmp;
-
-extern int dsp_mem_late_init(void);
-
-/*
- * mailbox commands
- */
-extern void mbox_wdsnd(struct mbcmd *mb);
-extern void mbox_wdreq(struct mbcmd *mb);
-extern void mbox_bksnd(struct mbcmd *mb);
-extern void mbox_bkreq(struct mbcmd *mb);
-extern void mbox_bkyld(struct mbcmd *mb);
-extern void mbox_bksndp(struct mbcmd *mb);
-extern void mbox_bkreqp(struct mbcmd *mb);
-extern void mbox_tctl(struct mbcmd *mb);
-extern void mbox_poll(struct mbcmd *mb);
-#ifdef OLD_BINARY_SUPPORT
-/* v3.3 obsolete */
-extern void mbox_wdt(struct mbcmd *mb);
-#endif
-extern void mbox_suspend(struct mbcmd *mb);
-static void mbox_kfunc(struct mbcmd *mb);
-extern void mbox_tcfg(struct mbcmd *mb);
-extern void mbox_tadd(struct mbcmd *mb);
-extern void mbox_tdel(struct mbcmd *mb);
-extern void mbox_dspcfg(struct mbcmd *mb);
-extern void mbox_regrw(struct mbcmd *mb);
-extern void mbox_getvar(struct mbcmd *mb);
-extern void mbox_err(struct mbcmd *mb);
-extern void mbox_dbg(struct mbcmd *mb);
-
-static const struct cmdinfo
- cif_wdsnd = { "WDSND", CMD_L_TYPE_TID, mbox_wdsnd },
- cif_wdreq = { "WDREQ", CMD_L_TYPE_TID, mbox_wdreq },
- cif_bksnd = { "BKSND", CMD_L_TYPE_TID, mbox_bksnd },
- cif_bkreq = { "BKREQ", CMD_L_TYPE_TID, mbox_bkreq },
- cif_bkyld = { "BKYLD", CMD_L_TYPE_NULL, mbox_bkyld },
- cif_bksndp = { "BKSNDP", CMD_L_TYPE_TID, mbox_bksndp },
- cif_bkreqp = { "BKREQP", CMD_L_TYPE_TID, mbox_bkreqp },
- cif_tctl = { "TCTL", CMD_L_TYPE_TID, mbox_tctl },
- cif_poll = { "POLL", CMD_L_TYPE_NULL, mbox_poll },
-#ifdef OLD_BINARY_SUPPORT
- /* v3.3 obsolete */
- cif_wdt = { "WDT", CMD_L_TYPE_NULL, mbox_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, mbox_suspend },
- cif_kfunc = { "KFUNC", CMD_L_TYPE_SUBCMD, mbox_kfunc },
- cif_tcfg = { "TCFG", CMD_L_TYPE_TID, mbox_tcfg },
- cif_tadd = { "TADD", CMD_L_TYPE_TID, mbox_tadd },
- cif_tdel = { "TDEL", CMD_L_TYPE_TID, mbox_tdel },
- cif_tstop = { "TSTOP", CMD_L_TYPE_TID, NULL },
- cif_dspcfg = { "DSPCFG", CMD_L_TYPE_SUBCMD, mbox_dspcfg },
- cif_regrw = { "REGRW", CMD_L_TYPE_SUBCMD, mbox_regrw },
- cif_getvar = { "GETVAR", CMD_L_TYPE_SUBCMD, mbox_getvar },
- cif_setvar = { "SETVAR", CMD_L_TYPE_SUBCMD, NULL },
- cif_err = { "ERR", CMD_L_TYPE_SUBCMD, mbox_err },
- cif_dbg = { "DBG", CMD_L_TYPE_NULL, mbox_dbg };
-
-#define MBOX_CMD_MAX 0x80
-const struct cmdinfo *cmdinfo[MBOX_CMD_MAX] = {
- [MBOX_CMD_DSP_WDSND] = &cif_wdsnd,
- [MBOX_CMD_DSP_WDREQ] = &cif_wdreq,
- [MBOX_CMD_DSP_BKSND] = &cif_bksnd,
- [MBOX_CMD_DSP_BKREQ] = &cif_bkreq,
- [MBOX_CMD_DSP_BKYLD] = &cif_bkyld,
- [MBOX_CMD_DSP_BKSNDP] = &cif_bksndp,
- [MBOX_CMD_DSP_BKREQP] = &cif_bkreqp,
- [MBOX_CMD_DSP_TCTL] = &cif_tctl,
- [MBOX_CMD_DSP_POLL] = &cif_poll,
-#ifdef OLD_BINARY_SUPPORT
- [MBOX_CMD_DSP_WDT] = &cif_wdt, /* v3.3 obsolete */
-#endif
- [MBOX_CMD_DSP_RUNLEVEL] = &cif_runlevel,
- [MBOX_CMD_DSP_PM] = &cif_pm,
- [MBOX_CMD_DSP_SUSPEND] = &cif_suspend,
- [MBOX_CMD_DSP_KFUNC] = &cif_kfunc,
- [MBOX_CMD_DSP_TCFG] = &cif_tcfg,
- [MBOX_CMD_DSP_TADD] = &cif_tadd,
- [MBOX_CMD_DSP_TDEL] = &cif_tdel,
- [MBOX_CMD_DSP_TSTOP] = &cif_tstop,
- [MBOX_CMD_DSP_DSPCFG] = &cif_dspcfg,
- [MBOX_CMD_DSP_REGRW] = &cif_regrw,
- [MBOX_CMD_DSP_GETVAR] = &cif_getvar,
- [MBOX_CMD_DSP_SETVAR] = &cif_setvar,
- [MBOX_CMD_DSP_ERR] = &cif_err,
- [MBOX_CMD_DSP_DBG] = &cif_dbg,
-};
-
-#define list_for_each_entry_safe_natural(p,n,h,m) \
- list_for_each_entry_safe(p,n,h,m)
-#define __BUILD_KFUNC(fn, dir) \
-static int __dsp_kfunc_##fn##_devices(struct omap_dsp *dsp, int type, int stage)\
-{ \
- struct dsp_kfunc_device *p, *tmp; \
- int ret, fail = 0; \
- \
- list_for_each_entry_safe_##dir(p, tmp, dsp->kdev_list, entry) { \
- if (type && (p->type != type)) \
- continue; \
- if (p->fn == NULL) \
- continue; \
- ret = p->fn(p, stage); \
- if (ret) { \
- printk(KERN_ERR "%s %s failed\n", #fn, p->name); \
- fail++; \
- } \
- } \
- return fail; \
-}
-#define BUILD_KFUNC(fn, dir) \
-__BUILD_KFUNC(fn, dir) \
-static inline int dsp_kfunc_##fn##_devices(struct omap_dsp *dsp) \
-{ \
- return __dsp_kfunc_##fn##_devices(dsp, 0, 0); \
-}
-#define BUILD_KFUNC_CTL(fn, dir) \
-__BUILD_KFUNC(fn, dir) \
-static inline int dsp_kfunc_##fn##_devices(struct omap_dsp *dsp, int type, int stage) \
-{ \
- return __dsp_kfunc_##fn##_devices(dsp, type, stage); \
-}
-
-BUILD_KFUNC(probe, natural)
-BUILD_KFUNC(remove, reverse)
-BUILD_KFUNC_CTL(enable, natural)
-BUILD_KFUNC_CTL(disable, reverse)
-
-int sync_with_dsp(u16 *adr, u16 val, int try_cnt)
-{
- int try;
-
- if (*(volatile u16 *)adr == val)
- return 0;
-
- for (try = 0; try < try_cnt; try++) {
- udelay(1);
- if (*(volatile u16 *)adr == val) {
- /* success! */
- pr_info("omapdsp: sync_with_dsp(): try = %d\n", try);
- return 0;
- }
- }
-
- /* fail! */
- return -1;
-}
-
-static int mbcmd_sender_prepare(void *data)
-{
- struct mb_exarg *arg = data;
- int i, ret = 0;
- /*
- * 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, TID_FREE, 10) < 0) {
- printk(KERN_ERR "omapdsp: ipbuf_sys_ad is busy.\n");
- ret = -EBUSY;
- goto out;
- }
-
- for (i = 0; i < arg->argc; i++) {
- ipbuf_sys_ad->d[i] = arg->argv[i];
- }
- ipbuf_sys_ad->s = arg->tid;
- out:
- dsp_mem_disable(ipbuf_sys_ad);
- return ret;
-}
-
-/*
- * __dsp_mbcmd_send_exarg(): mailbox dispatcher
- */
-int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
- int recovery_flag)
-{
- int ret = 0;
-
- if (unlikely(omap_dsp->enabled == 0)) {
- ret = dsp_kfunc_enable_devices(omap_dsp,
- DSP_KFUNC_DEV_TYPE_COMMON, 0);
- if (ret == 0)
- omap_dsp->enabled = 1;
- }
-
- /*
- * while MMU fault is set,
- * only recovery command can be executed
- */
- if (dsp_err_isset(ERRCODE_MMU) && !recovery_flag) {
- printk(KERN_ERR
- "mbox: mmu interrupt is set. %s is aborting.\n",
- cmd_name(*mb));
- goto out;
- }
-
- ret = omap_mbox_msg_send(omap_dsp->mbox,
- *(mbox_msg_t *)mb, (void*)arg);
- if (ret)
- goto out;
-
- if (mbseq)
- mbseq->ad_arm++;
-
- mblog_add(mb, DIR_A2D);
- out:
- return ret;
-}
-
-int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg,
- wait_queue_head_t *q)
-{
- int ret;
-
- DEFINE_WAIT(wait);
- prepare_to_wait(q, &wait, TASK_INTERRUPTIBLE);
- ret = dsp_mbcmd_send_exarg(mb, arg);
- if (ret < 0)
- goto out;
- schedule_timeout(DSP_TIMEOUT);
- out:
- finish_wait(q, &wait);
- return ret;
-}
-
-/*
- * mbcmd receiver
- */
-static int mbcmd_receiver(void* msg)
-{
- struct mbcmd *mb = (struct mbcmd *)&msg;
-
- if (cmdinfo[mb->cmd_h] == NULL) {
- printk(KERN_ERR
- "invalid message (%08x) for mbcmd_receiver().\n",
- (mbox_msg_t)msg);
- return -1;
- }
-
- (*mbseq_expect)++;
-
- mblog_add(mb, DIR_D2A);
-
- /* call handler for the command */
- if (cmdinfo[mb->cmd_h]->handler)
- cmdinfo[mb->cmd_h]->handler(mb);
- else
- printk(KERN_ERR "mbox: %s is not allowed from DSP.\n",
- cmd_name(*mb));
- return 0;
-}
-
-static int mbsync_hold_mem_active;
-
-void dsp_mbox_start(void)
-{
- omap_mbox_init_seq(omap_dsp->mbox);
- mbseq_expect_tmp = 0;
-}
-
-void dsp_mbox_stop(void)
-{
- mbseq = NULL;
- mbseq_expect = &mbseq_expect_tmp;
-}
-
-int dsp_mbox_config(void *p)
-{
- 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;
-}
-
-static int __init dsp_mbox_init(void)
-{
- omap_dsp->mbox = omap_mbox_get("dsp");
- if (IS_ERR(omap_dsp->mbox)) {
- printk(KERN_ERR "failed to get mailbox handler for DSP.\n");
- return -ENODEV;
- }
-
- omap_dsp->mbox->rxq->callback = mbcmd_receiver;
- omap_dsp->mbox->txq->callback = mbcmd_sender_prepare;
-
- return 0;
-}
-
-static void dsp_mbox_exit(void)
-{
- omap_dsp->mbox->txq->callback = NULL;
- omap_dsp->mbox->rxq->callback = NULL;
-
- omap_mbox_put(omap_dsp->mbox);
-
- if (mbsync_hold_mem_active) {
- dsp_mem_disable((void *)daram_base);
- mbsync_hold_mem_active = 0;
- }
-}
-
-/*
- * kernel function dispatcher
- */
-extern void mbox_fbctl_upd(void);
-extern void mbox_fbctl_disable(struct mbcmd *mb);
-
-static void mbox_kfunc_fbctl(struct mbcmd *mb)
-{
- switch (mb->data) {
- case FBCTL_UPD:
- mbox_fbctl_upd();
- break;
- case FBCTL_DISABLE:
- mbox_fbctl_disable(mb);
- break;
- default:
- printk(KERN_ERR
- "mbox: Unknown FBCTL from DSP: 0x%04x\n", mb->data);
- }
-}
-
-/*
- * dspgw: KFUNC message handler
- */
-static void mbox_kfunc_power(unsigned short data)
-{
- int ret = -1;
-
- switch (data) {
- case DVFS_START: /* ACK from DSP */
- /* TBD */
- break;
- case AUDIO_PWR_UP:
- ret = dsp_kfunc_enable_devices(omap_dsp,
- DSP_KFUNC_DEV_TYPE_AUDIO, 0);
- if (ret == 0)
- ret++;
- break;
- case AUDIO_PWR_DOWN: /* == AUDIO_PWR_DOWN1 */
- ret = dsp_kfunc_disable_devices(omap_dsp,
- DSP_KFUNC_DEV_TYPE_AUDIO, 1);
- break;
- case AUDIO_PWR_DOWN2:
- ret = dsp_kfunc_disable_devices(omap_dsp,
- DSP_KFUNC_DEV_TYPE_AUDIO, 2);
- break;
- case DSP_PWR_DOWN:
- ret = dsp_kfunc_disable_devices(omap_dsp,
- DSP_KFUNC_DEV_TYPE_COMMON, 0);
- if (ret == 0)
- omap_dsp->enabled = 0;
- break;
- default:
- printk(KERN_ERR
- "mailbox: Unknown PWR from DSP: 0x%04x\n", data);
- break;
- }
-
- if (unlikely(ret < 0)) {
- printk(KERN_ERR "mailbox: PWR(0x%04x) failed\n", data);
- return;
- }
-
- if (likely(ret == 0))
- return;
-
- mbcompose_send(KFUNC, KFUNC_POWER, data);
-}
-
-static void mbox_kfunc(struct mbcmd *mb)
-{
- switch (mb->cmd_l) {
- case KFUNC_FBCTL:
- mbox_kfunc_fbctl(mb);
- break;
- case KFUNC_POWER:
- mbox_kfunc_power(mb->data);
- break;
- default:
- printk(KERN_ERR
- "mbox: Unknown KFUNC from DSP: 0x%02x\n", mb->cmd_l);
- }
-}
-
-#if defined(CONFIG_ARCH_OMAP1)
-static inline void dsp_clk_enable(void) {}
-static inline void dsp_clk_disable(void) {}
-#elif defined(CONFIG_ARCH_OMAP2)
-static inline void dsp_clk_enable(void)
-{
- u32 r;
-
- /*XXX should be handled in mach-omap[1,2] XXX*/
- prm_write_mod_reg(OMAP24XX_FORCESTATE | (1 << OMAP_POWERSTATE_SHIFT),
- OMAP24XX_DSP_MOD, PM_PWSTCTRL);
-
- r = cm_read_mod_reg(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
- r |= OMAP2420_AUTO_DSP_IPI;
- cm_write_mod_reg(r, OMAP24XX_DSP_MOD, CM_AUTOIDLE);
-
- r = cm_read_mod_reg(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
- r |= OMAP24XX_AUTOSTATE_DSP;
- cm_write_mod_reg(r, OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
-
- clk_enable(dsp_fck_handle);
- clk_enable(dsp_ick_handle);
- __dsp_per_enable();
-}
-static inline void dsp_clk_disable(void)
-{
- __dsp_per_disable();
- clk_disable(dsp_ick_handle);
- clk_disable(dsp_fck_handle);
-
- prm_write_mod_reg(OMAP24XX_FORCESTATE | (3 << OMAP_POWERSTATE_SHIFT),
- OMAP24XX_DSP_MOD, PM_PWSTCTRL);
-}
-#endif
-
-int dsp_late_init(void)
-{
- int ret;
-
- dsp_clk_enable();
- ret = dsp_mem_late_init();
- if (ret)
- return ret;
- ret = dsp_mbox_init();
- if (ret)
- goto fail_mbox;
-#ifdef CONFIG_ARCH_OMAP1
- dsp_set_idle_boot_base(IDLEPG_BASE, IDLEPG_SIZE);
-#endif
- ret = dsp_kfunc_enable_devices(omap_dsp,
- DSP_KFUNC_DEV_TYPE_COMMON, 0);
- if (ret)
- goto fail_kfunc;
- omap_dsp->enabled = 1;
-
- return 0;
-
- fail_kfunc:
- dsp_mbox_exit();
- fail_mbox:
- dsp_clk_disable();
-
- return ret;
-}
-
-extern int dsp_ctl_core_init(void);
-extern void dsp_ctl_core_exit(void);
-extern int dsp_ctl_init(void);
-extern void dsp_ctl_exit(void);
-extern int dsp_mem_init(void);
-extern void dsp_mem_exit(void);
-extern void mblog_init(void);
-extern void mblog_exit(void);
-extern int dsp_taskmod_init(void);
-extern void dsp_taskmod_exit(void);
-
-/*
- * driver functions
- */
-static int __init dsp_drv_probe(struct platform_device *pdev)
-{
- int ret;
- struct omap_dsp *info;
- struct dsp_platform_data *pdata = pdev->dev.platform_data;
-
- dev_info(&pdev->dev, "OMAP DSP driver initialization\n");
-
- info = kzalloc(sizeof(struct omap_dsp), GFP_KERNEL);
- if (unlikely(info == NULL)) {
- dev_dbg(&pdev->dev, "no memory for info\n");
- return -ENOMEM;
- }
- platform_set_drvdata(pdev, info);
- omap_dsp = info;
-
- mutex_init(&info->lock);
- info->dev = &pdev->dev;
- info->kdev_list = &pdata->kdev_list;
-
- ret = dsp_kfunc_probe_devices(info);
- if (ret) {
- ret = -ENXIO;
- goto fail_kfunc;
- }
-
- ret = dsp_ctl_core_init();
- if (ret)
- goto fail_ctl_core;
- ret = dsp_mem_init();
- if (ret)
- goto fail_mem;
- ret = dsp_ctl_init();
- if (unlikely(ret))
- goto fail_ctl_init;
- mblog_init();
- ret = dsp_taskmod_init();
- if (ret)
- goto fail_taskmod;
-
- return 0;
-
- fail_taskmod:
- mblog_exit();
- dsp_ctl_exit();
- fail_ctl_init:
- dsp_mem_exit();
- fail_mem:
- dsp_ctl_core_exit();
- fail_ctl_core:
- dsp_kfunc_remove_devices(info);
- fail_kfunc:
- kfree(info);
-
- return ret;
-}
-
-static int dsp_drv_remove(struct platform_device *pdev)
-{
- struct omap_dsp *info = platform_get_drvdata(pdev);
-
- dsp_cpustat_request(CPUSTAT_RESET);
-
- dsp_cfgstat_request(CFGSTAT_CLEAN);
- dsp_mbox_exit();
- dsp_taskmod_exit();
- mblog_exit();
- dsp_ctl_exit();
- dsp_mem_exit();
-
- dsp_ctl_core_exit();
-
-#ifdef CONFIG_ARCH_OMAP2
- __dsp_per_disable();
- clk_disable(dsp_ick_handle);
- clk_disable(dsp_fck_handle);
-#endif
- dsp_kfunc_remove_devices(info);
- kfree(info);
-
- return 0;
-}
-
-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP1)
-static int dsp_drv_suspend(struct platform_device *pdev, pm_message_t state)
-{
- dsp_cfgstat_request(CFGSTAT_SUSPEND);
-
- return 0;
-}
-
-static int dsp_drv_resume(struct platform_device *pdev)
-{
- dsp_cfgstat_request(CFGSTAT_RESUME);
-
- return 0;
-}
-#else
-#define dsp_drv_suspend NULL
-#define dsp_drv_resume NULL
-#endif /* CONFIG_PM */
-
-static struct platform_driver dsp_driver = {
- .probe = dsp_drv_probe,
- .remove = dsp_drv_remove,
- .suspend = dsp_drv_suspend,
- .resume = dsp_drv_resume,
- .driver = {
- .name = "dsp",
- },
-};
-
-static int __init omap_dsp_mod_init(void)
-{
- return platform_driver_register(&dsp_driver);
-}
-
-static void __exit omap_dsp_mod_exit(void)
-{
- platform_driver_unregister(&dsp_driver);
-}
-
-/* module dependency: need mailbox module that have mbox_dsp_info */
-extern struct omap_mbox mbox_dsp_info;
-struct omap_mbox *mbox_dep = &mbox_dsp_info;
-
-module_init(omap_dsp_mod_init);
-module_exit(omap_dsp_mod_exit);
diff --git a/arch/arm/plat-omap/dsp/dsp_ctl.c b/arch/arm/plat-omap/dsp/dsp_ctl.c
deleted file mode 100644
index 79c1fdf..0000000
--- a/arch/arm/plat-omap/dsp/dsp_ctl.c
+++ /dev/null
@@ -1,1069 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/ioctls.h>
-#include <asm/arch/mailbox.h>
-#include <asm/arch/dsp.h>
-#include "hardware_dsp.h"
-#include "dsp_mbcmd.h"
-#include "dsp.h"
-#include "ipbuf.h"
-
-enum dsp_space_e {
- SPACE_MEM,
- SPACE_IO,
-};
-
-#ifdef CONFIG_OMAP_DSP_FBEXPORT
-static enum fbstat_e {
- FBSTAT_DISABLED = 0,
- FBSTAT_ENABLED,
- FBSTAT_MAX,
-} fbstat = FBSTAT_ENABLED;
-#endif
-
-static enum cfgstat_e cfgstat;
-int mbox_revision;
-static u8 n_stask;
-
-static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
- char *buf);
-static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
- char *buf);
-static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
- char *buf);
-static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count);
-static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
- char *buf);
-
-#define __ATTR_RW(_name, _mode) { \
- .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
- .show = _name##_show, \
- .store = _name##_store, \
-}
-
-static struct device_attribute dev_attr_ifver = __ATTR_RO(ifver);
-static struct device_attribute dev_attr_cpustat = __ATTR_RO(cpustat);
-static struct device_attribute dev_attr_icrmask = __ATTR_RW(icrmask, 0644);
-static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
-
-/*
- * misc interactive mailbox command operations
- */
-static struct misc_mb_wait_struct {
- struct mutex lock;
- wait_queue_head_t wait_q;
- u8 cmd_h;
- u8 cmd_l;
- u16 *retvp;
-} misc_mb_wait = {
- .lock = __MUTEX_INITIALIZER(misc_mb_wait.lock),
- .wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(misc_mb_wait.wait_q),
-};
-
-static int __misc_mbcompose_send_and_wait(u8 cmd_h, u8 cmd_l, u16 data,
- u16 *retvp)
-{
- struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
- int ret = 0;
-
- if (mutex_lock_interruptible(&misc_mb_wait.lock))
- return -EINTR;
-
- misc_mb_wait.cmd_h = mb.cmd_h;
- misc_mb_wait.cmd_l = mb.cmd_l;
- misc_mb_wait.retvp = retvp;
- dsp_mbcmd_send_and_wait(&mb, &misc_mb_wait.wait_q);
-
- if (misc_mb_wait.cmd_h != 0)
- ret = -EINVAL;
-
- mutex_unlock(&misc_mb_wait.lock);
- return ret;
-}
-
-#define misc_mbcompose_send_and_wait(cmd_h, cmd_l, data, retvp) \
- __misc_mbcompose_send_and_wait(MBOX_CMD_DSP_##cmd_h, (cmd_l), \
- (data), (retvp));
-
-static int misc_mbcmd_response(struct mbcmd *mb, int argc, int match_cmd_l_flag)
-{
- volatile u16 *buf;
- int i;
-
- /* if match_cmd_l_v flag is set, cmd_l needs to be matched as well. */
- if (!waitqueue_active(&misc_mb_wait.wait_q) ||
- (misc_mb_wait.cmd_h != mb->cmd_h) ||
- (match_cmd_l_flag && (misc_mb_wait.cmd_l != mb->cmd_l))) {
- const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
- char cmdstr[32];
-
- if (ci->cmd_l_type == CMD_L_TYPE_SUBCMD)
- sprintf(cmdstr, "%s:%s", ci->name, subcmd_name(mb));
- else
- strcpy(cmdstr, ci->name);
- printk(KERN_WARNING
- "mbox: unexpected command %s received!\n", cmdstr);
- return -1;
- }
-
- /*
- * if argc == 1, receive data through mbox:data register.
- * if argc > 1, receive through ipbuf_sys.
- */
- if (argc == 1)
- misc_mb_wait.retvp[0] = mb->data;
- else if (argc > 1) {
- if (dsp_mem_enable(ipbuf_sys_da) < 0) {
- printk(KERN_ERR "mbox: %s - ipbuf_sys_da read failed!\n",
- cmdinfo[mb->cmd_h]->name);
- return -1;
- }
- if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
- printk(KERN_ERR "mbox: %s - IPBUF sync failed!\n",
- cmdinfo[mb->cmd_h]->name);
- dsp_mem_disable(ipbuf_sys_da);
- return -1;
- }
- /* need word access. do not use memcpy. */
- buf = ipbuf_sys_da->d;
- for (i = 0; i < argc; i++)
- misc_mb_wait.retvp[i] = buf[i];
- release_ipbuf_pvt(ipbuf_sys_da);
- dsp_mem_disable(ipbuf_sys_da);
- }
-
- misc_mb_wait.cmd_h = 0;
- wake_up_interruptible(&misc_mb_wait.wait_q);
- return 0;
-}
-
-static int dsp_regread(enum dsp_space_e space, u16 adr, u16 *val)
-{
- u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMR : REGRW_IOR;
- int ret;
-
- ret = misc_mbcompose_send_and_wait(REGRW, cmd_l, adr, val);
- if ((ret < 0) && (ret != -EINTR))
- printk(KERN_ERR "omapdsp: register read error!\n");
-
- return ret;
-}
-
-static int dsp_regwrite(enum dsp_space_e space, u16 adr, u16 val)
-{
- u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMW : REGRW_IOW;
- struct mb_exarg arg = {
- .tid = TID_ANON,
- .argc = 1,
- .argv = &val,
- };
-
- mbcompose_send_exarg(REGRW, cmd_l, adr, &arg);
- return 0;
-}
-
-static int dsp_getvar(u8 varid, u16 *val)
-{
- int ret;
-
- ret = misc_mbcompose_send_and_wait(GETVAR, varid, 0, val);
- if ((ret < 0) && (ret != -EINTR))
- printk(KERN_ERR "omapdsp: variable read error!\n");
-
- return ret;
-}
-
-static int dsp_setvar(u8 varid, u16 val)
-{
- mbcompose_send(SETVAR, varid, val);
- return 0;
-}
-
-/*
- * dsp_cfg() return value
- * = 0: OK
- * = 1: failed, but state is clear. (DSPCFG command failed)
- * < 0: failed. need cleanup.
- */
-static int dsp_cfg(void)
-{
- int ret = 0;
-
-#ifdef CONFIG_ARCH_OMAP1
- /* for safety */
- dsp_mem_usecount_clear();
-#endif
-
- /*
- * DSPCFG command and dsp_mem_start() must be called
- * while internal mem is on.
- */
- dsp_mem_enable((void *)dspmem_base);
-
- dsp_mbox_start();
- dsp_twch_start();
- dsp_mem_start();
- dsp_err_start();
-
- mbox_revision = -1;
-
- ret = misc_mbcompose_send_and_wait(DSPCFG, DSPCFG_REQ, 0, NULL);
- if (ret < 0) {
- if (ret != -EINTR)
- printk(KERN_ERR "omapdsp: configuration error!\n");
- ret = 1;
- goto out;
- }
-
-#if defined(CONFIG_ARCH_OMAP1) && defined(OLD_BINARY_SUPPORT)
- /*
- * MBREV 3.2 or earlier doesn't assume DMA domain is on
- * when DSPCFG command is sent
- */
- if ((mbox_revision == MBREV_3_0) ||
- (mbox_revision == MBREV_3_2)) {
- if ((ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA)) < 0)
- goto out;
- }
-#endif
-
- if ((ret = dsp_task_config_all(n_stask)) < 0)
- goto out;
-
- /* initialization */
-#ifdef CONFIG_OMAP_DSP_FBEXPORT
- fbstat = FBSTAT_ENABLED;
-#endif
-
- /* send parameter */
- ret = dsp_setvar(VARID_ICRMASK, dsp_cpustat_get_icrmask());
- if (ret < 0)
- goto out;
-
- /* create runtime sysfs entries */
- ret = device_create_file(omap_dsp->dev, &dev_attr_loadinfo);
- if (ret)
- printk(KERN_ERR "device_create_file failed: %d\n", ret);
- out:
- dsp_mem_disable((void *)dspmem_base);
- return ret;
-}
-
-static int dsp_uncfg(void)
-{
- if (dsp_taskmod_busy()) {
- printk(KERN_WARNING "omapdsp: tasks are busy.\n");
- return -EBUSY;
- }
-
- /* FIXME: lock task module */
-
- /* remove runtime sysfs entries */
- device_remove_file(omap_dsp->dev, &dev_attr_loadinfo);
-
- dsp_mbox_stop();
- dsp_twch_stop();
- dsp_mem_stop();
- dsp_err_stop();
- dsp_dbg_stop();
- dsp_task_unconfig_all();
- ipbuf_stop();
-
- return 0;
-}
-
-static int dsp_suspend(void)
-{
- int ret;
-
- ret = misc_mbcompose_send_and_wait(SUSPEND, 0, 0, NULL);
- if (ret < 0) {
- if (ret != -EINVAL)
- printk(KERN_ERR "omapdsp: DSP suspend error!\n");
- return ret;
- }
-
- udelay(100); /* wait for DSP-side execution */
- return 0;
-}
-
-int dsp_cfgstat_request(enum cfgstat_e st_req)
-{
- static DEFINE_MUTEX(cfgstat_lock);
- int ret = 0, ret_override = 0;
-
- if (mutex_lock_interruptible(&cfgstat_lock))
- return -EINTR;
-
-again:
- switch (st_req) {
-
- /* cfgstat takes CLEAN, READY or SUSPEND,
- while st_req can take SUSPEND in addition. */
-
- case CFGSTAT_CLEAN:
- if (cfgstat == CFGSTAT_CLEAN)
- goto up_out;
- if ((ret = dsp_uncfg()) < 0)
- goto up_out;
- break;
-
- case CFGSTAT_READY:
- if (cfgstat != CFGSTAT_CLEAN) {
- printk(KERN_ERR "omapdsp: DSP is ready already!\n");
- ret = -EINVAL;
- goto up_out;
- }
-
- ret = dsp_cfg();
- if (ret > 0) { /* failed, but state is clear. */
- ret = -EINVAL;
- goto up_out;
- } else if (ret < 0) { /* failed, need cleanup. */
- st_req = CFGSTAT_CLEAN;
- ret_override = ret;
- goto again;
- }
- break;
-
- /*
- * suspend / resume
- * DSP is not reset within this code, but done in omap_pm_suspend.
- * so if these functions are called from sysfs,
- * DSP should be reset / unreset out of these functions.
- */
- case CFGSTAT_SUSPEND:
- switch (cfgstat) {
-
- case CFGSTAT_CLEAN:
- if (dsp_cpustat_get_stat() == CPUSTAT_RUN) {
- printk(KERN_WARNING
- "omapdsp: illegal operation -- trying "
- "suspend DSP while it is running but "
- "not configured.\n"
- " Resetting DSP.\n");
- dsp_cpustat_request(CPUSTAT_RESET);
- ret = -EINVAL;
- }
- goto up_out;
-
- case CFGSTAT_READY:
- if ((ret = dsp_suspend()) < 0)
- goto up_out;
- break;
-
- case CFGSTAT_SUSPEND:
- goto up_out;
-
- default:
- BUG();
-
- }
-
- break;
-
- case CFGSTAT_RESUME:
- if (cfgstat != CFGSTAT_SUSPEND) {
- printk(KERN_WARNING
- "omapdsp: DSP resume request, but DSP is not in "
- "suspend state.\n");
- ret = -EINVAL;
- goto up_out;
- }
- st_req = CFGSTAT_READY;
- break;
-
- default:
- BUG();
-
- }
-
- cfgstat = st_req;
-up_out:
- mutex_unlock(&cfgstat_lock);
- return ret_override ? ret_override : ret;
-}
-
-enum cfgstat_e dsp_cfgstat_get_stat(void)
-{
- return cfgstat;
-}
-
-/*
- * polls all tasks
- */
-static int dsp_poll(void)
-{
- int ret;
-
- ret = misc_mbcompose_send_and_wait(POLL, 0, 0, NULL);
- if ((ret < 0) && (ret != -EINTR))
- printk(KERN_ERR "omapdsp: poll error!\n");
-
- return ret;
-}
-
-int dsp_set_runlevel(u8 level)
-{
- if (level == RUNLEVEL_RECOVERY) {
- if (mbcompose_send_recovery(RUNLEVEL, level, 0) < 0)
- return -EINVAL;
- } else {
- if ((level < RUNLEVEL_USER) ||
- (level > RUNLEVEL_SUPER))
- return -EINVAL;
- if (mbcompose_send(RUNLEVEL, level, 0) < 0)
- return -EINVAL;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_OMAP_DSP_FBEXPORT
-static void dsp_fbctl_enable(void)
-{
- mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_ENABLE);
-}
-
-static int dsp_fbctl_disable(void)
-{
- int ret;
-
- ret = misc_mbcompose_send_and_wait(KFUNC, KFUNC_FBCTL, FBCTL_DISABLE,
- NULL);
- if ((ret < 0) && (ret != -EINTR))
- printk(KERN_ERR "omapdsp: fb disable error!\n");
-
- return 0;
-}
-
-static int dsp_fbstat_request(enum fbstat_e st)
-{
- static DEFINE_MUTEX(fbstat_lock);
- int ret = 0;
-
- if (mutex_lock_interruptible(&fbstat_lock))
- return -EINTR;
-
- if (st == fbstat)
- goto up_out;
-
- switch (st) {
- case FBSTAT_ENABLED:
- dsp_fbctl_enable();
- break;
- case FBSTAT_DISABLED:
- if ((ret = dsp_fbctl_disable()) < 0)
- goto up_out;
- break;
- default:
- BUG();
- }
-
- fbstat = st;
-up_out:
- mutex_unlock(&fbstat_lock);
- return 0;
-}
-#endif /* CONFIG_OMAP_DSP_FBEXPORT */
-
-/*
- * DSP control device file operations
- */
-static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- int ret = 0;
-
- switch (cmd) {
- /*
- * command level 1: commands which don't need lock
- */
- case DSPCTL_IOCTL_RUN:
- dsp_cpustat_request(CPUSTAT_RUN);
- break;
-
- case DSPCTL_IOCTL_RESET:
- dsp_cpustat_request(CPUSTAT_RESET);
- break;
-
- case DSPCTL_IOCTL_SETRSTVECT:
- ret = dsp_set_rstvect((dsp_long_t)arg);
- break;
-
-#ifdef CONFIG_ARCH_OMAP1
- case DSPCTL_IOCTL_CPU_IDLE:
- dsp_cpustat_request(CPUSTAT_CPU_IDLE);
- break;
-
- case DSPCTL_IOCTL_GBL_IDLE:
- dsp_cpustat_request(CPUSTAT_GBL_IDLE);
- break;
-
- case DSPCTL_IOCTL_MPUI_WORDSWAP_ON:
- mpui_wordswap_on();
- break;
-
- case DSPCTL_IOCTL_MPUI_WORDSWAP_OFF:
- mpui_wordswap_off();
- break;
-
- case DSPCTL_IOCTL_MPUI_BYTESWAP_ON:
- mpui_byteswap_on();
- break;
-
- case DSPCTL_IOCTL_MPUI_BYTESWAP_OFF:
- mpui_byteswap_off();
- break;
-#endif /* CONFIG_ARCH_OMAP1 */
-
- case DSPCTL_IOCTL_TASKCNT:
- ret = dsp_task_count();
- break;
-
- case DSPCTL_IOCTL_MBSEND:
- {
- struct omap_dsp_mailbox_cmd u_cmd;
- mbox_msg_t msg;
- if (copy_from_user(&u_cmd, (void *)arg, sizeof(u_cmd)))
- return -EFAULT;
- msg = (u_cmd.cmd << 16) | u_cmd.data;
- ret = dsp_mbcmd_send((struct mbcmd *)&msg);
- break;
- }
-
- case DSPCTL_IOCTL_SETVAR:
- {
- struct omap_dsp_varinfo var;
- if (copy_from_user(&var, (void *)arg, sizeof(var)))
- return -EFAULT;
- ret = dsp_setvar(var.varid, var.val[0]);
- break;
- }
-
- case DSPCTL_IOCTL_RUNLEVEL:
- ret = dsp_set_runlevel(arg);
- break;
-
-#ifdef CONFIG_OMAP_DSP_FBEXPORT
- case DSPCTL_IOCTL_FBEN:
- ret = dsp_fbstat_request(FBSTAT_ENABLED);
- break;
-#endif
-
- /*
- * command level 2: commands which need lock
- */
- case DSPCTL_IOCTL_DSPCFG:
- ret = dsp_cfgstat_request(CFGSTAT_READY);
- break;
-
- case DSPCTL_IOCTL_DSPUNCFG:
- ret = dsp_cfgstat_request(CFGSTAT_CLEAN);
- break;
-
- case DSPCTL_IOCTL_POLL:
- ret = dsp_poll();
- break;
-
-#ifdef CONFIG_OMAP_DSP_FBEXPORT
- case DSPCTL_IOCTL_FBDIS:
- ret = dsp_fbstat_request(FBSTAT_DISABLED);
- break;
-#endif
-
- case DSPCTL_IOCTL_SUSPEND:
- if ((ret = dsp_cfgstat_request(CFGSTAT_SUSPEND)) < 0)
- break;
- dsp_cpustat_request(CPUSTAT_RESET);
- break;
-
- case DSPCTL_IOCTL_RESUME:
- if ((ret = dsp_cfgstat_request(CFGSTAT_RESUME)) < 0)
- break;
- dsp_cpustat_request(CPUSTAT_RUN);
- break;
-
- case DSPCTL_IOCTL_REGMEMR:
- {
- struct omap_dsp_reginfo *u_reg = (void *)arg;
- u16 adr, val;
-
- if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
- return -EFAULT;
- if ((ret = dsp_regread(SPACE_MEM, adr, &val)) < 0)
- return ret;
- if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
- return -EFAULT;
- break;
- }
-
- case DSPCTL_IOCTL_REGMEMW:
- {
- struct omap_dsp_reginfo reg;
-
- if (copy_from_user(®, (void *)arg, sizeof(reg)))
- return -EFAULT;
- ret = dsp_regwrite(SPACE_MEM, reg.adr, reg.val);
- break;
- }
-
- case DSPCTL_IOCTL_REGIOR:
- {
- struct omap_dsp_reginfo *u_reg = (void *)arg;
- u16 adr, val;
-
- if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
- return -EFAULT;
- if ((ret = dsp_regread(SPACE_IO, adr, &val)) < 0)
- return ret;
- if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
- return -EFAULT;
- break;
- }
-
- case DSPCTL_IOCTL_REGIOW:
- {
- struct omap_dsp_reginfo reg;
-
- if (copy_from_user(®, (void *)arg, sizeof(reg)))
- return -EFAULT;
- ret = dsp_regwrite(SPACE_IO, reg.adr, reg.val);
- break;
- }
-
- case DSPCTL_IOCTL_GETVAR:
- {
- struct omap_dsp_varinfo *u_var = (void *)arg;
- u8 varid;
- u16 val[5]; /* maximum */
- int argc;
-
- if (copy_from_user(&varid, &u_var->varid, sizeof(u8)))
- return -EFAULT;
- switch (varid) {
- case VARID_ICRMASK:
- argc = 1;
- break;
- case VARID_LOADINFO:
- argc = 5;
- break;
- default:
- return -EINVAL;
- }
- if ((ret = dsp_getvar(varid, val)) < 0)
- return ret;
- if (copy_to_user(&u_var->val, val, sizeof(u16) * argc))
- return -EFAULT;
- break;
- }
-
- default:
- return -ENOIOCTLCMD;
- }
-
- return ret;
-}
-
-/*
- * functions called from mailbox interrupt routine
- */
-void mbox_suspend(struct mbcmd *mb)
-{
- misc_mbcmd_response(mb, 0, 0);
-}
-
-void mbox_dspcfg(struct mbcmd *mb)
-{
- u8 last = mb->cmd_l & 0x80;
- u8 cfgcmd = mb->cmd_l & 0x7f;
- static dsp_long_t tmp_ipb_adr;
-
- if (!waitqueue_active(&misc_mb_wait.wait_q) ||
- (misc_mb_wait.cmd_h != MBOX_CMD_DSP_DSPCFG)) {
- printk(KERN_WARNING
- "mbox: DSPCFG command received, "
- "but nobody is waiting for it...\n");
- return;
- }
-
- /* mailbox protocol check */
- if (cfgcmd == DSPCFG_PROTREV) {
- mbox_revision = mb->data;
- if (mbox_revision == MBPROT_REVISION)
- return;
-#ifdef OLD_BINARY_SUPPORT
- else if ((mbox_revision == MBREV_3_0) ||
- (mbox_revision == MBREV_3_2)) {
- printk(KERN_WARNING
- "mbox: ***** old DSP binary *****\n"
- " Please update your DSP application.\n");
- return;
- }
-#endif
- else {
- printk(KERN_ERR
- "mbox: protocol revision check error!\n"
- " expected=0x%04x, received=0x%04x\n",
- MBPROT_REVISION, mb->data);
- mbox_revision = -1;
- goto abort1;
- }
- }
-
- /*
- * following commands are accepted only after
- * revision check has been passed.
- */
- if (!mbox_revision < 0) {
- pr_info("mbox: DSPCFG command received, "
- "but revision check has not been passed.\n");
- return;
- }
-
- switch (cfgcmd) {
- case DSPCFG_SYSADRH:
- tmp_ipb_adr = (u32)mb->data << 16;
- break;
-
- case DSPCFG_SYSADRL:
- tmp_ipb_adr |= mb->data;
- break;
-
- case DSPCFG_ABORT:
- goto abort1;
-
- default:
- printk(KERN_ERR
- "mbox: Unknown CFG command: cmd_l=0x%02x, data=0x%04x\n",
- mb->cmd_l, mb->data);
- return;
- }
-
- if (last) {
- void *badr;
- u16 bln;
- u16 bsz;
- volatile u16 *buf;
- void *ipb_sys_da, *ipb_sys_ad;
- void *mbseq; /* FIXME: 3.4 obsolete */
- short *dbg_buf;
- u16 dbg_buf_sz, dbg_line_sz;
- struct mem_sync_struct mem_sync, *mem_syncp;
-
- ipb_sys_da = dspword_to_virt(tmp_ipb_adr);
- if (ipbuf_sys_config(ipb_sys_da, DIR_D2A) < 0)
- goto abort1;
-
- if (dsp_mem_enable(ipbuf_sys_da) < 0) {
- printk(KERN_ERR "mbox: DSPCFG - ipbuf_sys_da read failed!\n");
- goto abort1;
- }
- if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
- printk(KERN_ERR "mbox: DSPCFG - IPBUF sync failed!\n");
- dsp_mem_disable(ipbuf_sys_da);
- goto abort1;
- }
- /*
- * read configuration data on system IPBUF
- * we must read with 16bit-access
- */
-#ifdef OLD_BINARY_SUPPORT
- if (mbox_revision == MBPROT_REVISION) {
-#endif
- 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 = 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 (mbox_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 (mbox_revision == MBREV_3_0) {
- buf = ipbuf_sys_da->d;
- 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 */
- dsp_mem_disable(ipbuf_sys_da);
- goto abort1;
- }
-#endif /* OLD_BINARY_SUPPORT */
-
- release_ipbuf_pvt(ipbuf_sys_da);
- dsp_mem_disable(ipbuf_sys_da);
-
- /*
- * following configurations need to be done before
- * 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_mbox_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;
-
- misc_mb_wait.cmd_h = 0;
- wake_up_interruptible(&misc_mb_wait.wait_q);
- }
- return;
-
-abort2:
- ipbuf_stop();
-abort1:
- wake_up_interruptible(&misc_mb_wait.wait_q);
- return;
-}
-
-void mbox_poll(struct mbcmd *mb)
-{
- misc_mbcmd_response(mb, 0, 0);
-}
-
-void mbox_regrw(struct mbcmd *mb)
-{
- switch (mb->cmd_l) {
- case REGRW_DATA:
- misc_mbcmd_response(mb, 1, 0);
- break;
- default:
- printk(KERN_ERR
- "mbox: Illegal REGRW command: "
- "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
- return;
- }
-}
-
-void mbox_getvar(struct mbcmd *mb)
-{
- switch (mb->cmd_l) {
- case VARID_ICRMASK:
- misc_mbcmd_response(mb, 1, 1);
- break;
- case VARID_LOADINFO:
- misc_mbcmd_response(mb, 5, 1);
- break;
- default:
- printk(KERN_ERR
- "mbox: Illegal GETVAR command: "
- "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
- return;
- }
-}
-
-void mbox_fbctl_disable(struct mbcmd *mb)
-{
- misc_mbcmd_response(mb, 0, 0);
-}
-
-struct file_operations dsp_ctl_fops = {
- .owner = THIS_MODULE,
- .ioctl = dsp_ctl_ioctl,
-};
-
-/*
- * sysfs files
- */
-
-/* ifver */
-static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- int len = 0;
-
- /*
- * I/F VERSION descriptions:
- *
- * 3.2: sysfs / udev support
- * KMEM_RESERVE / KMEM_RELEASE ioctls for mem device
- * 3.3: added following ioctls
- * DSPCTL_IOCTL_GBL_IDLE
- * DSPCTL_IOCTL_CPU_IDLE (instead of DSPCTL_IOCTL_IDLE)
- * DSPCTL_IOCTL_POLL
- */
-
- /*
- * print all supporting I/F VERSIONs, like followings.
- *
- * 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;
-}
-
-/* cpustat */
-static char *cpustat_name[CPUSTAT_MAX] = {
- [CPUSTAT_RESET] = "reset",
-#ifdef CONFIG_ARCH_OMAP1
- [CPUSTAT_GBL_IDLE] = "gbl_idle",
- [CPUSTAT_CPU_IDLE] = "cpu_idle",
-#endif
- [CPUSTAT_RUN] = "run",
-};
-
-static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%s\n", cpustat_name[dsp_cpustat_get_stat()]);
-}
-
-/* icrmask */
-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)
-{
- u16 mask;
- int ret;
-
- mask = simple_strtol(buf, NULL, 16);
- dsp_cpustat_set_icrmask(mask);
-
- if (dsp_cfgstat_get_stat() == CFGSTAT_READY) {
- ret = dsp_setvar(VARID_ICRMASK, mask);
- if (ret < 0)
- return ret;
- }
-
- return count;
-}
-
-/* loadinfo */
-static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- int len;
- int ret;
- u16 val[5];
-
- if ((ret = dsp_getvar(VARID_LOADINFO, val)) < 0)
- return ret;
-
- /*
- * load info value range is 0(free) - 10000(busy):
- * if CPU load is not measured on DSP, it sets 0xffff at val[0].
- */
-
- if (val[0] == 0xffff) {
- len = sprintf(buf,
- "currently DSP load info is not available.\n");
- goto out;
- }
-
- len = sprintf(buf,
- "DSP load info:\n"
- " 10ms average = %3d.%02d%%\n"
- " 1sec average = %3d.%02d%% busiest 10ms = %3d.%02d%%\n"
- " 1min average = %3d.%02d%% busiest 1s = %3d.%02d%%\n",
- val[0]/100, val[0]%100,
- val[1]/100, val[1]%100, val[2]/100, val[2]%100,
- val[3]/100, val[3]%100, val[4]/100, val[4]%100);
-out:
- return len;
-}
-
-int __init dsp_ctl_init(void)
-{
- int ret;
-
- ret = device_create_file(omap_dsp->dev, &dev_attr_ifver);
- if (unlikely(ret))
- return ret;
- ret = device_create_file(omap_dsp->dev, &dev_attr_cpustat);
- if (unlikely(ret))
- goto fail_create_cpustat;
- ret = device_create_file(omap_dsp->dev, &dev_attr_icrmask);
- if (unlikely(ret))
- goto fail_create_icrmask;
-
- return 0;
-
-fail_create_icrmask:
- device_remove_file(omap_dsp->dev, &dev_attr_cpustat);
-fail_create_cpustat:
- device_remove_file(omap_dsp->dev, &dev_attr_ifver);
-
- return ret;
-}
-
-void dsp_ctl_exit(void)
-{
- device_remove_file(omap_dsp->dev, &dev_attr_ifver);
- device_remove_file(omap_dsp->dev, &dev_attr_cpustat);
- device_remove_file(omap_dsp->dev, &dev_attr_icrmask);
-}
diff --git a/arch/arm/plat-omap/dsp/dsp_ctl_core.c b/arch/arm/plat-omap/dsp/dsp_ctl_core.c
deleted file mode 100644
index 956ef26..0000000
--- a/arch/arm/plat-omap/dsp/dsp_ctl_core.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include "dsp.h"
-
-#define CTL_MINOR 0
-#define MEM_MINOR 1
-#define TWCH_MINOR 2
-#define ERR_MINOR 3
-
-static struct class *dsp_ctl_class;
-extern struct file_operations dsp_ctl_fops,
- dsp_mem_fops,
- dsp_twch_fops,
- dsp_err_fops;
-
-static int dsp_ctl_core_open(struct inode *inode, struct file *file)
-{
- static DEFINE_MUTEX(open_lock);
- int ret = 0;
-
- if (mutex_lock_interruptible(&open_lock))
- return -EINTR;
- if (omap_dsp->initialized == 0) {
- ret = dsp_late_init();
- if (ret != 0) {
- mutex_unlock(&open_lock);
- return ret;
- }
- omap_dsp->initialized = 1;
- }
- mutex_unlock(&open_lock);
-
- switch (iminor(inode)) {
- case CTL_MINOR:
- file->f_op = &dsp_ctl_fops;
- break;
- case MEM_MINOR:
- file->f_op = &dsp_mem_fops;
- break;
- case TWCH_MINOR:
- file->f_op = &dsp_twch_fops;
- break;
- case ERR_MINOR:
- file->f_op = &dsp_err_fops;
- break;
- default:
- return -ENXIO;
- }
- if (file->f_op && file->f_op->open)
- return file->f_op->open(inode, file);
- return 0;
-}
-
-static struct file_operations dsp_ctl_core_fops = {
- .owner = THIS_MODULE,
- .open = dsp_ctl_core_open,
-};
-
-static const struct dev_list {
- unsigned int minor;
- char *devname;
- umode_t mode;
-} dev_list[] = {
- {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)
-{
- int retval;
- int i;
-
- retval = register_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl",
- &dsp_ctl_core_fops);
- if (retval < 0) {
- printk(KERN_ERR
- "omapdsp: failed to register dspctl device: %d\n",
- retval);
- return retval;
- }
-
- dsp_ctl_class = class_create(THIS_MODULE, "dspctl");
- for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
- device_create(dsp_ctl_class, NULL,
- MKDEV(OMAP_DSP_CTL_MAJOR,
- dev_list[i].minor),
- dev_list[i].devname);
- }
-
- return 0;
-}
-
-void dsp_ctl_core_exit(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
- device_destroy(dsp_ctl_class,
- MKDEV(OMAP_DSP_CTL_MAJOR,
- dev_list[i].minor));
- }
- class_destroy(dsp_ctl_class);
-
- unregister_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl");
-}
diff --git a/arch/arm/plat-omap/dsp/dsp_mbcmd.h b/arch/arm/plat-omap/dsp/dsp_mbcmd.h
deleted file mode 100644
index fb35749..0000000
--- a/arch/arm/plat-omap/dsp/dsp_mbcmd.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __PLAT_OMAP_DSP_MBCMD_H
-#define __PLAT_OMAP_DSP_MBCMD_H
-/*
- * mailbox command: 0x00 - 0x7f
- * when a driver wants to use mailbox, it must reserve mailbox commands here.
- */
-#define MBOX_CMD_DSP_WDSND 0x10
-#define MBOX_CMD_DSP_WDREQ 0x11
-#define MBOX_CMD_DSP_BKSND 0x20
-#define MBOX_CMD_DSP_BKREQ 0x21
-#define MBOX_CMD_DSP_BKYLD 0x23
-#define MBOX_CMD_DSP_BKSNDP 0x24
-#define MBOX_CMD_DSP_BKREQP 0x25
-#define MBOX_CMD_DSP_TCTL 0x30
-#define MBOX_CMD_DSP_TCTLDATA 0x31
-#define MBOX_CMD_DSP_POLL 0x32
-#define MBOX_CMD_DSP_WDT 0x50
-#define MBOX_CMD_DSP_RUNLEVEL 0x51
-#define MBOX_CMD_DSP_PM 0x52
-#define MBOX_CMD_DSP_SUSPEND 0x53
-#define MBOX_CMD_DSP_KFUNC 0x54
-#define MBOX_CMD_DSP_TCFG 0x60
-#define MBOX_CMD_DSP_TADD 0x62
-#define MBOX_CMD_DSP_TDEL 0x63
-#define MBOX_CMD_DSP_TSTOP 0x65
-#define MBOX_CMD_DSP_DSPCFG 0x70
-#define MBOX_CMD_DSP_REGRW 0x72
-#define MBOX_CMD_DSP_GETVAR 0x74
-#define MBOX_CMD_DSP_SETVAR 0x75
-#define MBOX_CMD_DSP_ERR 0x78
-#define MBOX_CMD_DSP_DBG 0x79
-
-/*
- * DSP mailbox protocol definitions
- */
-#define MBPROT_REVISION 0x0019
-
-#define TCTL_TINIT 0x0000
-#define TCTL_TEN 0x0001
-#define TCTL_TDIS 0x0002
-#define TCTL_TCLR 0x0003
-#define TCTL_TCLR_FORCE 0x0004
-
-#define RUNLEVEL_USER 0x01
-#define RUNLEVEL_SUPER 0x0e
-#define RUNLEVEL_RECOVERY 0x10
-
-#define PM_DISABLE 0x00
-#define PM_ENABLE 0x01
-
-#define KFUNC_FBCTL 0x00
-#define KFUNC_POWER 0x01
-
-#define FBCTL_UPD 0x0000
-#define FBCTL_ENABLE 0x0002
-#define FBCTL_DISABLE 0x0003
-
-/* KFUNC_POWER */
-#define AUDIO_PWR_UP 0x0000 /* ARM(exe/ack) <-> DSP(req) */
-#define AUDIO_PWR_DOWN 0x0001 /* ARM(exe) <- DSP(req) */
-#define AUDIO_PWR_DOWN1 AUDIO_PWR_DOWN
-#define AUDIO_PWR_DOWN2 0x0002
-#define DSP_PWR_UP 0x0003 /* ARM(exe/snd) -> DSP(exe) */
-#define DSP_PWR_DOWN 0x0004 /* ARM(exe) <- DSP(req) */
-#define DVFS_START 0x0006 /* ARM(req) <-> DSP(exe/ack)*/
-#define DVFS_STOP 0x0007 /* ARM(req) -> DSP(exe) */
-
-#define TDEL_SAFE 0x0000
-#define TDEL_KILL 0x0001
-
-#define DSPCFG_REQ 0x00
-#define DSPCFG_SYSADRH 0x28
-#define DSPCFG_SYSADRL 0x29
-#define DSPCFG_PROTREV 0x70
-#define DSPCFG_ABORT 0x78
-#define DSPCFG_LAST 0x80
-
-#define REGRW_MEMR 0x00
-#define REGRW_MEMW 0x01
-#define REGRW_IOR 0x02
-#define REGRW_IOW 0x03
-#define REGRW_DATA 0x04
-
-#define VARID_ICRMASK 0x00
-#define VARID_LOADINFO 0x01
-
-#define TTYP_ARCV 0x0001
-#define TTYP_ASND 0x0002
-#define TTYP_BKMD 0x0004
-#define TTYP_BKDM 0x0008
-#define TTYP_PVMD 0x0010
-#define TTYP_PVDM 0x0020
-
-#define EID_BADTID 0x10
-#define EID_BADTCN 0x11
-#define EID_BADBID 0x20
-#define EID_BADCNT 0x21
-#define EID_NOTLOCKED 0x22
-#define EID_STVBUF 0x23
-#define EID_BADADR 0x24
-#define EID_BADTCTL 0x30
-#define EID_BADPARAM 0x50
-#define EID_FATAL 0x58
-#define EID_NOMEM 0xc0
-#define EID_NORES 0xc1
-#define EID_IPBFULL 0xc2
-#define EID_WDT 0xd0
-#define EID_TASKNOTRDY 0xe0
-#define EID_TASKBSY 0xe1
-#define EID_TASKERR 0xef
-#define EID_BADCFGTYP 0xf0
-#define EID_DEBUG 0xf8
-#define EID_BADSEQ 0xfe
-#define EID_BADCMD 0xff
-
-#define TNM_LEN 16
-
-#define TID_FREE 0xff
-#define TID_ANON 0xfe
-
-#define BID_NULL 0xffff
-#define BID_PVT 0xfffe
-
-#endif /* __PLAT_OMAP_DSP_MBCMD_H */
diff --git a/arch/arm/plat-omap/dsp/dsp_mem.c b/arch/arm/plat-omap/dsp/dsp_mem.c
deleted file mode 100644
index ca87a3a..0000000
--- a/arch/arm/plat-omap/dsp/dsp_mem.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * Conversion to mempool API and ARM MMU section mapping
- * by Paul Mundt <paul.mundt@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/fb.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/mempool.h>
-#include <linux/clk.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/arch/tc.h>
-#include <asm/arch/omapfb.h>
-#include <asm/arch/dsp.h>
-#include <asm/arch/mailbox.h>
-#include <asm/arch/mmu.h>
-#include "dsp_mbcmd.h"
-#include "dsp.h"
-#include "ipbuf.h"
-
-#if defined(CONFIG_ARCH_OMAP1)
-#include "../../mach-omap1/mmu.h"
-#elif defined(CONFIG_ARCH_OMAP2)
-#include "../../mach-omap2/mmu.h"
-#endif
-
-#include "mmu.h"
-
-static struct mem_sync_struct mem_sync;
-
-int dsp_mem_sync_inc(void)
-{
- if (dsp_mem_enable((void *)dspmem_base) < 0)
- return -1;
- 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_disable((void *)dspmem_base);
-
- return 0;
-}
-
-/*
- * dsp_mem_sync_config() is called from mbox1 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;
-}
-
-
-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(&dsp_mmu.exmap_sem);
- if (exmap_valid(&dsp_mmu, vadr, len))
- ret = MEM_TYPE_EXTERN;
- else
- ret = MEM_TYPE_NONE;
- up_read(&dsp_mmu.exmap_sem);
- return ret;
- }
-}
-
-int dsp_address_validate(void *p, size_t len, char *fmt, ...)
-{
- char s[64];
- va_list args;
-
- if (dsp_mem_type(p, len) > 0)
- return 0;
-
- if (fmt == NULL)
- goto out;
-
- 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 external memory\n"
- "space where no actual memory is mapped)\n", s, p, len);
- out:
- return -1;
-}
-
-#ifdef CONFIG_OMAP_DSP_FBEXPORT
-
-static inline unsigned long lineup_offset(unsigned long adr,
- unsigned long ref,
- unsigned long mask)
-{
- unsigned long newadr;
-
- newadr = (adr & ~mask) | (ref & mask);
- if (newadr < adr)
- newadr += mask + 1;
- return newadr;
-}
-
-/*
- * fb update functions:
- * fbupd_response() is executed by the workqueue.
- * fbupd_cb() is called when fb update is done, in interrupt context.
- * mbox_fbupd() is called when KFUNC:FBCTL:UPD is received from DSP.
- */
-static void fbupd_response(struct work_struct *unused)
-{
- int status;
-
- status = mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_UPD);
- if (status == 0)
- return;
-
- /* FIXME: DSP is busy !! */
- printk(KERN_ERR
- "omapdsp:"
- "DSP is busy when trying to send FBCTL:UPD response!\n");
-}
-
-static DECLARE_WORK(fbupd_response_work, fbupd_response);
-
-static void fbupd_cb(void *arg)
-{
- schedule_work(&fbupd_response_work);
-}
-
-void mbox_fbctl_upd(void)
-{
- struct omapfb_update_window win;
- volatile unsigned short *buf = ipbuf_sys_da->d;
-
- if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 5000) < 0) {
- printk(KERN_ERR "mbox: FBCTL:UPD - IPBUF sync failed!\n");
- return;
- }
- win.x = buf[0];
- win.y = buf[1];
- win.width = buf[2];
- win.height = buf[3];
- win.format = buf[4];
- release_ipbuf_pvt(ipbuf_sys_da);
-
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
- if (!omapfb_ready) {
- printk(KERN_WARNING
- "omapdsp: fbupd() called while HWA742 is not ready!\n");
- return;
- }
-#endif
- omapfb_update_window_async(registered_fb[0], &win, fbupd_cb, NULL);
-}
-
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
-static int omapfb_notifier_cb(struct notifier_block *omapfb_nb,
- unsigned long event, void *fbi)
-{
- pr_info("omapfb_notifier_cb(): event = %s\n",
- (event == OMAPFB_EVENT_READY) ? "READY" :
- (event == OMAPFB_EVENT_DISABLED) ? "DISABLED" : "Unknown");
- if (event == OMAPFB_EVENT_READY)
- omapfb_ready = 1;
- else if (event == OMAPFB_EVENT_DISABLED)
- omapfb_ready = 0;
- return 0;
-}
-#endif
-
-static int dsp_fbexport(dsp_long_t *dspadr)
-{
- dsp_long_t dspadr_actual;
- unsigned long padr_sys, padr, fbsz_sys, fbsz;
- int cnt;
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
- int status;
-#endif
-
- pr_debug( "omapdsp: frame buffer export\n");
-
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
- if (omapfb_nb) {
- printk(KERN_WARNING
- "omapdsp: frame buffer has been exported already!\n");
- return -EBUSY;
- }
-#endif
-
- if (num_registered_fb == 0) {
- pr_info("omapdsp: frame buffer not registered.\n");
- return -EINVAL;
- }
- if (num_registered_fb != 1) {
- pr_info("omapdsp: %d frame buffers found. we use first one.\n",
- num_registered_fb);
- }
- padr_sys = registered_fb[0]->fix.smem_start;
- fbsz_sys = registered_fb[0]->fix.smem_len;
- if (fbsz_sys == 0) {
- printk(KERN_ERR
- "omapdsp: framebuffer doesn't seem to be configured "
- "correctly! (size=0)\n");
- return -EINVAL;
- }
-
- /*
- * align padr and fbsz to 4kB boundary
- * (should be noted to the user afterwards!)
- */
- padr = padr_sys & ~(SZ_4K-1);
- fbsz = (fbsz_sys + padr_sys - padr + SZ_4K-1) & ~(SZ_4K-1);
-
- /* line up dspadr offset with padr */
- dspadr_actual =
- (fbsz > SZ_1M) ? lineup_offset(*dspadr, padr, SZ_1M-1) :
- (fbsz > SZ_64K) ? lineup_offset(*dspadr, padr, SZ_64K-1) :
- /* (fbsz > SZ_4KB) ? */ *dspadr;
- if (dspadr_actual != *dspadr)
- pr_debug(
- "omapdsp: actual dspadr for FBEXPORT = %08x\n",
- dspadr_actual);
- *dspadr = dspadr_actual;
-
- cnt = omap_mmu_exmap(&dsp_mmu, dspadr_actual, padr, fbsz,
- EXMAP_TYPE_FB);
- if (cnt < 0) {
- printk(KERN_ERR "omapdsp: exmap failure.\n");
- return cnt;
- }
-
- if ((padr != padr_sys) || (fbsz != fbsz_sys)) {
- printk(KERN_WARNING
-" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
-" !! screen base address or size is not aligned in 4kB: !!\n"
-" !! actual screen adr = %08lx, size = %08lx !!\n"
-" !! exporting adr = %08lx, size = %08lx !!\n"
-" !! Make sure that the framebuffer is allocated with 4kB-order! !!\n"
-" !! Otherwise DSP can corrupt the kernel memory. !!\n"
-" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",
- padr_sys, fbsz_sys, padr, fbsz);
- }
-
- /* increase the DMA priority */
- set_emiff_dma_prio(15);
-
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
- omapfb_nb = kzalloc(sizeof(struct omapfb_notifier_block), GFP_KERNEL);
- if (omapfb_nb == NULL) {
- printk(KERN_ERR
- "omapdsp: failed to allocate memory for omapfb_nb!\n");
- omap_mmu_exunmap(&dsp_mmu, (unsigned long)dspadr);
- return -ENOMEM;
- }
-
- status = omapfb_register_client(omapfb_nb, omapfb_notifier_cb, NULL);
- if (status)
- pr_info("omapfb_register_client(): failure(%d)\n", status);
-#endif
-
- return cnt;
-}
-#else
-void mbox_fbctl_upd(void) { }
-#endif
-
-/* dsp/mem fops: backward compatibility */
-static ssize_t dsp_mem_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- struct bin_attribute attr;
-
- return __omap_mmu_mem_read(&dsp_mmu, &attr,
- (char __user *)buf, *ppos, count);
-}
-
-static ssize_t dsp_mem_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct bin_attribute attr;
-
- return __omap_mmu_mem_write(&dsp_mmu, &attr,
- (char __user *)buf, *ppos, count);
-}
-
-static int dsp_mem_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct omap_dsp_mapinfo mapinfo;
- __u32 size;
-
- switch (cmd) {
- case MEM_IOCTL_MMUINIT:
- if (dsp_mmu.exmap_tbl)
- omap_mmu_unregister(&dsp_mmu);
- dsp_mem_ipi_init();
- return omap_mmu_register(&dsp_mmu);
-
- case MEM_IOCTL_EXMAP:
- if (copy_from_user(&mapinfo, (void __user *)arg,
- sizeof(mapinfo)))
- return -EFAULT;
- return omap_mmu_exmap(&dsp_mmu, mapinfo.dspadr,
- 0, mapinfo.size, EXMAP_TYPE_MEM);
-
- case MEM_IOCTL_EXUNMAP:
- return omap_mmu_exunmap(&dsp_mmu, (unsigned long)arg);
-
- case MEM_IOCTL_EXMAP_FLUSH:
- omap_mmu_exmap_flush(&dsp_mmu);
- return 0;
-#ifdef CONFIG_OMAP_DSP_FBEXPORT
- case MEM_IOCTL_FBEXPORT:
- {
- dsp_long_t dspadr;
- int ret;
- if (copy_from_user(&dspadr, (void __user *)arg,
- sizeof(dsp_long_t)))
- return -EFAULT;
- ret = dsp_fbexport(&dspadr);
- if (copy_to_user((void __user *)arg, &dspadr,
- sizeof(dsp_long_t)))
- return -EFAULT;
- return ret;
- }
-#endif
- case MEM_IOCTL_MMUITACK:
- return dsp_mmu_itack();
-
- case MEM_IOCTL_KMEM_RESERVE:
-
- if (copy_from_user(&size, (void __user *)arg,
- sizeof(__u32)))
- return -EFAULT;
- return omap_mmu_kmem_reserve(&dsp_mmu, size);
-
-
- case MEM_IOCTL_KMEM_RELEASE:
- omap_mmu_kmem_release();
- return 0;
-
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-struct file_operations dsp_mem_fops = {
- .owner = THIS_MODULE,
- .read = dsp_mem_read,
- .write = dsp_mem_write,
- .ioctl = dsp_mem_ioctl,
-};
-
-void dsp_mem_start(void)
-{
- 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();
-}
-
-static void dsp_mmu_irq_work(struct work_struct *work)
-{
- struct omap_mmu *mmu = container_of(work, struct omap_mmu, irq_work);
-
- if (dsp_cfgstat_get_stat() == CFGSTAT_READY) {
- dsp_err_set(ERRCODE_MMU, mmu->fault_address);
- return;
- }
- omap_mmu_itack(mmu);
- pr_info("Resetting DSP...\n");
- dsp_cpustat_request(CPUSTAT_RESET);
- omap_mmu_enable(mmu, 0);
-}
-
-/*
- * later half of dsp memory initialization
- */
-int dsp_mem_late_init(void)
-{
- int ret;
-
- dsp_mem_ipi_init();
-
- INIT_WORK(&dsp_mmu.irq_work, dsp_mmu_irq_work);
- ret = omap_mmu_register(&dsp_mmu);
- if (ret) {
- dsp_reset_idle_boot_base();
- goto out;
- }
- omap_dsp->mmu = &dsp_mmu;
- out:
- return ret;
-}
-
-int __init dsp_mem_init(void)
-{
-#ifdef CONFIG_ARCH_OMAP2
- dsp_mmu.clk = dsp_fck_handle;
- dsp_mmu.memclk = dsp_ick_handle;
-#elif defined(CONFIG_ARCH_OMAP1)
- dsp_mmu.clk = dsp_ck_handle;
- dsp_mmu.memclk = api_ck_handle;
-#endif
- return 0;
-}
-
-void dsp_mem_exit(void)
-{
- dsp_reset_idle_boot_base();
- omap_mmu_unregister(&dsp_mmu);
-}
diff --git a/arch/arm/plat-omap/dsp/error.c b/arch/arm/plat-omap/dsp/error.c
deleted file mode 100644
index d2276f9..0000000
--- a/arch/arm/plat-omap/dsp/error.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/arch/mailbox.h>
-#include <asm/uaccess.h>
-#include "dsp_mbcmd.h"
-#include "dsp.h"
-
-/*
- * value seen through read()
- */
-#define DSP_ERR_WDT 0x00000001
-#define DSP_ERR_MMU 0x00000002
-static unsigned long errval;
-
-static DECLARE_WAIT_QUEUE_HEAD(err_wait_q);
-static int errcnt;
-static u16 wdtval; /* FIXME: read through ioctl */
-static u32 mmu_fadr; /* FIXME: read through ioctl */
-
-/*
- * DSP error detection device file operations
- */
-static ssize_t dsp_err_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- unsigned long flags;
- int status;
- DEFINE_WAIT(wait);
-
- if (count < 4)
- return 0;
-
- prepare_to_wait(&err_wait_q, &wait, TASK_INTERRUPTIBLE);
- if (errcnt == 0)
- schedule();
- finish_wait(&err_wait_q, &wait);
- if (signal_pending(current))
- return -EINTR;
-
- local_irq_save(flags);
- status = copy_to_user(buf, &errval, 4);
- if (status) {
- local_irq_restore(flags);
- return -EFAULT;
- }
- errcnt = 0;
- local_irq_restore(flags);
-
- return 4;
-}
-
-static unsigned int dsp_err_poll(struct file *file, poll_table *wait)
-{
- unsigned int mask = 0;
-
- poll_wait(file, &err_wait_q, wait);
- if (errcnt != 0)
- mask |= POLLIN | POLLRDNORM;
-
- return mask;
-}
-
-struct file_operations dsp_err_fops = {
- .owner = THIS_MODULE,
- .poll = dsp_err_poll,
- .read = dsp_err_read,
-};
-
-/*
- * set / clear functions
- */
-
-/* DSP MMU */
-static void dsp_err_mmu_set(unsigned long arg)
-{
- disable_irq(omap_dsp->mmu->irq);
- mmu_fadr = (u32)arg;
-}
-
-static void dsp_err_mmu_clr(void)
-{
- enable_irq(omap_dsp->mmu->irq);
-}
-
-/* WDT */
-static void dsp_err_wdt_set(unsigned long arg)
-{
- wdtval = (u16)arg;
-}
-
-/*
- * error code handler
- */
-static struct {
- unsigned long val;
- void (*set)(unsigned long arg);
- void (*clr)(void);
-} dsp_err_desc[ERRCODE_MAX] = {
- [ERRCODE_MMU] = { DSP_ERR_MMU, dsp_err_mmu_set, dsp_err_mmu_clr },
- [ERRCODE_WDT] = { DSP_ERR_WDT, dsp_err_wdt_set, NULL },
-};
-
-void dsp_err_set(enum errcode_e code, unsigned long arg)
-{
- if (dsp_err_desc[code].set != NULL)
- dsp_err_desc[code].set(arg);
-
- errval |= dsp_err_desc[code].val;
- errcnt++;
- wake_up_interruptible(&err_wait_q);
-}
-
-void dsp_err_clear(enum errcode_e code)
-{
- errval &= ~dsp_err_desc[code].val;
-
- if (dsp_err_desc[code].clr != NULL)
- dsp_err_desc[code].clr();
-}
-
-int dsp_err_isset(enum errcode_e code)
-{
- return (errval & dsp_err_desc[code].val) ? 1 : 0;
-}
-
-void dsp_err_notify(void)
-{
- /* new error code should be assigned */
- dsp_err_set(DSP_ERR_WDT, 0);
-}
-
-/*
- * functions called from mailbox interrupt routine
- */
-static void mbox_err_wdt(u16 data)
-{
- dsp_err_set(DSP_ERR_WDT, (unsigned long)data);
-}
-
-#ifdef OLD_BINARY_SUPPORT
-/* v3.3 obsolete */
-void mbox_wdt(struct mbcmd *mb)
-{
- mbox_err_wdt(mb->data);
-}
-#endif
-
-extern void mbox_err_ipbfull(void);
-extern void mbox_err_fatal(u8 tid);
-
-void mbox_err(struct mbcmd *mb)
-{
- u8 eid = mb->cmd_l;
- char *eidnm = subcmd_name(mb);
- u8 tid;
-
- if (eidnm) {
- printk(KERN_WARNING
- "mbox: ERR from DSP (%s): 0x%04x\n", eidnm, mb->data);
- } else {
- printk(KERN_WARNING
- "mbox: ERR from DSP (unknown EID=%02x): %04x\n",
- eid, mb->data);
- }
-
- switch (eid) {
- case EID_IPBFULL:
- mbox_err_ipbfull();
- break;
-
- case EID_FATAL:
- tid = mb->data & 0x00ff;
- mbox_err_fatal(tid);
- break;
-
- case EID_WDT:
- mbox_err_wdt(mb->data);
- break;
- }
-}
-
-/*
- *
- */
-void dsp_err_start(void)
-{
- enum errcode_e i;
-
- for (i = 0; i < ERRCODE_MAX; i++) {
- if (dsp_err_isset(i))
- dsp_err_clear(i);
- }
- omap_dsp->mbox->err_notify = dsp_err_notify;
- errcnt = 0;
-}
-
-void dsp_err_stop(void)
-{
- wake_up_interruptible(&err_wait_q);
- omap_dsp->mbox->err_notify = NULL;
-}
diff --git a/arch/arm/plat-omap/dsp/hardware_dsp.h b/arch/arm/plat-omap/dsp/hardware_dsp.h
deleted file mode 100644
index 5af46f8..0000000
--- a/arch/arm/plat-omap/dsp/hardware_dsp.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __OMAP_DSP_HARDWARE_DSP_H
-#define __OMAP_DSP_HARDWARE_DSP_H
-
-#ifdef CONFIG_ARCH_OMAP1
-#include "omap1_dsp.h"
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3430)
-#include "omap2_dsp.h"
-#endif
-
-#endif /* __OMAP_DSP_HARDWARE_DSP_H */
diff --git a/arch/arm/plat-omap/dsp/ipbuf.c b/arch/arm/plat-omap/dsp/ipbuf.c
deleted file mode 100644
index aba8e74..0000000
--- a/arch/arm/plat-omap/dsp/ipbuf.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/sched.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <asm/arch/mailbox.h>
-#include "dsp_mbcmd.h"
-#include "dsp.h"
-#include "ipbuf.h"
-
-static struct ipbuf_head *g_ipbuf;
-struct ipbcfg ipbcfg;
-struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
-static struct ipblink ipb_free = IPBLINK_INIT;
-static int ipbuf_sys_hold_mem_active;
-
-static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
- char *buf);
-static struct device_attribute dev_attr_ipbuf = __ATTR_RO(ipbuf);
-
-void ipbuf_stop(void)
-{
- int i;
-
- device_remove_file(omap_dsp->dev, &dev_attr_ipbuf);
-
- spin_lock(&ipb_free.lock);
- RESET_IPBLINK(&ipb_free);
- spin_unlock(&ipb_free.lock);
-
- ipbcfg.ln = 0;
- if (g_ipbuf) {
- kfree(g_ipbuf);
- g_ipbuf = NULL;
- }
- for (i = 0; i < ipbuf_sys_hold_mem_active; i++) {
- dsp_mem_disable((void *)daram_base);
- }
- ipbuf_sys_hold_mem_active = 0;
-}
-
-int ipbuf_config(u16 ln, u16 lsz, void *base)
-{
- size_t lsz_byte = ((size_t)lsz) << 1;
- size_t size;
- int ret = 0;
- int i;
-
- /*
- * global IPBUF
- */
- if (((unsigned long)base) & 0x3) {
- printk(KERN_ERR
- "omapdsp: global ipbuf address(0x%p) is not "
- "32-bit aligned!\n", base);
- return -EINVAL;
- }
- size = lsz_byte * ln;
- if (dsp_address_validate(base, size, "global ipbuf") < 0)
- return -EINVAL;
-
- g_ipbuf = kmalloc(sizeof(struct ipbuf_head) * ln, GFP_KERNEL);
- if (g_ipbuf == NULL) {
- printk(KERN_ERR
- "omapdsp: memory allocation for ipbuf failed.\n");
- return -ENOMEM;
- }
- for (i = 0; i < ln; i++) {
- void *top, *btm;
-
- top = base + (sizeof(struct ipbuf) + lsz_byte) * i;
- btm = base + (sizeof(struct ipbuf) + lsz_byte) * (i+1) - 1;
- g_ipbuf[i].p = (struct ipbuf *)top;
- g_ipbuf[i].bid = i;
- if (((unsigned long)top & 0xfffe0000) !=
- ((unsigned long)btm & 0xfffe0000)) {
- /*
- * an ipbuf line should not cross
- * 64k-word boundary.
- */
- printk(KERN_ERR
- "omapdsp: ipbuf[%d] crosses 64k-word boundary!\n"
- " @0x%p, size=0x%08x\n", i, top, lsz_byte);
- ret = -EINVAL;
- goto free_out;
- }
- }
- ipbcfg.ln = ln;
- ipbcfg.lsz = lsz;
- ipbcfg.base = base;
- ipbcfg.bsycnt = ln; /* DSP holds all ipbufs initially. */
- ipbcfg.cnt_full = 0;
-
- pr_info("omapdsp: IPBUF configuration\n"
- " %d words * %d lines at 0x%p.\n",
- ipbcfg.lsz, ipbcfg.ln, ipbcfg.base);
-
- ret = device_create_file(omap_dsp->dev, &dev_attr_ipbuf);
- if (ret)
- printk(KERN_ERR "device_create_file failed: %d\n", ret);
-
- return ret;
-
- free_out:
- kfree(g_ipbuf);
- g_ipbuf = NULL;
- return ret;
-}
-
-int ipbuf_sys_config(void *p, arm_dsp_dir_t 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, arm_dsp_dir_t 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);
-}
-
-/*
- * Global IPBUF operations
- */
-struct ipbuf_head *bid_to_ipbuf(u16 bid)
-{
- return &g_ipbuf[bid];
-}
-
-struct ipbuf_head *get_free_ipbuf(u8 tid)
-{
- struct ipbuf_head *ipb_h;
-
- if (dsp_mem_enable_ipbuf() < 0)
- return NULL;
-
- spin_lock(&ipb_free.lock);
-
- if (ipblink_empty(&ipb_free)) {
- /* FIXME: wait on queue when not available. */
- ipb_h = NULL;
- goto out;
- }
- ipb_h = &g_ipbuf[ipb_free.top];
- ipb_h->p->la = tid; /* lock */
- __ipblink_del_top(&ipb_free);
-out:
- spin_unlock(&ipb_free.lock);
- dsp_mem_disable_ipbuf();
-
- return ipb_h;
-}
-
-void release_ipbuf(struct ipbuf_head *ipb_h)
-{
- if (ipb_h->p->la == TID_FREE) {
- printk(KERN_WARNING
- "omapdsp: attempt to release unlocked IPBUF[%d].\n",
- ipb_h->bid);
- /*
- * FIXME: re-calc bsycnt
- */
- return;
- }
- ipb_h->p->la = TID_FREE;
- ipb_h->p->sa = TID_FREE;
- ipblink_add_tail(&ipb_free, ipb_h->bid);
-}
-
-static int try_yld(struct ipbuf_head *ipb_h)
-{
- int status;
-
- ipb_h->p->sa = TID_ANON;
- status = mbcompose_send(BKYLD, 0, ipb_h->bid);
- if (status < 0) {
- /* DSP is busy and ARM keeps this line. */
- release_ipbuf(ipb_h);
- return status;
- }
-
- ipb_bsycnt_inc(&ipbcfg);
- return 0;
-}
-
-/*
- * balancing ipbuf lines with DSP
- */
-static void do_balance_ipbuf(struct work_struct *unused)
-{
- while (ipbcfg.bsycnt <= ipbcfg.ln / 4) {
- struct ipbuf_head *ipb_h;
-
- if ((ipb_h = get_free_ipbuf(TID_ANON)) == NULL)
- return;
- if (try_yld(ipb_h) < 0)
- return;
- }
-}
-
-static DECLARE_WORK(balance_ipbuf_work, do_balance_ipbuf);
-
-void balance_ipbuf(void)
-{
- schedule_work(&balance_ipbuf_work);
-}
-
-/* for process context */
-void unuse_ipbuf(struct ipbuf_head *ipb_h)
-{
- if (ipbcfg.bsycnt > ipbcfg.ln / 4) {
- /* we don't have enough IPBUF lines. let's keep it. */
- release_ipbuf(ipb_h);
- } else {
- /* we have enough IPBUF lines. let's return this line to DSP. */
- ipb_h->p->la = TID_ANON;
- try_yld(ipb_h);
- balance_ipbuf();
- }
-}
-
-/* for interrupt context */
-void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h)
-{
- release_ipbuf(ipb_h);
- balance_ipbuf();
-}
-
-/*
- * functions called from mailbox interrupt routine
- */
-
-void mbox_err_ipbfull(void)
-{
- ipbcfg.cnt_full++;
-}
-
-/*
- * sysfs files
- */
-static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- int len = 0;
- u16 bid;
-
- for (bid = 0; bid < ipbcfg.ln; bid++) {
- struct ipbuf_head *ipb_h = &g_ipbuf[bid];
- u16 la = ipb_h->p->la;
- u16 ld = ipb_h->p->ld;
- u16 c = ipb_h->p->c;
-
- if (len > PAGE_SIZE - 100) {
- len += sprintf(buf + len, "out of buffer.\n");
- goto finish;
- }
-
- len += sprintf(buf + len, "ipbuf[%d]: adr = 0x%p\n",
- bid, ipb_h->p);
- if (la == TID_FREE) {
- len += sprintf(buf + len,
- " DSPtask[%d]->Linux "
- "(already read and now free for Linux)\n",
- ld);
- } else if (ld == TID_FREE) {
- len += sprintf(buf + len,
- " Linux->DSPtask[%d] "
- "(already read and now free for DSP)\n",
- la);
- } else if (ipbuf_is_held(ld, bid)) {
- len += sprintf(buf + len,
- " DSPtask[%d]->Linux "
- "(waiting to be read)\n"
- " count = %d\n", ld, c);
- } else {
- len += sprintf(buf + len,
- " Linux->DSPtask[%d] "
- "(waiting to be read)\n"
- " count = %d\n", la, c);
- }
- }
-
- len += sprintf(buf + len, "\nFree IPBUF link: ");
- spin_lock(&ipb_free.lock);
- ipblink_for_each(bid, &ipb_free) {
- len += sprintf(buf + len, "%d ", bid);
- }
- spin_unlock(&ipb_free.lock);
- len += sprintf(buf + len, "\n");
- len += sprintf(buf + len, "IPBFULL error count: %ld\n",
- ipbcfg.cnt_full);
-
-finish:
- return len;
-}
diff --git a/arch/arm/plat-omap/dsp/ipbuf.h b/arch/arm/plat-omap/dsp/ipbuf.h
deleted file mode 100644
index 926d353..0000000
--- a/arch/arm/plat-omap/dsp/ipbuf.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __PLAT_OMAP_DSP_IPBUF_H
-#define __PLAT_OMAP_DSP_IPBUF_H
-
-struct ipbuf {
- u16 c; /* count */
- u16 next; /* link */
- u16 la; /* lock owner (ARM side) */
- u16 sa; /* sync word (ARM->DSP) */
- u16 ld; /* lock owner (DSP side) */
- u16 sd; /* sync word (DSP->ARM) */
- unsigned char d[0]; /* data */
-};
-
-struct ipbuf_p {
- u16 c; /* count */
- u16 s; /* sync word */
- u16 al; /* data address lower */
- u16 ah; /* data address upper */
-};
-
-#define IPBUF_SYS_DLEN 31
-
-struct ipbuf_sys {
- u16 s; /* sync word */
- u16 d[IPBUF_SYS_DLEN]; /* data */
-};
-
-struct ipbcfg {
- u16 ln;
- u16 lsz;
- void *base;
- u16 bsycnt;
- unsigned long cnt_full; /* count of IPBFULL error */
-};
-
-struct ipbuf_head {
- u16 bid;
- struct ipbuf *p;
-};
-
-extern struct ipbcfg ipbcfg;
-extern struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
-
-#define ipb_bsycnt_inc(ipbcfg) atomic_inc((atomic_t *)&((ipbcfg)->bsycnt))
-#define ipb_bsycnt_dec(ipbcfg) atomic_dec((atomic_t *)&((ipbcfg)->bsycnt))
-
-#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;
- u16 top;
- u16 tail;
-};
-
-#define IPBLINK_INIT { \
- .lock = SPIN_LOCK_UNLOCKED, \
- .top = BID_NULL, \
- .tail = BID_NULL, \
- }
-
-#define INIT_IPBLINK(link) \
- do { \
- spin_lock_init(&(link)->lock); \
- (link)->top = BID_NULL; \
- (link)->tail = BID_NULL; \
- } while(0)
-
-#define RESET_IPBLINK(link) \
- do { \
- (link)->top = BID_NULL; \
- (link)->tail = BID_NULL; \
- } while(0)
-
-#define ipblink_empty(link) ((link)->top == BID_NULL)
-
-static inline void __ipblink_del_top(struct ipblink *link)
-{
- struct ipbuf_head *ipb_h = bid_to_ipbuf(link->top);
-
- if ((link->top = ipb_h->p->next) == BID_NULL)
- link->tail = BID_NULL;
- else
- ipb_h->p->next = BID_NULL;
-}
-
-static inline void ipblink_del_top(struct ipblink *link)
-{
- spin_lock(&link->lock);
- __ipblink_del_top(link);
- spin_unlock(&link->lock);
-}
-
-static inline void __ipblink_add_tail(struct ipblink *link, u16 bid)
-{
- if (ipblink_empty(link))
- link->top = bid;
- else
- bid_to_ipbuf(link->tail)->p->next = bid;
- link->tail = bid;
-}
-
-static inline void ipblink_add_tail(struct ipblink *link, u16 bid)
-{
- spin_lock(&link->lock);
- __ipblink_add_tail(link, bid);
- spin_unlock(&link->lock);
-}
-
-static inline void __ipblink_flush(struct ipblink *link)
-{
- u16 bid;
-
- while (!ipblink_empty(link)) {
- bid = link->top;
- __ipblink_del_top(link);
- unuse_ipbuf(bid_to_ipbuf(bid));
- }
-}
-
-static inline void ipblink_flush(struct ipblink *link)
-{
- spin_lock(&link->lock);
- __ipblink_flush(link);
- spin_unlock(&link->lock);
-}
-
-static inline void __ipblink_add_pvt(struct ipblink *link)
-{
- link->top = BID_PVT;
- link->tail = BID_PVT;
-}
-
-static inline void ipblink_add_pvt(struct ipblink *link)
-{
- spin_lock(&link->lock);
- __ipblink_add_pvt(link);
- spin_unlock(&link->lock);
-}
-
-static inline void __ipblink_del_pvt(struct ipblink *link)
-{
- link->top = BID_NULL;
- link->tail = BID_NULL;
-}
-
-static inline void ipblink_del_pvt(struct ipblink *link)
-{
- spin_lock(&link->lock);
- __ipblink_del_pvt(link);
- spin_unlock(&link->lock);
-}
-
-static inline void __ipblink_flush_pvt(struct ipblink *link)
-{
- if (!ipblink_empty(link))
- ipblink_del_pvt(link);
-}
-
-static inline void ipblink_flush_pvt(struct ipblink *link)
-{
- spin_lock(&link->lock);
- __ipblink_flush_pvt(link);
- spin_unlock(&link->lock);
-}
-
-#define ipblink_for_each(bid, link) \
- for (bid = (link)->top; bid != BID_NULL; bid = bid_to_ipbuf(bid)->p->next)
-
-#endif /* __PLAT_OMAP_DSP_IPBUF_H */
diff --git a/arch/arm/plat-omap/dsp/mblog.c b/arch/arm/plat-omap/dsp/mblog.c
deleted file mode 100644
index 2b1e113..0000000
--- a/arch/arm/plat-omap/dsp/mblog.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2003-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/jiffies.h>
-#include <asm/arch/mailbox.h>
-#include "dsp_mbcmd.h"
-#include "dsp.h"
-
-char *subcmd_name(struct mbcmd *mb)
-{
- u8 cmd_h = mb->cmd_h;
- u8 cmd_l = mb->cmd_l;
- char *s;
-
- switch (cmd_h) {
- case MBOX_CMD_DSP_RUNLEVEL:
- s = (cmd_l == RUNLEVEL_USER) ? "USER":
- (cmd_l == RUNLEVEL_SUPER) ? "SUPER":
- (cmd_l == RUNLEVEL_RECOVERY) ? "RECOVERY":
- NULL;
- break;
- case MBOX_CMD_DSP_PM:
- s = (cmd_l == PM_DISABLE) ? "DISABLE":
- (cmd_l == PM_ENABLE) ? "ENABLE":
- NULL;
- break;
- case MBOX_CMD_DSP_KFUNC:
- s = (cmd_l == KFUNC_FBCTL) ? "FBCTL":
- (cmd_l == KFUNC_POWER) ?
- ((mb->data == AUDIO_PWR_UP) ? "PWR AUD /UP":
- (mb->data == AUDIO_PWR_DOWN) ? "PWR AUD /DOWN":
- (mb->data == AUDIO_PWR_DOWN2) ? "PWR AUD /DOWN(2)":
- (mb->data == DSP_PWR_UP) ? "PWR DSP /UP":
- (mb->data == DSP_PWR_DOWN) ? "PWR DSP /DOWN":
- (mb->data == DVFS_START) ? "PWR DVFS/START":
- (mb->data == DVFS_STOP) ? "PWR DVFS/STOP":
- NULL):
-
- NULL;
- break;
- case MBOX_CMD_DSP_DSPCFG:
- {
- u8 cfgc = cmd_l & 0x7f;
- s = (cfgc == DSPCFG_REQ) ? "REQ":
- (cfgc == DSPCFG_SYSADRH) ? "SYSADRH":
- (cfgc == DSPCFG_SYSADRL) ? "SYSADRL":
- (cfgc == DSPCFG_ABORT) ? "ABORT":
- (cfgc == DSPCFG_PROTREV) ? "PROTREV":
- NULL;
- break;
- }
- case MBOX_CMD_DSP_REGRW:
- s = (cmd_l == REGRW_MEMR) ? "MEMR":
- (cmd_l == REGRW_MEMW) ? "MEMW":
- (cmd_l == REGRW_IOR) ? "IOR":
- (cmd_l == REGRW_IOW) ? "IOW":
- (cmd_l == REGRW_DATA) ? "DATA":
- NULL;
- break;
- case MBOX_CMD_DSP_GETVAR:
- case MBOX_CMD_DSP_SETVAR:
- s = (cmd_l == VARID_ICRMASK) ? "ICRMASK":
- (cmd_l == VARID_LOADINFO) ? "LOADINFO":
- NULL;
- break;
- case MBOX_CMD_DSP_ERR:
- s = (cmd_l == EID_BADTID) ? "BADTID":
- (cmd_l == EID_BADTCN) ? "BADTCN":
- (cmd_l == EID_BADBID) ? "BADBID":
- (cmd_l == EID_BADCNT) ? "BADCNT":
- (cmd_l == EID_NOTLOCKED) ? "NOTLOCKED":
- (cmd_l == EID_STVBUF) ? "STVBUF":
- (cmd_l == EID_BADADR) ? "BADADR":
- (cmd_l == EID_BADTCTL) ? "BADTCTL":
- (cmd_l == EID_BADPARAM) ? "BADPARAM":
- (cmd_l == EID_FATAL) ? "FATAL":
- (cmd_l == EID_WDT) ? "WDT":
- (cmd_l == EID_NOMEM) ? "NOMEM":
- (cmd_l == EID_NORES) ? "NORES":
- (cmd_l == EID_IPBFULL) ? "IPBFULL":
- (cmd_l == EID_TASKNOTRDY) ? "TASKNOTRDY":
- (cmd_l == EID_TASKBSY) ? "TASKBSY":
- (cmd_l == EID_TASKERR) ? "TASKERR":
- (cmd_l == EID_BADCFGTYP) ? "BADCFGTYP":
- (cmd_l == EID_DEBUG) ? "DEBUG":
- (cmd_l == EID_BADSEQ) ? "BADSEQ":
- (cmd_l == EID_BADCMD) ? "BADCMD":
- NULL;
- break;
- default:
- s = NULL;
- }
-
- return s;
-}
-
-/* output of show() method should fit to PAGE_SIZE */
-#define MBLOG_DEPTH 64
-
-struct mblogent {
- unsigned long jiffies;
- mbox_msg_t msg;
- arm_dsp_dir_t dir;
-};
-
-static struct {
- spinlock_t lock;
- int wp;
- unsigned long cnt, cnt_ad, cnt_da;
- struct mblogent ent[MBLOG_DEPTH];
-} mblog = {
- .lock = SPIN_LOCK_UNLOCKED,
-};
-
-#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
-static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir)
-{
- const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
- char *dir_str;
- char *subname;
-
- dir_str = (dir == DIR_A2D) ? "sending " : "receiving";
- switch (ci->cmd_l_type) {
- case CMD_L_TYPE_SUBCMD:
- subname = subcmd_name(mb);
- if (unlikely(!subname))
- subname = "Unknown";
- pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n",
- dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
- ci->name, subname, mb->data);
- break;
- case CMD_L_TYPE_TID:
- pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n",
- dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
- ci->name, mb->cmd_l, mb->data);
- break;
- case CMD_L_TYPE_NULL:
- pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n",
- dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
- ci->name, mb->data);
- break;
- }
-}
-#else
-static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir) { }
-#endif
-
-void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir)
-{
- struct mblogent *ent;
-
- spin_lock(&mblog.lock);
- ent = &mblog.ent[mblog.wp];
- ent->jiffies = jiffies;
- ent->msg = *(mbox_msg_t *)mb;
- ent->dir = dir;
- if (mblog.cnt < 0xffffffff)
- mblog.cnt++;
- switch (dir) {
- case DIR_A2D:
- if (mblog.cnt_ad < 0xffffffff)
- mblog.cnt_ad++;
- break;
- case DIR_D2A:
- if (mblog.cnt_da < 0xffffffff)
- mblog.cnt_da++;
- break;
- }
- if (++mblog.wp == MBLOG_DEPTH)
- mblog.wp = 0;
- spin_unlock(&mblog.lock);
-
- mblog_print_cmd(mb, dir);
-}
-
-/*
- * sysfs file
- */
-static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- int len = 0;
- int wp;
- int i;
-
- spin_lock(&mblog.lock);
-
- wp = mblog.wp;
- len += sprintf(buf + len,
- "log count:%ld / ARM->DSP:%ld, DSP->ARM:%ld\n",
- mblog.cnt, mblog.cnt_ad, mblog.cnt_da);
- if (mblog.cnt == 0)
- goto done;
-
- len += sprintf(buf + len, " ARM->DSP ARM<-DSP\n");
- len += sprintf(buf + len, " jiffies cmd data cmd data\n");
- i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0;
- do {
- struct mblogent *ent = &mblog.ent[i];
- struct mbcmd *mb = (struct mbcmd *)&ent->msg;
- char *subname;
- struct cmdinfo ci_null = {
- .name = "Unknown",
- .cmd_l_type = CMD_L_TYPE_NULL,
- };
- const struct cmdinfo *ci;
-
- len += sprintf(buf + len,
- (ent->dir == DIR_A2D) ?
- "%08lx %04x %04x ":
- "%08lx %04x %04x ",
- ent->jiffies,
- (ent->msg >> 16) & 0x7fff, ent->msg & 0xffff);
-
- if ((ci = cmdinfo[mb->cmd_h]) == NULL)
- ci = &ci_null;
-
- switch (ci->cmd_l_type) {
- case CMD_L_TYPE_SUBCMD:
- if ((subname = subcmd_name(mb)) == NULL)
- subname = "Unknown";
- len += sprintf(buf + len, "%s:%s\n",
- ci->name, subname);
- break;
- case CMD_L_TYPE_TID:
- len += sprintf(buf + len, "%s:task %d\n",
- ci->name, mb->cmd_l);
- break;
- case CMD_L_TYPE_NULL:
- len += sprintf(buf + len, "%s\n", ci->name);
- break;
- }
-
- if (++i == MBLOG_DEPTH)
- i = 0;
- } while (i != wp);
-
-done:
- spin_unlock(&mblog.lock);
-
- return len;
-}
-
-static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
-
-void __init mblog_init(void)
-{
- int ret;
-
- ret = device_create_file(omap_dsp->dev, &dev_attr_mblog);
- if (ret)
- printk(KERN_ERR "device_create_file failed: %d\n", ret);
-}
-
-void mblog_exit(void)
-{
- device_remove_file(omap_dsp->dev, &dev_attr_mblog);
-}
diff --git a/arch/arm/plat-omap/dsp/mmu.h b/arch/arm/plat-omap/dsp/mmu.h
deleted file mode 100644
index 9d60e9e..0000000
--- a/arch/arm/plat-omap/dsp/mmu.h
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef __PLAT_OMAP_DSP_MMU_H
-#define __PLAT_OMAP_DSP_MMU_H
-
-#ifdef CONFIG_ARCH_OMAP1
-
-#ifdef CONFIG_ARCH_OMAP15XX
-struct omap_mmu dsp_mmu = {
- .name = "mmu:dsp",
- .type = OMAP_MMU_DSP,
- .base = IO_ADDRESS(OMAP1510_DSP_MMU_BASE),
- .membase = OMAP1510_DSP_BASE,
- .memsize = OMAP1510_DSP_SIZE,
- .nr_tlb_entries = 32,
- .addrspace = 24,
- .irq = INT_1510_DSP_MMU,
- .ops = &omap1_mmu_ops,
-};
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-struct omap_mmu dsp_mmu = {
- .name = "mmu:dsp",
- .type = OMAP_MMU_DSP,
- .base = IO_ADDRESS(OMAP16XX_DSP_MMU_BASE),
- .membase = OMAP16XX_DSP_BASE,
- .memsize = OMAP16XX_DSP_SIZE,
- .nr_tlb_entries = 32,
- .addrspace = 24,
- .irq = INT_1610_DSP_MMU,
- .ops = &omap1_mmu_ops,
-};
-#endif
-#else /* OMAP2 */
-struct omap_mmu dsp_mmu = {
- .name = "mmu:dsp",
- .type = OMAP_MMU_DSP,
- .base = DSP_MMU_24XX_VIRT,
- .membase = DSP_MEM_24XX_VIRT,
- .memsize = DSP_MEM_24XX_SIZE,
- .nr_tlb_entries = 32,
- .addrspace = 24,
- .irq = INT_24XX_DSP_MMU,
- .ops = &omap2_mmu_ops,
-};
-
-#define IOMAP_VAL 0x3f
-#endif
-
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
-static struct omapfb_notifier_block *omapfb_nb;
-static int omapfb_ready;
-#endif
-
-/*
- * OMAP1 EMIFF access
- */
-#ifdef CONFIG_ARCH_OMAP1
-#define EMIF_PRIO_LB_MASK 0x0000f000
-#define EMIF_PRIO_LB_SHIFT 12
-#define EMIF_PRIO_DMA_MASK 0x00000f00
-#define EMIF_PRIO_DMA_SHIFT 8
-#define EMIF_PRIO_DSP_MASK 0x00000070
-#define EMIF_PRIO_DSP_SHIFT 4
-#define EMIF_PRIO_MPU_MASK 0x00000007
-#define EMIF_PRIO_MPU_SHIFT 0
-#define set_emiff_dma_prio(prio) \
- do { \
- omap_writel((omap_readl(OMAP_TC_OCPT1_PRIOR) & \
- ~EMIF_PRIO_DMA_MASK) | \
- ((prio) << EMIF_PRIO_DMA_SHIFT), \
- OMAP_TC_OCPT1_PRIOR); \
- } while(0)
-#else
-#define set_emiff_dma_prio(prio) do { } while (0)
-#endif /* CONFIG_ARCH_OMAP1 */
-
-#ifdef CONFIG_ARCH_OMAP1
-static int dsp_mmu_itack(void)
-{
- unsigned long dspadr;
-
- pr_info("omapdsp: sending DSP MMU interrupt ack.\n");
- if (!dsp_err_isset(ERRCODE_MMU)) {
- printk(KERN_ERR "omapdsp: DSP MMU error has not been set.\n");
- return -EINVAL;
- }
- dspadr = dsp_mmu.fault_address & ~(SZ_4K-1);
- /* FIXME: reserve TLB entry for this */
- omap_mmu_exmap(&dsp_mmu, dspadr, 0, SZ_4K, EXMAP_TYPE_MEM);
- pr_info("omapdsp: falling into recovery runlevel...\n");
- dsp_set_runlevel(RUNLEVEL_RECOVERY);
- omap_mmu_itack(&dsp_mmu);
- udelay(100);
- omap_mmu_exunmap(&dsp_mmu, dspadr);
- dsp_err_clear(ERRCODE_MMU);
- return 0;
-}
-
-/*
- * 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.
- */
-static int intmem_enable(void)
-{
- int ret = 0;
-
- if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
- ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA);
-
- return ret;
-}
-
-static void intmem_disable(void) {
- if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
- mbcompose_send(PM, PM_DISABLE, DSPREG_ICR_DMA);
-}
-#else
-static int intmem_enable(void) { return 0; }
-static void intmem_disable(void) { }
-static int dsp_mmu_itack(void) { return 0; }
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2
-static inline void dsp_mem_ipi_init(void)
-{
- int i, dspmem_pg_count;
- dspmem_pg_count = dspmem_size >> 12;
- for (i = 0; i < dspmem_pg_count; i++) {
- writel(i, DSP_IPI_INDEX);
- writel(DSP_IPI_ENTRY_ELMSIZEVALUE_16, DSP_IPI_ENTRY);
- }
- writel(1, DSP_IPI_ENABLE);
- writel(IOMAP_VAL, DSP_IPI_IOMAP);
-}
-#else
-static inline void dsp_mem_ipi_init(void) { }
-#endif
-
-#endif /* __PLAT_OMAP_DSP_MMU_H */
diff --git a/arch/arm/plat-omap/dsp/omap1_dsp.h b/arch/arm/plat-omap/dsp/omap1_dsp.h
deleted file mode 100644
index f4ec73e..0000000
--- a/arch/arm/plat-omap/dsp/omap1_dsp.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __OMAP_DSP_OMAP1_DSP_H
-#define __OMAP_DSP_OMAP1_DSP_H
-
-#ifdef CONFIG_ARCH_OMAP15XX
-#define OMAP1510_DARAM_BASE (OMAP1510_DSP_BASE + 0x0)
-#define OMAP1510_DARAM_SIZE 0x10000
-#define OMAP1510_SARAM_BASE (OMAP1510_DSP_BASE + 0x10000)
-#define OMAP1510_SARAM_SIZE 0x18000
-#endif
-
-#ifdef CONFIG_ARCH_OMAP16XX
-#define OMAP16XX_DARAM_BASE (OMAP16XX_DSP_BASE + 0x0)
-#define OMAP16XX_DARAM_SIZE 0x10000
-#define OMAP16XX_SARAM_BASE (OMAP16XX_DSP_BASE + 0x10000)
-#define OMAP16XX_SARAM_SIZE 0x18000
-#endif
-
-/*
- * Reset Control
- */
-#define ARM_RSTCT1_SW_RST 0x0008
-#define ARM_RSTCT1_DSP_RST 0x0004
-#define ARM_RSTCT1_DSP_EN 0x0002
-#define ARM_RSTCT1_ARM_RST 0x0001
-
-/*
- * MPUI
- */
-#define MPUI_CTRL_WORDSWAP_MASK 0x00600000
-#define MPUI_CTRL_WORDSWAP_ALL 0x00000000
-#define MPUI_CTRL_WORDSWAP_NONAPI 0x00200000
-#define MPUI_CTRL_WORDSWAP_API 0x00400000
-#define MPUI_CTRL_WORDSWAP_NONE 0x00600000
-#define MPUI_CTRL_AP_MASK 0x001c0000
-#define MPUI_CTRL_AP_MDH 0x00000000
-#define MPUI_CTRL_AP_MHD 0x00040000
-#define MPUI_CTRL_AP_DMH 0x00080000
-#define MPUI_CTRL_AP_HMD 0x000c0000
-#define MPUI_CTRL_AP_DHM 0x00100000
-#define MPUI_CTRL_AP_HDM 0x00140000
-#define MPUI_CTRL_BYTESWAP_MASK 0x00030000
-#define MPUI_CTRL_BYTESWAP_NONE 0x00000000
-#define MPUI_CTRL_BYTESWAP_NONAPI 0x00010000
-#define MPUI_CTRL_BYTESWAP_ALL 0x00020000
-#define MPUI_CTRL_BYTESWAP_API 0x00030000
-#define MPUI_CTRL_TIMEOUT_MASK 0x0000ff00
-#define MPUI_CTRL_APIF_HNSTB_DIV_MASK 0x000000f0
-#define MPUI_CTRL_S_NABORT_GL 0x00000008
-#define MPUI_CTRL_S_NABORT_32BIT 0x00000004
-#define MPUI_CTRL_EN_TIMEOUT 0x00000002
-#define MPUI_CTRL_HF_MCUCLK 0x00000001
-#define DSP_BOOT_CONFIG_DIRECT 0x00000000
-#define DSP_BOOT_CONFIG_PSD_DIRECT 0x00000001
-#define DSP_BOOT_CONFIG_IDLE 0x00000002
-#define DSP_BOOT_CONFIG_DL16 0x00000003
-#define DSP_BOOT_CONFIG_DL32 0x00000004
-#define DSP_BOOT_CONFIG_MPUI 0x00000005
-#define DSP_BOOT_CONFIG_INTERNAL 0x00000006
-
-/*
- * DSP boot mode
- * direct: 0xffff00
- * pseudo direct: 0x080000
- * MPUI: branch 0x010000
- * internel: branch 0x024000
- */
-#define DSP_BOOT_ADR_DIRECT 0xffff00
-#define DSP_BOOT_ADR_PSD_DIRECT 0x080000
-#define DSP_BOOT_ADR_MPUI 0x010000
-#define DSP_BOOT_ADR_INTERNAL 0x024000
-
-/*
- * TC
- */
-#define TC_ENDIANISM_SWAP 0x00000002
-#define TC_ENDIANISM_SWAP_WORD 0x00000002
-#define TC_ENDIANISM_SWAP_BYTE 0x00000000
-#define TC_ENDIANISM_EN 0x00000001
-
-/*
- * DSP ICR
- */
-#define DSPREG_ICR_RESERVED_BITS 0xffc0
-#define DSPREG_ICR_EMIF 0x0020
-#define DSPREG_ICR_DPLL 0x0010
-#define DSPREG_ICR_PER 0x0008
-#define DSPREG_ICR_CACHE 0x0004
-#define DSPREG_ICR_DMA 0x0002
-#define DSPREG_ICR_CPU 0x0001
-
-#endif /* __OMAP_DSP_OMAP1_DSP_H */
diff --git a/arch/arm/plat-omap/dsp/omap2_dsp.h b/arch/arm/plat-omap/dsp/omap2_dsp.h
deleted file mode 100644
index 0dc43f0..0000000
--- a/arch/arm/plat-omap/dsp/omap2_dsp.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __OMAP_DSP_OMAP2_DSP_H
-#define __OMAP_DSP_OMAP2_DSP_H
-
-#ifdef CONFIG_ARCH_OMAP24XX
-#define OMAP24XX_DARAM_BASE (DSP_MEM_24XX_VIRT + 0x0)
-#define OMAP24XX_DARAM_SIZE 0x10000
-#define OMAP24XX_SARAM_BASE (DSP_MEM_24XX_VIRT + 0x10000)
-#define OMAP24XX_SARAM_SIZE 0x18000
-#endif
-
-#include <asm/arch/hardware.h>
-
-/*
- * DSP IPI registers: mapped to 0xe1000000 -- use readX(), writeX()
- */
-#ifdef CONFIG_ARCH_OMAP24XX
-#define DSP_IPI_BASE DSP_IPI_24XX_VIRT
-#endif
-
-#ifdef CONFIG_ARCH_OMAP34XX
-#define DSP_IPI_BASE DSP_IPI_34XX_VIRT
-#endif
-
-#define DSP_IPI_REVISION (DSP_IPI_BASE + 0x00)
-#define DSP_IPI_SYSCONFIG (DSP_IPI_BASE + 0x10)
-#define DSP_IPI_INDEX (DSP_IPI_BASE + 0x40)
-#define DSP_IPI_ENTRY (DSP_IPI_BASE + 0x44)
-#define DSP_IPI_ENABLE (DSP_IPI_BASE + 0x48)
-#define DSP_IPI_IOMAP (DSP_IPI_BASE + 0x4c)
-#define DSP_IPI_DSPBOOTCONFIG (DSP_IPI_BASE + 0x50)
-
-#define DSP_IPI_ENTRY_ELMSIZEVALUE_MASK 0x00000003
-#define DSP_IPI_ENTRY_ELMSIZEVALUE_8 0x00000000
-#define DSP_IPI_ENTRY_ELMSIZEVALUE_16 0x00000001
-#define DSP_IPI_ENTRY_ELMSIZEVALUE_32 0x00000002
-
-#define DSP_BOOT_CONFIG_DIRECT 0x00000000
-#define DSP_BOOT_CONFIG_PSD_DIRECT 0x00000001
-#define DSP_BOOT_CONFIG_IDLE 0x00000002
-#define DSP_BOOT_CONFIG_DL16 0x00000003
-#define DSP_BOOT_CONFIG_DL32 0x00000004
-#define DSP_BOOT_CONFIG_API 0x00000005
-#define DSP_BOOT_CONFIG_INTERNAL 0x00000006
-
-/*
- * DSP boot mode
- * direct: 0xffff00
- * pseudo direct: 0x080000
- * API: branch 0x010000
- * internel: branch 0x024000
- */
-#define DSP_BOOT_ADR_DIRECT 0xffff00
-#define DSP_BOOT_ADR_PSD_DIRECT 0x080000
-#define DSP_BOOT_ADR_API 0x010000
-#define DSP_BOOT_ADR_INTERNAL 0x024000
-
-/*
- * DSP ICR
- */
-#define DSPREG_ICR_RESERVED_BITS 0xfc00
-#define DSPREG_ICR_HWA 0x0200
-#define DSPREG_ICR_IPORT 0x0100
-#define DSPREG_ICR_MPORT 0x0080
-#define DSPREG_ICR_XPORT 0x0040
-#define DSPREG_ICR_DPORT 0x0020
-#define DSPREG_ICR_DPLL 0x0010
-#define DSPREG_ICR_PER 0x0008
-#define DSPREG_ICR_CACHE 0x0004
-#define DSPREG_ICR_DMA 0x0002
-#define DSPREG_ICR_CPU 0x0001
-
-#endif /* __OMAP_DSP_OMAP2_DSP_H */
diff --git a/arch/arm/plat-omap/dsp/proclist.h b/arch/arm/plat-omap/dsp/proclist.h
deleted file mode 100644
index 666ca4d..0000000
--- a/arch/arm/plat-omap/dsp/proclist.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __PLAT_OMAP_DSP_PROCLIST_H
-#define __PLAT_OMAP_DSP_PROCLIST_H
-
-struct proc_list {
- struct list_head list_head;
- pid_t pid;
- struct file *file;
-};
-
-static inline int proc_list_add(spinlock_t *lock, struct list_head *list,
- struct task_struct *tsk, struct file *file)
-{
- struct proc_list *new;
-
- new = kmalloc(sizeof(struct proc_list), GFP_KERNEL);
- if (new == NULL)
- return -ENOMEM;
- new->pid = tsk->pid;
- new->file = file;
- spin_lock(lock);
- list_add_tail(&new->list_head, list);
- spin_unlock(lock);
-
- return 0;
-}
-
-static inline void proc_list_del(spinlock_t *lock, struct list_head *list,
- struct task_struct *tsk, struct file *file)
-{
- struct proc_list *pl;
-
- spin_lock(lock);
- list_for_each_entry(pl, list, list_head) {
- if (pl->file == file) {
- list_del(&pl->list_head);
- kfree(pl);
- spin_unlock(lock);
- return;
- }
- }
-
- /* correspinding file struct isn't found in the list ??? */
- printk(KERN_ERR "proc_list_del(): proc_list is inconsistent!\n"
- "struct file (%p) not found\n", file);
- printk(KERN_ERR "listing proc_list...\n");
- list_for_each_entry(pl, list, list_head)
- printk(KERN_ERR " pid:%d file:%p\n", pl->pid, pl->file);
- spin_unlock(lock);
-}
-
-static inline void proc_list_flush(spinlock_t *lock, struct list_head *list)
-{
- struct proc_list *pl;
-
- spin_lock(lock);
- while (!list_empty(list)) {
- pl = list_entry(list->next, struct proc_list, list_head);
- list_del(&pl->list_head);
- kfree(pl);
- }
- spin_unlock(lock);
-}
-
-#endif /* __PLAT_OMAP_DSP_PROCLIST_H */
diff --git a/arch/arm/plat-omap/dsp/task.c b/arch/arm/plat-omap/dsp/task.c
deleted file mode 100644
index e5ee8e0..0000000
--- a/arch/arm/plat-omap/dsp/task.c
+++ /dev/null
@@ -1,3042 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/arch/mailbox.h>
-#include <asm/arch/dsp.h>
-#include "uaccess_dsp.h"
-#include "dsp_mbcmd.h"
-#include "dsp.h"
-#include "ipbuf.h"
-#include "proclist.h"
-
-/*
- * devstate: task device state machine
- * NOTASK: task is not attached.
- * ATTACHED: task is attached.
- * GARBAGE: task is detached. waiting for all processes to close this device.
- * ADDREQ: requesting for tadd
- * DELREQ: requesting for tdel. no process is opening this device.
- * FREEZED: task is attached, but reserved to be killed.
- * ADDFAIL: tadd failed.
- * ADDING: tadd in process.
- * DELING: tdel in process.
- * KILLING: tkill in process.
- */
-#define TASKDEV_ST_NOTASK 0x00000001
-#define TASKDEV_ST_ATTACHED 0x00000002
-#define TASKDEV_ST_GARBAGE 0x00000004
-#define TASKDEV_ST_INVALID 0x00000008
-#define TASKDEV_ST_ADDREQ 0x00000100
-#define TASKDEV_ST_DELREQ 0x00000200
-#define TASKDEV_ST_FREEZED 0x00000400
-#define TASKDEV_ST_ADDFAIL 0x00001000
-#define TASKDEV_ST_ADDING 0x00010000
-#define TASKDEV_ST_DELING 0x00020000
-#define TASKDEV_ST_KILLING 0x00040000
-#define TASKDEV_ST_STATE_MASK 0x7fffffff
-#define TASKDEV_ST_STALE 0x80000000
-
-static struct {
- long state;
- char *name;
-} devstate_desc[] = {
- { TASKDEV_ST_NOTASK, "notask" },
- { TASKDEV_ST_ATTACHED, "attached" },
- { TASKDEV_ST_GARBAGE, "garbage" },
- { TASKDEV_ST_INVALID, "invalid" },
- { TASKDEV_ST_ADDREQ, "addreq" },
- { TASKDEV_ST_DELREQ, "delreq" },
- { TASKDEV_ST_FREEZED, "freezed" },
- { TASKDEV_ST_ADDFAIL, "addfail" },
- { TASKDEV_ST_ADDING, "adding" },
- { TASKDEV_ST_DELING, "deling" },
- { TASKDEV_ST_KILLING, "killing" },
-};
-
-static char *devstate_name(long state)
-{
- int i;
- int max = ARRAY_SIZE(devstate_desc);
-
- for (i = 0; i < max; i++) {
- if (state & devstate_desc[i].state)
- return devstate_desc[i].name;
- }
- return "unknown";
-}
-
-struct rcvdt_bk_struct {
- struct ipblink link;
- unsigned int rp;
-};
-
-struct taskdev {
- struct bus_type *bus;
- struct device dev; /* Generic device interface */
-
- long state;
- struct rw_semaphore state_sem;
- wait_queue_head_t state_wait_q;
- struct mutex usecount_lock;
- unsigned int usecount;
- char name[TNM_LEN];
- struct file_operations fops;
- spinlock_t proc_list_lock;
- struct list_head proc_list;
- struct dsptask *task;
-
- /* read stuff */
- wait_queue_head_t read_wait_q;
- struct mutex read_mutex;
- spinlock_t read_lock;
- union {
- struct kfifo *fifo; /* for active word */
- struct rcvdt_bk_struct bk;
- } rcvdt;
-
- /* write stuff */
- wait_queue_head_t write_wait_q;
- struct mutex write_mutex;
- spinlock_t wsz_lock;
- size_t wsz;
-
- /* tctl stuff */
- wait_queue_head_t tctl_wait_q;
- struct mutex tctl_mutex;
- int tctl_stat;
- int tctl_ret; /* return value for tctl_show() */
-
- /* device lock */
- struct mutex lock;
- pid_t lock_pid;
-};
-
-#define to_taskdev(n) container_of(n, struct taskdev, dev)
-
-struct dsptask {
- enum {
- TASK_ST_ERR = 0,
- TASK_ST_READY,
- TASK_ST_CFGREQ
- } state;
- u8 tid;
- char name[TNM_LEN];
- u16 ttyp;
- struct taskdev *dev;
-
- /* read stuff */
- struct ipbuf_p *ipbuf_pvt_r;
-
- /* write stuff */
- struct ipbuf_p *ipbuf_pvt_w;
-
- /* mmap stuff */
- void *map_base;
- size_t map_length;
-};
-
-#define sndtyp_acv(ttyp) ((ttyp) & TTYP_ASND)
-#define sndtyp_psv(ttyp) (!((ttyp) & TTYP_ASND))
-#define sndtyp_bk(ttyp) ((ttyp) & TTYP_BKDM)
-#define sndtyp_wd(ttyp) (!((ttyp) & TTYP_BKDM))
-#define sndtyp_pvt(ttyp) ((ttyp) & TTYP_PVDM)
-#define sndtyp_gbl(ttyp) (!((ttyp) & TTYP_PVDM))
-#define rcvtyp_acv(ttyp) ((ttyp) & TTYP_ARCV)
-#define rcvtyp_psv(ttyp) (!((ttyp) & TTYP_ARCV))
-#define rcvtyp_bk(ttyp) ((ttyp) & TTYP_BKMD)
-#define rcvtyp_wd(ttyp) (!((ttyp) & TTYP_BKMD))
-#define rcvtyp_pvt(ttyp) ((ttyp) & TTYP_PVMD)
-#define rcvtyp_gbl(ttyp) (!((ttyp) & TTYP_PVMD))
-
-static inline int has_taskdev_lock(struct taskdev *dev);
-static int dsp_rmdev_minor(unsigned char minor);
-static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor);
-static void taskdev_delete(unsigned char minor);
-static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task);
-static int dsp_tdel_bh(struct taskdev *dev, u16 type);
-
-static struct bus_type dsptask_bus = {
- .name = "dsptask",
-};
-
-static struct class *dsp_task_class;
-static DEFINE_MUTEX(devmgr_lock);
-static struct taskdev *taskdev[TASKDEV_MAX];
-static struct dsptask *dsptask[TASKDEV_MAX];
-static DEFINE_MUTEX(cfg_lock);
-static u16 cfg_cmd;
-static u8 cfg_tid;
-static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q);
-static u8 n_task; /* static task count */
-static void *heap;
-
-#define is_dynamic_task(tid) ((tid) >= n_task)
-
-#define devstate_read_lock(dev, devstate) \
- devstate_read_lock_timeout(dev, devstate, 0)
-#define devstate_read_unlock(dev) up_read(&(dev)->state_sem)
-#define devstate_write_lock(dev, devstate) \
- devstate_write_lock_timeout(dev, devstate, 0)
-#define devstate_write_unlock(dev) up_write(&(dev)->state_sem)
-
-static ssize_t devname_show(struct device *d, struct device_attribute *attr,
- char *buf);
-static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
- char *buf);
-static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
- char *buf);
-static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
- char *buf);
-static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
- char *buf);
-static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
- char *buf);
-static int fifosz_store(struct device *d, struct device_attribute *attr,
- const char *buf, size_t count);
-static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
- char *buf);
-static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
- char *buf);
-static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
- char *buf);
-static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
- char *buf);
-
-#define __ATTR_RW(_name,_mode) { \
- .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
- .show = _name##_show, \
- .store = _name##_store, \
-}
-
-static struct device_attribute dev_attr_devname = __ATTR_RO(devname);
-static struct device_attribute dev_attr_devstate = __ATTR_RO(devstate);
-static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list);
-static struct device_attribute dev_attr_taskname = __ATTR_RO(taskname);
-static struct device_attribute dev_attr_ttyp = __ATTR_RO(ttyp);
-static struct device_attribute dev_attr_fifosz = __ATTR_RW(fifosz, 0666);
-static struct device_attribute dev_attr_fifocnt = __ATTR_RO(fifocnt);
-static struct device_attribute dev_attr_ipblink = __ATTR_RO(ipblink);
-static struct device_attribute dev_attr_wsz = __ATTR_RO(wsz);
-static struct device_attribute dev_attr_mmap = __ATTR_RO(mmap);
-
-static inline void set_taskdev_state(struct taskdev *dev, int state)
-{
- pr_debug("omapdsp: devstate: CHANGE %s[%d]:\"%s\"->\"%s\"\n",
- dev->name,
- (dev->task ? dev->task->tid : -1),
- devstate_name(dev->state),
- devstate_name(state));
- dev->state = state;
-}
-
-/*
- * devstate_read_lock_timeout()
- * devstate_write_lock_timeout():
- * timeout != 0: dev->state can be diffeent from what you want.
- * timeout == 0: no timeout
- */
-#define BUILD_DEVSTATE_LOCK_TIMEOUT(rw) \
-static int devstate_##rw##_lock_timeout(struct taskdev *dev, long devstate, \
- int timeout) \
-{ \
- DEFINE_WAIT(wait); \
- down_##rw(&dev->state_sem); \
- while (!(dev->state & devstate)) { \
- up_##rw(&dev->state_sem); \
- prepare_to_wait(&dev->state_wait_q, &wait, TASK_INTERRUPTIBLE); \
- if (!timeout) \
- timeout = MAX_SCHEDULE_TIMEOUT; \
- timeout = schedule_timeout(timeout); \
- finish_wait(&dev->state_wait_q, &wait); \
- if (timeout == 0) \
- return -ETIME; \
- if (signal_pending(current)) \
- return -EINTR; \
- down_##rw(&dev->state_sem); \
- } \
- return 0; \
-}
-BUILD_DEVSTATE_LOCK_TIMEOUT(read)
-BUILD_DEVSTATE_LOCK_TIMEOUT(write)
-
-#define BUILD_DEVSTATE_LOCK_AND_TEST(rw) \
-static int devstate_##rw##_lock_and_test(struct taskdev *dev, long devstate) \
-{ \
- down_##rw(&dev->state_sem); \
- if (dev->state & devstate) \
- return 1; /* success */ \
- /* failure */ \
- up_##rw(&dev->state_sem); \
- return 0; \
-}
-BUILD_DEVSTATE_LOCK_AND_TEST(read)
-BUILD_DEVSTATE_LOCK_AND_TEST(write)
-
-static int taskdev_lock_interruptible(struct taskdev *dev,
- struct mutex *lock)
-{
- int ret;
-
- if (has_taskdev_lock(dev))
- ret = mutex_lock_interruptible(lock);
- else {
- if ((ret = mutex_lock_interruptible(&dev->lock)) != 0)
- return ret;
- ret = mutex_lock_interruptible(lock);
- mutex_unlock(&dev->lock);
- }
-
- return ret;
-}
-
-static int taskdev_lock_and_statelock_attached(struct taskdev *dev,
- struct mutex *lock)
-{
- int ret;
-
- if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
- return -ENODEV;
-
- if ((ret = taskdev_lock_interruptible(dev, lock)) != 0)
- devstate_read_unlock(dev);
-
- return ret;
-}
-
-static inline void taskdev_unlock_and_stateunlock(struct taskdev *dev,
- struct mutex *lock)
-{
- mutex_unlock(lock);
- devstate_read_unlock(dev);
-}
-
-/*
- * taskdev_flush_buf()
- * must be called under state_lock(ATTACHED) and dev->read_mutex.
- */
-static int taskdev_flush_buf(struct taskdev *dev)
-{
- u16 ttyp = dev->task->ttyp;
-
- if (sndtyp_wd(ttyp)) {
- /* word receiving */
- kfifo_reset(dev->rcvdt.fifo);
- } else {
- /* block receiving */
- struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
-
- if (sndtyp_gbl(ttyp))
- ipblink_flush(&rcvdt->link);
- else {
- ipblink_flush_pvt(&rcvdt->link);
- release_ipbuf_pvt(dev->task->ipbuf_pvt_r);
- }
- }
-
- return 0;
-}
-
-/*
- * taskdev_set_fifosz()
- * must be called under dev->read_mutex.
- */
-static int taskdev_set_fifosz(struct taskdev *dev, unsigned long sz)
-{
- u16 ttyp = dev->task->ttyp;
-
- if (!(sndtyp_wd(ttyp) && sndtyp_acv(ttyp))) {
- printk(KERN_ERR
- "omapdsp: buffer size can be changed only for "
- "active word sending task.\n");
- return -EINVAL;
- }
- if ((sz == 0) || (sz & 1)) {
- printk(KERN_ERR "omapdsp: illegal buffer size! (%ld)\n"
- "it must be even and non-zero value.\n", sz);
- return -EINVAL;
- }
-
- if (kfifo_len(dev->rcvdt.fifo)) {
- printk(KERN_ERR "omapdsp: buffer is not empty!\n");
- return -EIO;
- }
-
- kfifo_free(dev->rcvdt.fifo);
- dev->rcvdt.fifo = kfifo_alloc(sz, GFP_KERNEL, &dev->read_lock);
- if (IS_ERR(dev->rcvdt.fifo)) {
- printk(KERN_ERR
- "omapdsp: unable to change receive buffer size. "
- "(%ld bytes for %s)\n", sz, dev->name);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static inline int has_taskdev_lock(struct taskdev *dev)
-{
- return (dev->lock_pid == current->pid);
-}
-
-static int taskdev_lock(struct taskdev *dev)
-{
- if (mutex_lock_interruptible(&dev->lock))
- return -EINTR;
- dev->lock_pid = current->pid;
- return 0;
-}
-
-static int taskdev_unlock(struct taskdev *dev)
-{
- if (!has_taskdev_lock(dev)) {
- printk(KERN_ERR
- "omapdsp: an illegal process attempted to "
- "unlock the dsptask lock!\n");
- return -EINVAL;
- }
- dev->lock_pid = 0;
- mutex_unlock(&dev->lock);
- return 0;
-}
-
-static int dsp_task_config(struct dsptask *task, u8 tid)
-{
- u16 ttyp;
- int ret;
-
- task->tid = tid;
- dsptask[tid] = task;
-
- /* TCFG request */
- task->state = TASK_ST_CFGREQ;
- if (mutex_lock_interruptible(&cfg_lock)) {
- ret = -EINTR;
- goto fail_out;
- }
- cfg_cmd = MBOX_CMD_DSP_TCFG;
- mbcompose_send_and_wait(TCFG, tid, 0, &cfg_wait_q);
- cfg_cmd = 0;
- mutex_unlock(&cfg_lock);
-
- if (task->state != TASK_ST_READY) {
- printk(KERN_ERR "omapdsp: task %d configuration error!\n", tid);
- ret = -EINVAL;
- goto fail_out;
- }
-
- if (strlen(task->name) <= 1)
- sprintf(task->name, "%d", tid);
- pr_info("omapdsp: task %d: name %s\n", tid, task->name);
-
- ttyp = task->ttyp;
-
- /*
- * task info sanity check
- */
-
- /* task type check */
- if (rcvtyp_psv(ttyp) && rcvtyp_pvt(ttyp)) {
- 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) &&
- (ipbuf_p_validate(task->ipbuf_pvt_r, DIR_D2A) < 0)) {
- ret = -EINVAL;
- goto fail_out;
- }
- 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) &&
- ((!ALIGN((unsigned long)task->map_base, PAGE_SIZE)) ||
- (!ALIGN(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;
- }
-
- return 0;
-
-fail_out:
- dsptask[tid] = NULL;
- return ret;
-}
-
-static void dsp_task_init(struct dsptask *task)
-{
- mbcompose_send(TCTL, task->tid, TCTL_TINIT);
-}
-
-int dsp_task_config_all(u8 n)
-{
- int i, ret;
- struct taskdev *devheap;
- struct dsptask *taskheap;
- size_t devheapsz, taskheapsz;
-
- pr_info("omapdsp: found %d task(s)\n", n);
- if (n == 0)
- return 0;
-
- /*
- * reducing kmalloc!
- */
- devheapsz = sizeof(struct taskdev) * n;
- taskheapsz = sizeof(struct dsptask) * n;
- heap = kzalloc(devheapsz + taskheapsz, GFP_KERNEL);
- if (heap == NULL)
- return -ENOMEM;
- devheap = heap;
- taskheap = heap + devheapsz;
-
- n_task = n;
- for (i = 0; i < n; i++) {
- struct taskdev *dev = &devheap[i];
- struct dsptask *task = &taskheap[i];
-
- if ((ret = dsp_task_config(task, i)) < 0)
- return ret;
- if ((ret = taskdev_init(dev, task->name, i)) < 0)
- return ret;
- if ((ret = taskdev_attach_task(dev, task)) < 0)
- return ret;
- dsp_task_init(task);
- pr_info("omapdsp: taskdev %s enabled.\n", dev->name);
- }
-
- return 0;
-}
-
-static void dsp_task_unconfig(struct dsptask *task)
-{
- dsptask[task->tid] = NULL;
-}
-
-void dsp_task_unconfig_all(void)
-{
- unsigned char minor;
- u8 tid;
- struct dsptask *task;
-
- for (minor = 0; minor < n_task; minor++) {
- /*
- * taskdev[minor] can be NULL in case of
- * configuration failure
- */
- if (taskdev[minor])
- taskdev_delete(minor);
- }
- for (; minor < TASKDEV_MAX; minor++) {
- if (taskdev[minor])
- dsp_rmdev_minor(minor);
- }
-
- for (tid = 0; tid < n_task; tid++) {
- /*
- * dsptask[tid] can be NULL in case of
- * configuration failure
- */
- task = dsptask[tid];
- if (task)
- dsp_task_unconfig(task);
- }
- for (; tid < TASKDEV_MAX; tid++) {
- task = dsptask[tid];
- if (task) {
- /*
- * on-demand tasks should be deleted in
- * rmdev_minor(), but just in case.
- */
- dsp_task_unconfig(task);
- kfree(task);
- }
- }
-
- if (heap) {
- kfree(heap);
- heap = NULL;
- }
-
- n_task = 0;
-}
-
-static struct device_driver dsptask_driver = {
- .name = "dsptask",
- .bus = &dsptask_bus,
-};
-
-u8 dsp_task_count(void)
-{
- return n_task;
-}
-
-int dsp_taskmod_busy(void)
-{
- struct taskdev *dev;
- unsigned char minor;
- unsigned int usecount;
-
- for (minor = 0; minor < TASKDEV_MAX; minor++) {
- dev = taskdev[minor];
- if (dev == NULL)
- continue;
- if ((usecount = dev->usecount) > 0) {
- printk("dsp_taskmod_busy(): %s: usecount=%d\n",
- dev->name, usecount);
- return 1;
- }
-/*
- if ((dev->state & (TASKDEV_ST_ADDREQ |
- TASKDEV_ST_DELREQ)) {
-*/
- if (dev->state & TASKDEV_ST_ADDREQ) {
- printk("dsp_taskmod_busy(): %s is in %s\n",
- dev->name, devstate_name(dev->state));
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * DSP task device file operations
- */
-static ssize_t dsp_task_read_wd_acv(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
- int ret = 0;
- DEFINE_WAIT(wait);
-
- if (count == 0) {
- return 0;
- } else if (count & 0x1) {
- printk(KERN_ERR
- "omapdsp: odd count is illegal for DSP task device.\n");
- return -EINVAL;
- }
-
- if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
- return -ENODEV;
-
-
- prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE);
- if (kfifo_len(dev->rcvdt.fifo) == 0)
- schedule();
- finish_wait(&dev->read_wait_q, &wait);
- if (kfifo_len(dev->rcvdt.fifo) == 0) {
- /* failure */
- if (signal_pending(current))
- ret = -EINTR;
- goto up_out;
- }
-
-
- ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count);
-
- up_out:
- taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
- return ret;
-}
-
-static ssize_t dsp_task_read_bk_acv(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
- struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
- ssize_t ret = 0;
- DEFINE_WAIT(wait);
-
- if (count == 0) {
- return 0;
- } else if (count & 0x1) {
- printk(KERN_ERR
- "omapdsp: odd count is illegal for DSP task device.\n");
- return -EINVAL;
- } else if ((int)buf & 0x1) {
- printk(KERN_ERR
- "omapdsp: buf should be word aligned for "
- "dsp_task_read().\n");
- return -EINVAL;
- }
-
- if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
- return -ENODEV;
-
- prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE);
- if (ipblink_empty(&rcvdt->link))
- schedule();
- finish_wait(&dev->read_wait_q, &wait);
- if (ipblink_empty(&rcvdt->link)) {
- /* failure */
- if (signal_pending(current))
- ret = -EINTR;
- goto up_out;
- }
-
- /* copy from delayed IPBUF */
- if (sndtyp_pvt(dev->task->ttyp)) {
- /* private */
- if (!ipblink_empty(&rcvdt->link)) {
- struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
- unsigned char *base, *src;
- size_t bkcnt;
-
- if (dsp_mem_enable(ipbp) < 0) {
- ret = -EBUSY;
- goto up_out;
- }
- 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 = -EINVAL;
- goto pv_out1;
- }
- if (dsp_mem_enable(base) < 0) {
- ret = -EBUSY;
- goto pv_out1;
- }
- src = base + rcvdt->rp;
- if (bkcnt > count) {
- if (copy_to_user_dsp(buf, src, count)) {
- ret = -EFAULT;
- goto pv_out2;
- }
- ret = count;
- rcvdt->rp += count;
- } else {
- if (copy_to_user_dsp(buf, src, bkcnt)) {
- ret = -EFAULT;
- goto pv_out2;
- }
- ret = bkcnt;
- ipblink_del_pvt(&rcvdt->link);
- release_ipbuf_pvt(ipbp);
- rcvdt->rp = 0;
- }
- pv_out2:
- dsp_mem_disable(src);
- pv_out1:
- dsp_mem_disable(ipbp);
- }
- } else {
- /* global */
- if (dsp_mem_enable_ipbuf() < 0) {
- ret = -EBUSY;
- goto up_out;
- }
- while (!ipblink_empty(&rcvdt->link)) {
- unsigned char *src;
- size_t bkcnt;
- struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
-
- src = ipb_h->p->d + rcvdt->rp;
- bkcnt = ((unsigned long)ipb_h->p->c) * 2 - rcvdt->rp;
- if (bkcnt > count) {
- if (copy_to_user_dsp(buf, src, count)) {
- ret = -EFAULT;
- goto gb_out;
- }
- ret += count;
- rcvdt->rp += count;
- break;
- } else {
- if (copy_to_user_dsp(buf, src, bkcnt)) {
- ret = -EFAULT;
- goto gb_out;
- }
- ret += bkcnt;
- buf += bkcnt;
- count -= bkcnt;
- ipblink_del_top(&rcvdt->link);
- unuse_ipbuf(ipb_h);
- rcvdt->rp = 0;
- }
- }
- gb_out:
- dsp_mem_disable_ipbuf();
- }
-
- up_out:
- taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
- return ret;
-}
-
-static ssize_t dsp_task_read_wd_psv(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
- int ret = 0;
-
- if (count == 0) {
- return 0;
- } else if (count & 0x1) {
- printk(KERN_ERR
- "omapdsp: odd count is illegal for DSP task device.\n");
- return -EINVAL;
- } else {
- /* force! */
- count = 2;
- }
-
- if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
- return -ENODEV;
-
- mbcompose_send_and_wait(WDREQ, dev->task->tid, 0, &dev->read_wait_q);
-
- if (kfifo_len(dev->rcvdt.fifo) == 0) {
- /* failure */
- if (signal_pending(current))
- ret = -EINTR;
- goto up_out;
- }
-
- ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count);
-
-up_out:
- taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
- return ret;
-}
-
-static ssize_t dsp_task_read_bk_psv(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
- struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
- int ret = 0;
-
- if (count == 0) {
- return 0;
- } else if (count & 0x1) {
- printk(KERN_ERR
- "omapdsp: odd count is illegal for DSP task device.\n");
- return -EINVAL;
- } else if ((int)buf & 0x1) {
- printk(KERN_ERR
- "omapdsp: buf should be word aligned for "
- "dsp_task_read().\n");
- return -EINVAL;
- }
-
- if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
- return -ENODEV;
-
- mbcompose_send_and_wait(BKREQ, dev->task->tid, count/2,
- &dev->read_wait_q);
-
- if (ipblink_empty(&rcvdt->link)) {
- /* failure */
- if (signal_pending(current))
- ret = -EINTR;
- goto up_out;
- }
-
- /*
- * We will not receive more than requested count.
- */
- if (sndtyp_pvt(dev->task->ttyp)) {
- /* private */
- struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
- size_t rcvcnt;
- void *src;
-
- if (dsp_mem_enable(ipbp) < 0) {
- ret = -EBUSY;
- goto up_out;
- }
- src = MKVIRT(ipbp->ah, ipbp->al);
- rcvcnt = ((unsigned long)ipbp->c) * 2;
- if (dsp_address_validate(src, rcvcnt, "task %s read buffer",
- dev->task->name) < 0) {
- ret = -EINVAL;
- goto pv_out1;
- }
- if (dsp_mem_enable(src) < 0) {
- ret = -EBUSY;
- goto pv_out1;
- }
- if (count > rcvcnt)
- count = rcvcnt;
- if (copy_to_user_dsp(buf, src, count)) {
- ret = -EFAULT;
- goto pv_out2;
- }
- ipblink_del_pvt(&rcvdt->link);
- release_ipbuf_pvt(ipbp);
- ret = count;
-pv_out2:
- dsp_mem_disable(src);
-pv_out1:
- dsp_mem_disable(ipbp);
- } else {
- /* global */
- struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
- size_t rcvcnt;
-
- if (dsp_mem_enable_ipbuf() < 0) {
- ret = -EBUSY;
- goto up_out;
- }
- rcvcnt = ((unsigned long)ipb_h->p->c) * 2;
- if (count > rcvcnt)
- count = rcvcnt;
- if (copy_to_user_dsp(buf, ipb_h->p->d, count)) {
- ret = -EFAULT;
- goto gb_out;
- }
- ipblink_del_top(&rcvdt->link);
- unuse_ipbuf(ipb_h);
- ret = count;
-gb_out:
- dsp_mem_disable_ipbuf();
- }
-
-up_out:
- taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
- return ret;
-}
-
-static ssize_t dsp_task_write_wd(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
- u16 wd;
- int ret = 0;
- DEFINE_WAIT(wait);
-
- if (count == 0) {
- return 0;
- } else if (count & 0x1) {
- printk(KERN_ERR
- "omapdsp: odd count is illegal for DSP task device.\n");
- return -EINVAL;
- } else {
- /* force! */
- count = 2;
- }
-
- if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
- return -ENODEV;
-
- prepare_to_wait(&dev->write_wait_q, &wait, TASK_INTERRUPTIBLE);
- if (dev->wsz == 0)
- schedule();
- finish_wait(&dev->write_wait_q, &wait);
- if (dev->wsz == 0) {
- /* failure */
- if (signal_pending(current))
- ret = -EINTR;
- goto up_out;
- }
-
- if (copy_from_user(&wd, buf, count)) {
- ret = -EFAULT;
- goto up_out;
- }
-
- spin_lock(&dev->wsz_lock);
- if (mbcompose_send(WDSND, dev->task->tid, wd) < 0) {
- spin_unlock(&dev->wsz_lock);
- goto up_out;
- }
- ret = count;
- if (rcvtyp_acv(dev->task->ttyp))
- dev->wsz = 0;
- spin_unlock(&dev->wsz_lock);
-
- up_out:
- taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
- return ret;
-}
-
-static ssize_t dsp_task_write_bk(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
- int ret = 0;
- DEFINE_WAIT(wait);
-
- if (count == 0) {
- return 0;
- } else if (count & 0x1) {
- printk(KERN_ERR
- "omapdsp: odd count is illegal for DSP task device.\n");
- return -EINVAL;
- } else if ((int)buf & 0x1) {
- printk(KERN_ERR
- "omapdsp: buf should be word aligned for "
- "dsp_task_write().\n");
- return -EINVAL;
- }
-
- if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
- return -ENODEV;
-
- prepare_to_wait(&dev->write_wait_q, &wait, TASK_INTERRUPTIBLE);
- if (dev->wsz == 0)
- schedule();
- finish_wait(&dev->write_wait_q, &wait);
- if (dev->wsz == 0) {
- /* failure */
- if (signal_pending(current))
- ret = -EINTR;
- goto up_out;
- }
-
- if (count > dev->wsz)
- count = dev->wsz;
-
- if (rcvtyp_pvt(dev->task->ttyp)) {
- /* private */
- struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_w;
- unsigned char *dst;
-
- if (dsp_mem_enable(ipbp) < 0) {
- ret = -EBUSY;
- goto up_out;
- }
- dst = MKVIRT(ipbp->ah, ipbp->al);
- if (dsp_address_validate(dst, count, "task %s write buffer",
- dev->task->name) < 0) {
- ret = -EINVAL;
- goto pv_out1;
- }
- if (dsp_mem_enable(dst) < 0) {
- ret = -EBUSY;
- goto pv_out1;
- }
- if (copy_from_user_dsp(dst, buf, count)) {
- ret = -EFAULT;
- goto pv_out2;
- }
- ipbp->c = count/2;
- ipbp->s = dev->task->tid;
- spin_lock(&dev->wsz_lock);
- if (mbcompose_send(BKSNDP, dev->task->tid, 0) == 0) {
- if (rcvtyp_acv(dev->task->ttyp))
- dev->wsz = 0;
- ret = count;
- }
- spin_unlock(&dev->wsz_lock);
- pv_out2:
- dsp_mem_disable(dst);
- pv_out1:
- dsp_mem_disable(ipbp);
- } else {
- /* global */
- struct ipbuf_head *ipb_h;
-
- if (dsp_mem_enable_ipbuf() < 0) {
- ret = -EBUSY;
- goto up_out;
- }
- if ((ipb_h = get_free_ipbuf(dev->task->tid)) == NULL)
- goto gb_out;
- if (copy_from_user_dsp(ipb_h->p->d, buf, count)) {
- release_ipbuf(ipb_h);
- ret = -EFAULT;
- goto gb_out;
- }
- ipb_h->p->c = count/2;
- ipb_h->p->sa = dev->task->tid;
- spin_lock(&dev->wsz_lock);
- if (mbcompose_send(BKSND, dev->task->tid, ipb_h->bid) == 0) {
- if (rcvtyp_acv(dev->task->ttyp))
- dev->wsz = 0;
- ret = count;
- ipb_bsycnt_inc(&ipbcfg);
- } else
- release_ipbuf(ipb_h);
- spin_unlock(&dev->wsz_lock);
- gb_out:
- dsp_mem_disable_ipbuf();
- }
-
- up_out:
- taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
- return ret;
-}
-
-static unsigned int dsp_task_poll(struct file * file, poll_table * wait)
-{
- unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
- struct dsptask *task = dev->task;
- unsigned int mask = 0;
-
- if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
- return 0;
- poll_wait(file, &dev->read_wait_q, wait);
- poll_wait(file, &dev->write_wait_q, wait);
- if (sndtyp_psv(task->ttyp) ||
- (sndtyp_wd(task->ttyp) && kfifo_len(dev->rcvdt.fifo)) ||
- (sndtyp_bk(task->ttyp) && !ipblink_empty(&dev->rcvdt.bk.link)))
- mask |= POLLIN | POLLRDNORM;
- if (dev->wsz)
- mask |= POLLOUT | POLLWRNORM;
- devstate_read_unlock(dev);
-
- return mask;
-}
-
-static int dsp_tctl_issue(struct taskdev *dev, u16 cmd, int argc, u16 argv[])
-{
- int tctl_argc;
- struct mb_exarg mbarg, *mbargp;
- int interactive;
- u8 tid;
- int ret = 0;
-
- if (cmd < 0x8000) {
- /*
- * 0x0000 - 0x7fff
- * system reserved TCTL commands
- */
- switch (cmd) {
- case TCTL_TEN:
- case TCTL_TDIS:
- tctl_argc = 0;
- interactive = 0;
- break;
- default:
- return -EINVAL;
- }
- }
- /*
- * 0x8000 - 0xffff
- * user-defined TCTL commands
- */
- else if (cmd < 0x8100) {
- /* 0x8000-0x80ff: no arg, non-interactive */
- tctl_argc = 0;
- interactive = 0;
- } else if (cmd < 0x8200) {
- /* 0x8100-0x81ff: 1 arg, non-interactive */
- tctl_argc = 1;
- interactive = 0;
- } else if (cmd < 0x9000) {
- /* 0x8200-0x8fff: reserved */
- return -EINVAL;
- } else if (cmd < 0x9100) {
- /* 0x9000-0x90ff: no arg, interactive */
- tctl_argc = 0;
- interactive = 1;
- } else if (cmd < 0x9200) {
- /* 0x9100-0x91ff: 1 arg, interactive */
- tctl_argc = 1;
- interactive = 1;
- } else {
- /* 0x9200-0xffff: reserved */
- return -EINVAL;
- }
-
- /*
- * if argc < 0, use tctl_argc as is.
- * if argc >= 0, check arg count.
- */
- if ((argc >= 0) && (argc != tctl_argc))
- return -EINVAL;
-
- /*
- * issue TCTL
- */
- if (taskdev_lock_interruptible(dev, &dev->tctl_mutex))
- return -EINTR;
-
- tid = dev->task->tid;
- if (tctl_argc > 0) {
- mbarg.argc = tctl_argc;
- mbarg.tid = tid;
- mbarg.argv = argv;
- mbargp = &mbarg;
- } else
- mbargp = NULL;
-
- if (interactive) {
- dev->tctl_stat = -EINVAL;
-
- mbcompose_send_and_wait_exarg(TCTL, tid, cmd, mbargp,
- &dev->tctl_wait_q);
- if (signal_pending(current)) {
- ret = -EINTR;
- goto up_out;
- }
- if ((ret = dev->tctl_stat) < 0) {
- printk(KERN_ERR "omapdsp: TCTL not responding.\n");
- goto up_out;
- }
- } else
- mbcompose_send_exarg(TCTL, tid, cmd, mbargp);
-
-up_out:
- mutex_unlock(&dev->tctl_mutex);
- return ret;
-}
-
-static int dsp_task_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- unsigned int minor = MINOR(inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
- int ret;
-
- if (cmd < 0x10000) {
- /* issue TCTL */
- u16 mbargv[1];
-
- mbargv[0] = arg & 0xffff;
- return dsp_tctl_issue(dev, cmd, -1, mbargv);
- }
-
- /* non TCTL ioctls */
- switch (cmd) {
-
- case TASK_IOCTL_LOCK:
- ret = taskdev_lock(dev);
- break;
-
- case TASK_IOCTL_UNLOCK:
- ret = taskdev_unlock(dev);
- break;
-
- case TASK_IOCTL_BFLSH:
- if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
- return -ENODEV;
- ret = taskdev_flush_buf(dev);
- taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
- break;
-
- case TASK_IOCTL_SETBSZ:
- if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
- return -ENODEV;
- ret = taskdev_set_fifosz(dev, arg);
- taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
- break;
-
- case TASK_IOCTL_GETNAME:
- ret = 0;
- if (copy_to_user((void __user *)arg, dev->name,
- strlen(dev->name) + 1))
- ret = -EFAULT;
- break;
-
- default:
- ret = -ENOIOCTLCMD;
-
- }
-
- 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 & TASKDEV_ST_ATTACHED));
- task = dev->task;
- omap_mmu_exmap_use(&dsp_mmu, 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 & TASKDEV_ST_ATTACHED));
- task = dev->task;
- omap_mmu_exmap_unuse(&dsp_mmu, 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_mmap_nopage(struct vm_area_struct *vma,
- unsigned long address, int *type)
-{
- return NOPAGE_SIGBUS;
-}
-
-static struct vm_operations_struct dsp_task_vm_ops = {
- .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)
-{
- void *tmp_vadr;
- unsigned long tmp_padr, tmp_vmadr, off;
- size_t req_len, tmp_len;
- unsigned int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
- struct dsptask *task;
- int ret = 0;
-
- if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
- return -ENODEV;
- task = dev->task;
-
- /*
- * Don't swap this area out
- * Don't dump this area to a core file
- */
- vma->vm_flags |= VM_RESERVED | VM_IO;
-
- /* Do not cache this area */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- req_len = vma->vm_end - vma->vm_start;
- off = vma->vm_pgoff << PAGE_SHIFT;
- tmp_vmadr = vma->vm_start;
- tmp_vadr = task->map_base + off;
- do {
- tmp_padr = omap_mmu_virt_to_phys(&dsp_mmu, tmp_vadr, &tmp_len);
- if (tmp_padr == 0) {
- printk(KERN_ERR
- "omapdsp: task %s: illegal address "
- "for mmap: %p", task->name, tmp_vadr);
- /* partial mapping will be cleared in upper layer */
- ret = -EINVAL;
- goto unlock_out;
- }
- if (tmp_len > req_len)
- tmp_len = req_len;
-
- pr_debug("omapdsp: mmap info: "
- "vmadr = %08lx, padr = %08lx, len = %x\n",
- tmp_vmadr, tmp_padr, tmp_len);
- if (remap_pfn_range(vma, tmp_vmadr, tmp_padr >> PAGE_SHIFT,
- tmp_len, vma->vm_page_prot) != 0) {
- printk(KERN_ERR
- "omapdsp: task %s: remap_page_range() failed.\n",
- task->name);
- /* partial mapping will be cleared in upper layer */
- ret = -EINVAL;
- goto unlock_out;
- }
-
- req_len -= tmp_len;
- tmp_vmadr += tmp_len;
- tmp_vadr += tmp_len;
- } while (req_len);
-
- vma->vm_ops = &dsp_task_vm_ops;
- vma->vm_private_data = dev;
- omap_mmu_exmap_use(&dsp_mmu, task->map_base, vma->vm_end - vma->vm_start);
-
-unlock_out:
- devstate_read_unlock(dev);
- return ret;
-}
-
-static int dsp_task_open(struct inode *inode, struct file *file)
-{
- unsigned int minor = MINOR(inode->i_rdev);
- struct taskdev *dev;
- int ret = 0;
-
- if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL))
- return -ENODEV;
-
- restart:
- mutex_lock(&dev->usecount_lock);
- down_write(&dev->state_sem);
-
- /* state can be NOTASK, ATTACHED/FREEZED, KILLING, GARBAGE or INVALID here. */
- switch (dev->state & TASKDEV_ST_STATE_MASK) {
- case TASKDEV_ST_NOTASK:
- break;
- case TASKDEV_ST_ATTACHED:
- goto attached;
-
- case TASKDEV_ST_INVALID:
- up_write(&dev->state_sem);
- mutex_unlock(&dev->usecount_lock);
- return -ENODEV;
-
- case TASKDEV_ST_FREEZED:
- case TASKDEV_ST_KILLING:
- case TASKDEV_ST_GARBAGE:
- case TASKDEV_ST_DELREQ:
- /* on the kill process. wait until it becomes NOTASK. */
- up_write(&dev->state_sem);
- mutex_unlock(&dev->usecount_lock);
- if (devstate_write_lock(dev, TASKDEV_ST_NOTASK) < 0)
- return -EINTR;
- devstate_write_unlock(dev);
- goto restart;
- }
-
- /* NOTASK */
- set_taskdev_state(dev, TASKDEV_ST_ADDREQ);
- /* wake up twch daemon for tadd */
- dsp_twch_touch();
- up_write(&dev->state_sem);
- if (devstate_write_lock(dev, TASKDEV_ST_ATTACHED |
- TASKDEV_ST_ADDFAIL) < 0) {
- /* cancelled */
- if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
- mutex_unlock(&dev->usecount_lock);
- /* out of control ??? */
- return -EINTR;
- }
- set_taskdev_state(dev, TASKDEV_ST_NOTASK);
- ret = -EINTR;
- goto change_out;
- }
- if (dev->state & TASKDEV_ST_ADDFAIL) {
- printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
- dev->name);
- ret = -EBUSY;
- set_taskdev_state(dev, TASKDEV_ST_NOTASK);
- goto change_out;
- }
-
- attached:
- ret = proc_list_add(&dev->proc_list_lock,
- &dev->proc_list, current, file);
- if (ret)
- goto out;
-
- dev->usecount++;
- file->f_op = &dev->fops;
- up_write(&dev->state_sem);
- mutex_unlock(&dev->usecount_lock);
-
-#ifdef DSP_PTE_FREE /* not used currently. */
- dsp_map_update(current);
- dsp_cur_users_add(current);
-#endif /* DSP_PTE_FREE */
- return 0;
-
- change_out:
- wake_up_interruptible_all(&dev->state_wait_q);
- out:
- up_write(&dev->state_sem);
- mutex_unlock(&dev->usecount_lock);
- return ret;
-}
-
-static int dsp_task_release(struct inode *inode, struct file *file)
-{
- unsigned int minor = MINOR(inode->i_rdev);
- struct taskdev *dev = taskdev[minor];
-
-#ifdef DSP_PTE_FREE /* not used currently. */
- dsp_cur_users_del(current);
-#endif /* DSP_PTE_FREE */
-
- if (has_taskdev_lock(dev))
- taskdev_unlock(dev);
-
- proc_list_del(&dev->proc_list_lock, &dev->proc_list, current, file);
- mutex_lock(&dev->usecount_lock);
- if (--dev->usecount > 0) {
- /* other processes are using this device. no state change. */
- mutex_unlock(&dev->usecount_lock);
- return 0;
- }
-
- /* usecount == 0 */
- down_write(&dev->state_sem);
-
- /* state can be ATTACHED/FREEZED, KILLING or GARBAGE here. */
- switch (dev->state & TASKDEV_ST_STATE_MASK) {
-
- case TASKDEV_ST_KILLING:
- break;
-
- case TASKDEV_ST_GARBAGE:
- set_taskdev_state(dev, TASKDEV_ST_NOTASK);
- wake_up_interruptible_all(&dev->state_wait_q);
- break;
-
- case TASKDEV_ST_ATTACHED:
- case TASKDEV_ST_FREEZED:
- if (is_dynamic_task(minor)) {
- set_taskdev_state(dev, TASKDEV_ST_DELREQ);
- /* wake up twch daemon for tdel */
- dsp_twch_touch();
- }
- break;
-
- }
-
- up_write(&dev->state_sem);
- mutex_unlock(&dev->usecount_lock);
- return 0;
-}
-
-/*
- * mkdev / rmdev
- */
-int dsp_mkdev(char *name)
-{
- struct taskdev *dev;
- int status;
- unsigned char minor;
- int ret;
-
- if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
- printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
- return -EINVAL;
- }
-
- if (mutex_lock_interruptible(&devmgr_lock))
- return -EINTR;
-
- /* naming check */
- for (minor = 0; minor < TASKDEV_MAX; minor++) {
- if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
- printk(KERN_ERR
- "omapdsp: task device name %s is already "
- "in use.\n", name);
- ret = -EINVAL;
- goto out;
- }
- }
-
- /* find free minor number */
- for (minor = n_task; minor < TASKDEV_MAX; minor++) {
- if (taskdev[minor] == NULL)
- goto do_make;
- }
- printk(KERN_ERR "omapdsp: Too many task devices.\n");
- ret = -EBUSY;
- goto out;
-
-do_make:
- if ((dev = kzalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- if ((status = taskdev_init(dev, name, minor)) < 0) {
- kfree(dev);
- ret = status;
- goto out;
- }
- ret = minor;
-
-out:
- mutex_unlock(&devmgr_lock);
- return ret;
-}
-
-int dsp_rmdev(char *name)
-{
- unsigned char minor;
- int status;
- int ret;
-
- if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
- printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
- return -EINVAL;
- }
-
- if (mutex_lock_interruptible(&devmgr_lock))
- return -EINTR;
-
- /* find in dynamic devices */
- for (minor = n_task; minor < TASKDEV_MAX; minor++) {
- if (taskdev[minor] && !strcmp(taskdev[minor]->name, name))
- goto do_remove;
- }
-
- /* find in static devices */
- for (minor = 0; minor < n_task; minor++) {
- if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
- printk(KERN_ERR
- "omapdsp: task device %s is static.\n", name);
- ret = -EINVAL;
- goto out;
- }
- }
-
- printk(KERN_ERR "omapdsp: task device %s not found.\n", name);
- return -EINVAL;
-
-do_remove:
- ret = minor;
- if ((status = dsp_rmdev_minor(minor)) < 0)
- ret = status;
-out:
- mutex_unlock(&devmgr_lock);
- return ret;
-}
-
-static int dsp_rmdev_minor(unsigned char minor)
-{
- struct taskdev *dev = taskdev[minor];
-
- while (!down_write_trylock(&dev->state_sem)) {
- down_read(&dev->state_sem);
- if (dev->state & (TASKDEV_ST_ATTACHED |
- TASKDEV_ST_FREEZED)) {
- /*
- * task is working. kill it.
- * ATTACHED -> FREEZED can be changed under
- * down_read of state_sem..
- */
- set_taskdev_state(dev, TASKDEV_ST_FREEZED);
- wake_up_interruptible_all(&dev->read_wait_q);
- wake_up_interruptible_all(&dev->write_wait_q);
- wake_up_interruptible_all(&dev->tctl_wait_q);
- }
- up_read(&dev->state_sem);
- schedule();
- }
-
- switch (dev->state & TASKDEV_ST_STATE_MASK) {
-
- case TASKDEV_ST_NOTASK:
- case TASKDEV_ST_INVALID:
- /* fine */
- goto notask;
-
- case TASKDEV_ST_ATTACHED:
- case TASKDEV_ST_FREEZED:
- /* task is working. kill it. */
- set_taskdev_state(dev, TASKDEV_ST_KILLING);
- up_write(&dev->state_sem);
- dsp_tdel_bh(dev, TDEL_KILL);
- goto invalidate;
-
- case TASKDEV_ST_ADDREQ:
- /* open() is waiting. drain it. */
- set_taskdev_state(dev, TASKDEV_ST_ADDFAIL);
- wake_up_interruptible_all(&dev->state_wait_q);
- break;
-
- case TASKDEV_ST_DELREQ:
- /* nobody is waiting. */
- set_taskdev_state(dev, TASKDEV_ST_NOTASK);
- wake_up_interruptible_all(&dev->state_wait_q);
- break;
-
- case TASKDEV_ST_ADDING:
- case TASKDEV_ST_DELING:
- case TASKDEV_ST_KILLING:
- case TASKDEV_ST_GARBAGE:
- case TASKDEV_ST_ADDFAIL:
- /* transient state. wait for a moment. */
- break;
-
- }
-
- up_write(&dev->state_sem);
-
-invalidate:
- /* wait for some time and hope the state is settled */
- devstate_read_lock_timeout(dev, TASKDEV_ST_NOTASK, 5 * HZ);
- if (!(dev->state & TASKDEV_ST_NOTASK)) {
- printk(KERN_WARNING
- "omapdsp: illegal device state (%s) on rmdev %s.\n",
- devstate_name(dev->state), dev->name);
- }
-notask:
- set_taskdev_state(dev, TASKDEV_ST_INVALID);
- devstate_read_unlock(dev);
-
- taskdev_delete(minor);
- kfree(dev);
-
- return 0;
-}
-
-static struct file_operations dsp_task_fops = {
- .owner = THIS_MODULE,
- .poll = dsp_task_poll,
- .ioctl = dsp_task_ioctl,
- .open = dsp_task_open,
- .release = dsp_task_release,
-};
-
-static void dsptask_dev_release(struct device *dev)
-{
-}
-
-static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
-{
- int ret;
- struct device *task_dev;
-
- taskdev[minor] = dev;
-
- spin_lock_init(&dev->proc_list_lock);
- INIT_LIST_HEAD(&dev->proc_list);
- init_waitqueue_head(&dev->read_wait_q);
- init_waitqueue_head(&dev->write_wait_q);
- init_waitqueue_head(&dev->tctl_wait_q);
- mutex_init(&dev->read_mutex);
- mutex_init(&dev->write_mutex);
- mutex_init(&dev->tctl_mutex);
- mutex_init(&dev->lock);
- spin_lock_init(&dev->wsz_lock);
- dev->tctl_ret = -EINVAL;
- dev->lock_pid = 0;
-
- strncpy(dev->name, name, TNM_LEN);
- dev->name[TNM_LEN-1] = '\0';
- set_taskdev_state(dev, (minor < n_task) ? TASKDEV_ST_ATTACHED : TASKDEV_ST_NOTASK);
- dev->usecount = 0;
- mutex_init(&dev->usecount_lock);
- memcpy(&dev->fops, &dsp_task_fops, sizeof(struct file_operations));
-
- dev->dev.parent = omap_dsp->dev;
- dev->dev.bus = &dsptask_bus;
- sprintf(dev->dev.bus_id, "dsptask%d", minor);
- dev->dev.release = dsptask_dev_release;
- ret = device_register(&dev->dev);
- if (ret) {
- printk(KERN_ERR "device_register failed: %d\n", ret);
- return ret;
- }
- ret = device_create_file(&dev->dev, &dev_attr_devname);
- if (ret)
- goto fail_create_devname;
- ret = device_create_file(&dev->dev, &dev_attr_devstate);
- if (ret)
- goto fail_create_devstate;
- ret = device_create_file(&dev->dev, &dev_attr_proc_list);
- if (ret)
- goto fail_create_proclist;
-
- task_dev = device_create(dsp_task_class, NULL,
- MKDEV(OMAP_DSP_TASK_MAJOR, minor),
- "dsptask%d", (int)minor);
-
- if (unlikely(IS_ERR(task_dev))) {
- ret = -EINVAL;
- goto fail_create_taskclass;
- }
-
- init_waitqueue_head(&dev->state_wait_q);
- init_rwsem(&dev->state_sem);
-
- return 0;
-
- fail_create_taskclass:
- device_remove_file(&dev->dev, &dev_attr_proc_list);
- fail_create_proclist:
- device_remove_file(&dev->dev, &dev_attr_devstate);
- fail_create_devstate:
- device_remove_file(&dev->dev, &dev_attr_devname);
- fail_create_devname:
- device_unregister(&dev->dev);
- return ret;
-}
-
-static void taskdev_delete(unsigned char minor)
-{
- struct taskdev *dev = taskdev[minor];
-
- if (!dev)
- return;
- 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);
- device_destroy(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor));
- device_unregister(&dev->dev);
- proc_list_flush(&dev->proc_list_lock, &dev->proc_list);
- taskdev[minor] = NULL;
-}
-
-static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
-{
- u16 ttyp = task->ttyp;
- int ret;
-
- dev->fops.read =
- sndtyp_acv(ttyp) ?
- sndtyp_wd(ttyp) ? dsp_task_read_wd_acv:
- /* sndtyp_bk */ dsp_task_read_bk_acv:
- /* sndtyp_psv */
- sndtyp_wd(ttyp) ? dsp_task_read_wd_psv:
- /* sndtyp_bk */ dsp_task_read_bk_psv;
- if (sndtyp_wd(ttyp)) {
- /* word */
- size_t fifosz = sndtyp_psv(ttyp) ? 2:32; /* passive:active */
-
- dev->rcvdt.fifo = kfifo_alloc(fifosz, GFP_KERNEL,
- &dev->read_lock);
- if (IS_ERR(dev->rcvdt.fifo)) {
- printk(KERN_ERR
- "omapdsp: unable to allocate receive buffer. "
- "(%d bytes for %s)\n", fifosz, dev->name);
- return -ENOMEM;
- }
- } else {
- /* block */
- INIT_IPBLINK(&dev->rcvdt.bk.link);
- dev->rcvdt.bk.rp = 0;
- }
-
- dev->fops.write =
- rcvtyp_wd(ttyp) ? dsp_task_write_wd:
- /* rcvbyp_bk */ dsp_task_write_bk;
- dev->wsz = rcvtyp_acv(ttyp) ? 0 : /* active */
- rcvtyp_wd(ttyp) ? 2 : /* passive word */
- ipbcfg.lsz*2; /* passive block */
-
- if (task->map_length)
- dev->fops.mmap = dsp_task_mmap;
-
- ret = device_create_file(&dev->dev, &dev_attr_taskname);
- if (unlikely(ret))
- goto fail_create_taskname;
- ret = device_create_file(&dev->dev, &dev_attr_ttyp);
- if (unlikely(ret))
- goto fail_create_ttyp;
- ret = device_create_file(&dev->dev, &dev_attr_wsz);
- if (unlikely(ret))
- goto fail_create_wsz;
- if (task->map_length) {
- ret = device_create_file(&dev->dev, &dev_attr_mmap);
- if (unlikely(ret))
- goto fail_create_mmap;
- }
- if (sndtyp_wd(ttyp)) {
- ret = device_create_file(&dev->dev, &dev_attr_fifosz);
- if (unlikely(ret))
- goto fail_create_fifosz;
- ret = device_create_file(&dev->dev, &dev_attr_fifocnt);
- if (unlikely(ret))
- goto fail_create_fifocnt;
- } else {
- ret = device_create_file(&dev->dev, &dev_attr_ipblink);
- if (unlikely(ret))
- goto fail_create_ipblink;
- }
-
- dev->task = task;
- task->dev = dev;
-
- return 0;
-
- fail_create_fifocnt:
- device_remove_file(&dev->dev, &dev_attr_fifosz);
- fail_create_ipblink:
- fail_create_fifosz:
- if (task->map_length)
- device_remove_file(&dev->dev, &dev_attr_mmap);
- fail_create_mmap:
- device_remove_file(&dev->dev, &dev_attr_wsz);
- fail_create_wsz:
- device_remove_file(&dev->dev, &dev_attr_ttyp);
- fail_create_ttyp:
- device_remove_file(&dev->dev, &dev_attr_taskname);
- fail_create_taskname:
- if (task->map_length)
- dev->fops.mmap = NULL;
-
- dev->fops.write = NULL;
- dev->wsz = 0;
-
- dev->fops.read = NULL;
- taskdev_flush_buf(dev);
-
- if (sndtyp_wd(ttyp))
- kfifo_free(dev->rcvdt.fifo);
-
- dev->task = NULL;
-
- return ret;
-}
-
-static void taskdev_detach_task(struct taskdev *dev)
-{
- u16 ttyp = dev->task->ttyp;
-
- device_remove_file(&dev->dev, &dev_attr_taskname);
- device_remove_file(&dev->dev, &dev_attr_ttyp);
- if (sndtyp_wd(ttyp)) {
- device_remove_file(&dev->dev, &dev_attr_fifosz);
- device_remove_file(&dev->dev, &dev_attr_fifocnt);
- } else
- device_remove_file(&dev->dev, &dev_attr_ipblink);
- device_remove_file(&dev->dev, &dev_attr_wsz);
- if (dev->task->map_length) {
- device_remove_file(&dev->dev, &dev_attr_mmap);
- dev->fops.mmap = NULL;
- }
-
- dev->fops.read = NULL;
- taskdev_flush_buf(dev);
- if (sndtyp_wd(ttyp))
- kfifo_free(dev->rcvdt.fifo);
-
- dev->fops.write = NULL;
- dev->wsz = 0;
-
- pr_info("omapdsp: taskdev %s disabled.\n", dev->name);
- dev->task = NULL;
-}
-
-/*
- * tadd / tdel / tkill
- */
-static int dsp_tadd(struct taskdev *dev, dsp_long_t adr)
-{
- struct dsptask *task;
- struct mb_exarg arg;
- u8 tid, tid_response;
- u16 argv[2];
- int ret = 0;
-
- if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
- printk(KERN_ERR
- "omapdsp: taskdev %s is not requesting for tadd. "
- "(state is %s)\n", dev->name, devstate_name(dev->state));
- return -EINVAL;
- }
- set_taskdev_state(dev, TASKDEV_ST_ADDING);
- devstate_write_unlock(dev);
-
- if (adr == TADD_ABORTADR) {
- /* aborting tadd intentionally */
- pr_info("omapdsp: tadd address is ABORTADR.\n");
- goto fail_out;
- }
- if (adr >= DSPSPACE_SIZE) {
- printk(KERN_ERR
- "omapdsp: illegal address 0x%08x for tadd\n", adr);
- ret = -EINVAL;
- goto fail_out;
- }
-
- adr >>= 1; /* word address */
- argv[0] = adr >> 16; /* addrh */
- argv[1] = adr & 0xffff; /* addrl */
-
- if (mutex_lock_interruptible(&cfg_lock)) {
- ret = -EINTR;
- goto fail_out;
- }
- cfg_tid = TID_ANON;
- cfg_cmd = MBOX_CMD_DSP_TADD;
- arg.tid = TID_ANON;
- arg.argc = 2;
- arg.argv = argv;
-
- if (dsp_mem_sync_inc() < 0) {
- printk(KERN_ERR "omapdsp: memory sync failed!\n");
- ret = -EBUSY;
- goto fail_out;
- }
- mbcompose_send_and_wait_exarg(TADD, 0, 0, &arg, &cfg_wait_q);
-
- tid = cfg_tid;
- cfg_tid = TID_ANON;
- cfg_cmd = 0;
- mutex_unlock(&cfg_lock);
-
- if (tid == TID_ANON) {
- printk(KERN_ERR "omapdsp: tadd failed!\n");
- ret = -EINVAL;
- goto fail_out;
- }
- if ((tid < n_task) || dsptask[tid]) {
- printk(KERN_ERR "omapdsp: illegal tid (%d)!\n", tid);
- ret = -EINVAL;
- goto fail_out;
- }
- if ((task = kzalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
- ret = -ENOMEM;
- goto del_out;
- }
-
- if ((ret = dsp_task_config(task, tid)) < 0)
- goto free_out;
-
- if (strcmp(dev->name, task->name)) {
- printk(KERN_ERR
- "omapdsp: task name (%s) doesn't match with "
- "device name (%s).\n", task->name, dev->name);
- ret = -EINVAL;
- goto free_out;
- }
-
- if ((ret = taskdev_attach_task(dev, task)) < 0)
- goto free_out;
-
- dsp_task_init(task);
- pr_info("omapdsp: taskdev %s enabled.\n", dev->name);
- set_taskdev_state(dev, TASKDEV_ST_ATTACHED);
- wake_up_interruptible_all(&dev->state_wait_q);
- return 0;
-
-free_out:
- kfree(task);
-
-del_out:
- printk(KERN_ERR "omapdsp: deleting the task...\n");
-
- set_taskdev_state(dev, TASKDEV_ST_DELING);
-
- if (mutex_lock_interruptible(&cfg_lock)) {
- printk(KERN_ERR "omapdsp: aborting tdel process. "
- "DSP side could be corrupted.\n");
- goto fail_out;
- }
- cfg_tid = TID_ANON;
- cfg_cmd = MBOX_CMD_DSP_TDEL;
- mbcompose_send_and_wait(TDEL, tid, TDEL_KILL, &cfg_wait_q);
- tid_response = cfg_tid;
- cfg_tid = TID_ANON;
- cfg_cmd = 0;
- mutex_unlock(&cfg_lock);
-
- if (tid_response != tid)
- printk(KERN_ERR "omapdsp: tdel failed. "
- "DSP side could be corrupted.\n");
-
-fail_out:
- set_taskdev_state(dev, TASKDEV_ST_ADDFAIL);
- wake_up_interruptible_all(&dev->state_wait_q);
- return ret;
-}
-
-int dsp_tadd_minor(unsigned char minor, dsp_long_t adr)
-{
- struct taskdev *dev;
- int status;
- int ret;
-
- if (mutex_lock_interruptible(&devmgr_lock))
- return -EINTR;
-
- if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
- printk(KERN_ERR
- "omapdsp: no task device with minor %d\n", minor);
- ret = -EINVAL;
- goto out;
- }
- ret = minor;
- if ((status = dsp_tadd(dev, adr)) < 0)
- ret = status;
-
-out:
- mutex_unlock(&devmgr_lock);
- return ret;
-}
-
-static int dsp_tdel(struct taskdev *dev)
-{
- if (!devstate_write_lock_and_test(dev, TASKDEV_ST_DELREQ)) {
- printk(KERN_ERR
- "omapdsp: taskdev %s is not requesting for tdel. "
- "(state is %s)\n", dev->name, devstate_name(dev->state));
- return -EINVAL;
- }
- set_taskdev_state(dev, TASKDEV_ST_DELING);
- devstate_write_unlock(dev);
-
- return dsp_tdel_bh(dev, TDEL_SAFE);
-}
-
-int dsp_tdel_minor(unsigned char minor)
-{
- struct taskdev *dev;
- int status;
- int ret;
-
- if (mutex_lock_interruptible(&devmgr_lock))
- return -EINTR;
-
- if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
- printk(KERN_ERR
- "omapdsp: no task device with minor %d\n", minor);
- ret = -EINVAL;
- goto out;
- }
-
- ret = minor;
- if ((status = dsp_tdel(dev)) < 0)
- ret = status;
-
-out:
- mutex_unlock(&devmgr_lock);
- return ret;
-}
-
-static int dsp_tkill(struct taskdev *dev)
-{
- while (!down_write_trylock(&dev->state_sem)) {
- if (!devstate_read_lock_and_test(dev, (TASKDEV_ST_ATTACHED |
- TASKDEV_ST_FREEZED))) {
- printk(KERN_ERR
- "omapdsp: task has not been attached for "
- "taskdev %s\n", dev->name);
- return -EINVAL;
- }
- /* ATTACHED -> FREEZED can be changed under read semaphore. */
- set_taskdev_state(dev, TASKDEV_ST_FREEZED);
- wake_up_interruptible_all(&dev->read_wait_q);
- wake_up_interruptible_all(&dev->write_wait_q);
- wake_up_interruptible_all(&dev->tctl_wait_q);
- devstate_read_unlock(dev);
- schedule();
- }
-
- if (!(dev->state & (TASKDEV_ST_ATTACHED |
- TASKDEV_ST_FREEZED))) {
- printk(KERN_ERR
- "omapdsp: task has not been attached for taskdev %s\n",
- dev->name);
- devstate_write_unlock(dev);
- return -EINVAL;
- }
- if (!is_dynamic_task(dev->task->tid)) {
- printk(KERN_ERR "omapdsp: task %s is not a dynamic task.\n",
- dev->name);
- devstate_write_unlock(dev);
- return -EINVAL;
- }
- set_taskdev_state(dev, TASKDEV_ST_KILLING);
- devstate_write_unlock(dev);
-
- return dsp_tdel_bh(dev, TDEL_KILL);
-}
-
-int dsp_tkill_minor(unsigned char minor)
-{
- struct taskdev *dev;
- int status;
- int ret;
-
- if (mutex_lock_interruptible(&devmgr_lock))
- return -EINTR;
-
- if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
- printk(KERN_ERR
- "omapdsp: no task device with minor %d\n", minor);
- ret = -EINVAL;
- goto out;
- }
-
- ret = minor;
- if ((status = dsp_tkill(dev)) < 0)
- ret = status;
-
-out:
- mutex_unlock(&devmgr_lock);
- return ret;
-}
-
-static int dsp_tdel_bh(struct taskdev *dev, u16 type)
-{
- struct dsptask *task;
- u8 tid, tid_response;
- int ret = 0;
-
- task = dev->task;
- tid = task->tid;
- if (mutex_lock_interruptible(&cfg_lock)) {
- if (type == TDEL_SAFE) {
- set_taskdev_state(dev, TASKDEV_ST_DELREQ);
- return -EINTR;
- } else {
- tid_response = TID_ANON;
- ret = -EINTR;
- goto detach_out;
- }
- }
- cfg_tid = TID_ANON;
- cfg_cmd = MBOX_CMD_DSP_TDEL;
- mbcompose_send_and_wait(TDEL, tid, type, &cfg_wait_q);
- tid_response = cfg_tid;
- cfg_tid = TID_ANON;
- cfg_cmd = 0;
- mutex_unlock(&cfg_lock);
-
-detach_out:
- taskdev_detach_task(dev);
- dsp_task_unconfig(task);
- kfree(task);
-
- if (tid_response != tid) {
- printk(KERN_ERR "omapdsp: %s failed!\n",
- (type == TDEL_SAFE) ? "tdel" : "tkill");
- ret = -EINVAL;
- }
- down_write(&dev->state_sem);
- set_taskdev_state(dev, (dev->usecount > 0) ? TASKDEV_ST_GARBAGE :
- TASKDEV_ST_NOTASK);
- wake_up_interruptible_all(&dev->state_wait_q);
- up_write(&dev->state_sem);
-
- return ret;
-}
-
-/*
- * state inquiry
- */
-long taskdev_state_stale(unsigned char minor)
-{
- if (taskdev[minor]) {
- long state = taskdev[minor]->state;
- taskdev[minor]->state |= TASKDEV_ST_STALE;
- return state;
- } else
- return TASKDEV_ST_NOTASK;
-}
-
-/*
- * functions called from mailbox interrupt routine
- */
-void mbox_wdsnd(struct mbcmd *mb)
-{
- unsigned int n;
- u8 tid = mb->cmd_l;
- u16 data = mb->data;
- struct dsptask *task = dsptask[tid];
-
- if ((tid >= TASKDEV_MAX) || (task == NULL)) {
- printk(KERN_ERR "mbox: WDSND with illegal tid! %d\n", tid);
- return;
- }
- if (sndtyp_bk(task->ttyp)) {
- printk(KERN_ERR
- "mbox: WDSND from block sending task! (task%d)\n", tid);
- return;
- }
- if (sndtyp_psv(task->ttyp) &&
- !waitqueue_active(&task->dev->read_wait_q)) {
- printk(KERN_WARNING
- "mbox: WDSND from passive sending task (task%d) "
- "without request!\n", tid);
- return;
- }
-
- n = kfifo_put(task->dev->rcvdt.fifo, (unsigned char *)&data,
- sizeof(data));
- if (n != sizeof(data))
- printk(KERN_WARNING "Receive FIFO(%d) is full\n", tid);
-
- wake_up_interruptible(&task->dev->read_wait_q);
-}
-
-void mbox_wdreq(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
- struct dsptask *task = dsptask[tid];
- struct taskdev *dev;
-
- if ((tid >= TASKDEV_MAX) || (task == NULL)) {
- printk(KERN_ERR "mbox: WDREQ with illegal tid! %d\n", tid);
- return;
- }
- if (rcvtyp_psv(task->ttyp)) {
- printk(KERN_ERR
- "mbox: WDREQ from passive receiving task! (task%d)\n",
- tid);
- return;
- }
-
- dev = task->dev;
- spin_lock(&dev->wsz_lock);
- dev->wsz = 2;
- spin_unlock(&dev->wsz_lock);
- wake_up_interruptible(&dev->write_wait_q);
-}
-
-void mbox_bksnd(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
- u16 bid = mb->data;
- struct dsptask *task = dsptask[tid];
- struct ipbuf_head *ipb_h;
- u16 cnt;
-
- if (bid >= ipbcfg.ln) {
- printk(KERN_ERR "mbox: BKSND with illegal bid! %d\n", bid);
- return;
- }
- ipb_h = bid_to_ipbuf(bid);
- ipb_bsycnt_dec(&ipbcfg);
- if ((tid >= TASKDEV_MAX) || (task == NULL)) {
- printk(KERN_ERR "mbox: BKSND with illegal tid! %d\n", tid);
- goto unuse_ipbuf_out;
- }
- if (sndtyp_wd(task->ttyp)) {
- printk(KERN_ERR
- "mbox: BKSND from word sending task! (task%d)\n", tid);
- goto unuse_ipbuf_out;
- }
- if (sndtyp_pvt(task->ttyp)) {
- printk(KERN_ERR
- "mbox: BKSND from private sending task! (task%d)\n", tid);
- goto unuse_ipbuf_out;
- }
- if (sync_with_dsp(&ipb_h->p->sd, tid, 10) < 0) {
- printk(KERN_ERR "mbox: BKSND - IPBUF sync failed!\n");
- return;
- }
-
- /* should be done in DSP, but just in case. */
- ipb_h->p->next = BID_NULL;
-
- cnt = ipb_h->p->c;
- if (cnt > ipbcfg.lsz) {
- printk(KERN_ERR "mbox: BKSND cnt(%d) > ipbuf line size(%d)!\n",
- cnt, ipbcfg.lsz);
- goto unuse_ipbuf_out;
- }
-
- if (cnt == 0) {
- /* 0-byte send from DSP */
- unuse_ipbuf_nowait(ipb_h);
- goto done;
- }
- ipblink_add_tail(&task->dev->rcvdt.bk.link, bid);
- /* we keep coming bid and return alternative line to DSP. */
- balance_ipbuf();
-
-done:
- wake_up_interruptible(&task->dev->read_wait_q);
- return;
-
-unuse_ipbuf_out:
- unuse_ipbuf_nowait(ipb_h);
- return;
-}
-
-void mbox_bkreq(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
- u16 cnt = mb->data;
- struct dsptask *task = dsptask[tid];
- struct taskdev *dev;
-
- if ((tid >= TASKDEV_MAX) || (task == NULL)) {
- printk(KERN_ERR "mbox: BKREQ with illegal tid! %d\n", tid);
- return;
- }
- if (rcvtyp_wd(task->ttyp)) {
- printk(KERN_ERR
- "mbox: BKREQ from word receiving task! (task%d)\n", tid);
- return;
- }
- if (rcvtyp_pvt(task->ttyp)) {
- printk(KERN_ERR
- "mbox: BKREQ from private receiving task! (task%d)\n",
- tid);
- return;
- }
- if (rcvtyp_psv(task->ttyp)) {
- printk(KERN_ERR
- "mbox: BKREQ from passive receiving task! (task%d)\n",
- tid);
- return;
- }
-
- dev = task->dev;
- spin_lock(&dev->wsz_lock);
- dev->wsz = cnt*2;
- spin_unlock(&dev->wsz_lock);
- wake_up_interruptible(&dev->write_wait_q);
-}
-
-void mbox_bkyld(struct mbcmd *mb)
-{
- u16 bid = mb->data;
- struct ipbuf_head *ipb_h;
-
- if (bid >= ipbcfg.ln) {
- printk(KERN_ERR "mbox: BKYLD with illegal bid! %d\n", bid);
- return;
- }
- ipb_h = bid_to_ipbuf(bid);
-
- /* should be done in DSP, but just in case. */
- ipb_h->p->next = BID_NULL;
-
- /* we don't need to sync with DSP */
- ipb_bsycnt_dec(&ipbcfg);
- release_ipbuf(ipb_h);
-}
-
-void mbox_bksndp(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
- struct dsptask *task = dsptask[tid];
- struct ipbuf_p *ipbp;
-
- if ((tid >= TASKDEV_MAX) || (task == NULL)) {
- printk(KERN_ERR "mbox: BKSNDP with illegal tid! %d\n", tid);
- return;
- }
- if (sndtyp_wd(task->ttyp)) {
- printk(KERN_ERR
- "mbox: BKSNDP from word sending task! (task%d)\n", tid);
- return;
- }
- if (sndtyp_gbl(task->ttyp)) {
- printk(KERN_ERR
- "mbox: BKSNDP from non-private sending task! (task%d)\n",
- tid);
- return;
- }
-
- /*
- * we should not have delayed block at this point
- * because read() routine releases the lock of the buffer and
- * until then DSP can't send next data.
- */
-
- ipbp = task->ipbuf_pvt_r;
- if (sync_with_dsp(&ipbp->s, tid, 10) < 0) {
- printk(KERN_ERR "mbox: BKSNDP - IPBUF sync failed!\n");
- return;
- }
- pr_debug("mbox: ipbuf_pvt_r->a = 0x%08lx\n",
- MKLONG(ipbp->ah, ipbp->al));
- ipblink_add_pvt(&task->dev->rcvdt.bk.link);
- wake_up_interruptible(&task->dev->read_wait_q);
-}
-
-void mbox_bkreqp(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
- struct dsptask *task = dsptask[tid];
- struct taskdev *dev;
- struct ipbuf_p *ipbp;
-
- if ((tid >= TASKDEV_MAX) || (task == NULL)) {
- printk(KERN_ERR "mbox: BKREQP with illegal tid! %d\n", tid);
- return;
- }
- if (rcvtyp_wd(task->ttyp)) {
- printk(KERN_ERR
- "mbox: BKREQP from word receiving task! (task%d)\n", tid);
- return;
- }
- if (rcvtyp_gbl(task->ttyp)) {
- printk(KERN_ERR
- "mbox: BKREQP from non-private receiving task! (task%d)\n", tid);
- return;
- }
- if (rcvtyp_psv(task->ttyp)) {
- printk(KERN_ERR
- "mbox: BKREQP from passive receiving task! (task%d)\n", tid);
- return;
- }
-
- ipbp = task->ipbuf_pvt_w;
- if (sync_with_dsp(&ipbp->s, TID_FREE, 10) < 0) {
- printk(KERN_ERR "mbox: BKREQP - IPBUF sync failed!\n");
- return;
- }
- pr_debug("mbox: ipbuf_pvt_w->a = 0x%08lx\n",
- MKLONG(ipbp->ah, ipbp->al));
- dev = task->dev;
- spin_lock(&dev->wsz_lock);
- dev->wsz = ipbp->c*2;
- spin_unlock(&dev->wsz_lock);
- wake_up_interruptible(&dev->write_wait_q);
-}
-
-void mbox_tctl(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
- struct dsptask *task = dsptask[tid];
-
- if ((tid >= TASKDEV_MAX) || (task == NULL)) {
- printk(KERN_ERR "mbox: TCTL with illegal tid! %d\n", tid);
- return;
- }
-
- if (!waitqueue_active(&task->dev->tctl_wait_q)) {
- printk(KERN_WARNING "mbox: unexpected TCTL from DSP!\n");
- return;
- }
-
- task->dev->tctl_stat = mb->data;
- wake_up_interruptible(&task->dev->tctl_wait_q);
-}
-
-void mbox_tcfg(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
- struct dsptask *task = dsptask[tid];
- u16 *tnm;
- volatile u16 *buf;
- int i;
-
- if ((tid >= TASKDEV_MAX) || (task == NULL)) {
- printk(KERN_ERR "mbox: TCFG with illegal tid! %d\n", tid);
- return;
- }
- if ((task->state != TASK_ST_CFGREQ) || (cfg_cmd != MBOX_CMD_DSP_TCFG)) {
- printk(KERN_WARNING "mbox: unexpected TCFG from DSP!\n");
- return;
- }
-
- if (dsp_mem_enable(ipbuf_sys_da) < 0) {
- printk(KERN_ERR "mbox: TCFG - ipbuf_sys_da read failed!\n");
- dsp_mem_disable(ipbuf_sys_da);
- goto out;
- }
- if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
- printk(KERN_ERR "mbox: TCFG - IPBUF sync failed!\n");
- dsp_mem_disable(ipbuf_sys_da);
- goto out;
- }
-
- /*
- * read configuration data on system IPBUF
- */
- buf = ipbuf_sys_da->d;
- task->ttyp = buf[0];
- task->ipbuf_pvt_r = MKVIRT(buf[1], buf[2]);
- task->ipbuf_pvt_w = MKVIRT(buf[3], buf[4]);
- task->map_base = MKVIRT(buf[5], buf[6]);
- task->map_length = MKLONG(buf[7], buf[8]) << 1; /* word -> byte */
- tnm = MKVIRT(buf[9], buf[10]);
- release_ipbuf_pvt(ipbuf_sys_da);
- dsp_mem_disable(ipbuf_sys_da);
-
- /*
- * copy task name string
- */
- if (dsp_address_validate(tnm, TNM_LEN, "task name buffer") < 0) {
- task->name[0] = '\0';
- goto out;
- }
-
- for (i = 0; i < TNM_LEN-1; i++) {
- /* avoiding byte access */
- u16 tmp = tnm[i];
- task->name[i] = tmp & 0x00ff;
- if (!tmp)
- break;
- }
- task->name[TNM_LEN-1] = '\0';
-
- task->state = TASK_ST_READY;
-out:
- wake_up_interruptible(&cfg_wait_q);
-}
-
-void mbox_tadd(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
-
- if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBOX_CMD_DSP_TADD)) {
- printk(KERN_WARNING "mbox: unexpected TADD from DSP!\n");
- return;
- }
- cfg_tid = tid;
- wake_up_interruptible(&cfg_wait_q);
-}
-
-void mbox_tdel(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
-
- if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBOX_CMD_DSP_TDEL)) {
- printk(KERN_WARNING "mbox: unexpected TDEL from DSP!\n");
- return;
- }
- cfg_tid = tid;
- wake_up_interruptible(&cfg_wait_q);
-}
-
-void mbox_err_fatal(u8 tid)
-{
- struct dsptask *task = dsptask[tid];
- struct taskdev *dev;
-
- if ((tid >= TASKDEV_MAX) || (task == NULL)) {
- printk(KERN_ERR "mbox: FATAL ERR with illegal tid! %d\n", tid);
- return;
- }
-
- /* wake up waiting processes */
- dev = task->dev;
- wake_up_interruptible_all(&dev->read_wait_q);
- wake_up_interruptible_all(&dev->write_wait_q);
- wake_up_interruptible_all(&dev->tctl_wait_q);
-}
-
-static u16 *dbg_buf;
-static u16 dbg_buf_sz, dbg_line_sz;
-static int dbg_rp;
-
-int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz)
-{
-#ifdef OLD_BINARY_SUPPORT
- if ((mbox_revision == MBREV_3_0) || (mbox_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 mbox_dbg_old(struct mbcmd *mb);
-#endif
-
-void mbox_dbg(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
- int cnt = mb->data;
- char s[80], *s_end = &s[79], *p;
- u16 *src;
- int i;
-
-#ifdef OLD_BINARY_SUPPORT
- if ((mbox_revision == MBREV_3_0) || (mbox_revision == MBREV_3_2)) {
- mbox_dbg_old(mb);
- return;
- }
-#endif
-
- if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
- (tid != TID_ANON)) {
- printk(KERN_ERR "mbox: DBG with illegal tid! %d\n", tid);
- return;
- }
- if (dbg_buf == NULL) {
- printk(KERN_ERR "mbox: 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++) {
- u16 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';
- pr_info("%s", s);
- p = s;
- continue;
- }
- if (p == s_end) {
- *p = '\0';
- pr_info("%s\n", s);
- p = s;
- continue;
- }
- }
- if (p > s) {
- *p = '\0';
- pr_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 mbox_dbg_old(struct mbcmd *mb)
-{
- u8 tid = mb->cmd_l;
- char s[80], *s_end = &s[79], *p;
- u16 *src;
- volatile u16 *buf;
- int cnt;
- int i;
-
- if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
- (tid != TID_ANON)) {
- printk(KERN_ERR "mbox: DBG with illegal tid! %d\n", tid);
- return;
- }
- if (dsp_mem_enable(ipbuf_sys_da) < 0) {
- printk(KERN_ERR "mbox: DBG - ipbuf_sys_da read failed!\n");
- return;
- }
- if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
- printk(KERN_ERR "mbox: DBG - IPBUF sync failed!\n");
- goto out1;
- }
- buf = ipbuf_sys_da->d;
- cnt = buf[0];
- src = MKVIRT(buf[1], buf[2]);
- if (dsp_address_validate(src, cnt, "dbg buffer") < 0)
- goto out2;
-
- if (dsp_mem_enable(src) < 0)
- goto out2;
-
- p = s;
- for (i = 0; i < cnt; i++) {
- u16 tmp;
- /*
- * Be carefull that ipbuf 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';
- pr_info("%s", s);
- p = s;
- continue;
- }
- if (p == s_end) {
- *p = '\0';
- pr_info("%s\n", s);
- p = s;
- continue;
- }
- }
- if (p > s) {
- *p = '\0';
- pr_info("%s\n", s);
- }
-
- dsp_mem_disable(src);
-out2:
- release_ipbuf_pvt(ipbuf_sys_da);
-out1:
- dsp_mem_disable(ipbuf_sys_da);
-}
-#endif /* OLD_BINARY_SUPPORT */
-
-/*
- * sysfs files: for each device
- */
-
-/* devname */
-static ssize_t devname_show(struct device *d, struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%s\n", to_taskdev(d)->name);
-}
-
-/* devstate */
-static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%s\n", devstate_name(to_taskdev(d)->state));
-}
-
-/* proc_list */
-static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
- char *buf)
-{
- struct taskdev *dev;
- struct proc_list *pl;
- int len = 0;
-
- dev = to_taskdev(d);
- spin_lock(&dev->proc_list_lock);
- list_for_each_entry(pl, &dev->proc_list, list_head) {
- /* need to lock tasklist_lock before calling
- * find_task_by_pid_type. */
- if (find_task_by_pid(pl->pid) != NULL)
- len += sprintf(buf + len, "%d\n", pl->pid);
- read_unlock(&tasklist_lock);
- }
- spin_unlock(&dev->proc_list_lock);
-
- return len;
-}
-
-/* taskname */
-static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
- char *buf)
-{
- struct taskdev *dev = to_taskdev(d);
- int len;
-
- if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
- return -ENODEV;
-
- len = sprintf(buf, "%s\n", dev->task->name);
-
- devstate_read_unlock(dev);
- return len;
-}
-
-/* ttyp */
-static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
- char *buf)
-{
- struct taskdev *dev = to_taskdev(d);
- u16 ttyp;
- int len = 0;
-
- if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
- return -ENODEV;
-
- ttyp = dev->task->ttyp;
- len += sprintf(buf + len, "0x%04x\n", ttyp);
- len += sprintf(buf + len, "%s %s send\n",
- (sndtyp_acv(ttyp)) ? "active" :
- "passive",
- (sndtyp_wd(ttyp)) ? "word" :
- (sndtyp_pvt(ttyp)) ? "private block" :
- "global block");
- len += sprintf(buf + len, "%s %s receive\n",
- (rcvtyp_acv(ttyp)) ? "active" :
- "passive",
- (rcvtyp_wd(ttyp)) ? "word" :
- (rcvtyp_pvt(ttyp)) ? "private block" :
- "global block");
-
- devstate_read_unlock(dev);
- return len;
-}
-
-/* fifosz */
-static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
- char *buf)
-{
- struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo;
- return sprintf(buf, "%d\n", fifo->size);
-}
-
-static int fifosz_store(struct device *d, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct taskdev *dev = to_taskdev(d);
- unsigned long fifosz;
- int ret;
-
- fifosz = simple_strtol(buf, NULL, 10);
- if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
- return -ENODEV;
- ret = taskdev_set_fifosz(dev, fifosz);
- taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
-
- return (ret < 0) ? ret : strlen(buf);
-}
-
-/* fifocnt */
-static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
- char *buf)
-{
- struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo;
- return sprintf(buf, "%d\n", fifo->size);
-}
-
-/* ipblink */
-static inline char *bid_name(u16 bid)
-{
- static char s[6];
-
- switch (bid) {
- case BID_NULL:
- return "NULL";
- case BID_PVT:
- return "PRIVATE";
- default:
- sprintf(s, "%d", bid);
- return s;
- }
-}
-
-static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
- char *buf)
-{
- struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->rcvdt.bk;
- int len;
-
- spin_lock(&rcvdt->link.lock);
- len = sprintf(buf, "top %s\ntail %s\n",
- bid_name(rcvdt->link.top), bid_name(rcvdt->link.tail));
- spin_unlock(&rcvdt->link.lock);
-
- return len;
-}
-
-/* wsz */
-static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%d\n", to_taskdev(d)->wsz);
-}
-
-/* mmap */
-static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
- char *buf)
-{
- struct dsptask *task = to_taskdev(d)->task;
- return sprintf(buf, "0x%p 0x%x\n", task->map_base, task->map_length);
-}
-
-/*
- * called from ipbuf_show()
- */
-int ipbuf_is_held(u8 tid, u16 bid)
-{
- struct dsptask *task = dsptask[tid];
- struct ipblink *link;
- u16 b;
- int ret = 0;
-
- if (task == NULL)
- return 0;
-
- link = &task->dev->rcvdt.bk.link;
- spin_lock(&link->lock);
- ipblink_for_each(b, link) {
- if (b == bid) { /* found */
- ret = 1;
- break;
- }
- }
- spin_unlock(&link->lock);
-
- return ret;
-}
-
-int __init dsp_taskmod_init(void)
-{
- int retval;
-
- memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX);
- memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX);
-
- retval = register_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask",
- &dsp_task_fops);
- if (retval < 0) {
- printk(KERN_ERR
- "omapdsp: failed to register task device: %d\n", retval);
- return retval;
- }
-
- retval = bus_register(&dsptask_bus);
- if (retval) {
- printk(KERN_ERR
- "omapdsp: failed to register DSP task bus: %d\n",
- retval);
- unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
- return -EINVAL;
- }
- retval = driver_register(&dsptask_driver);
- if (retval) {
- printk(KERN_ERR
- "omapdsp: failed to register DSP task driver: %d\n",
- retval);
- bus_unregister(&dsptask_bus);
- unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
- return -EINVAL;
- }
- dsp_task_class = class_create(THIS_MODULE, "dsptask");
- if (IS_ERR(dsp_task_class)) {
- printk(KERN_ERR "omapdsp: failed to create DSP task class\n");
- driver_unregister(&dsptask_driver);
- bus_unregister(&dsptask_bus);
- unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
- return -EINVAL;
- }
-
- return 0;
-}
-
-void dsp_taskmod_exit(void)
-{
- class_destroy(dsp_task_class);
- driver_unregister(&dsptask_driver);
- bus_unregister(&dsptask_bus);
- unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
-}
diff --git a/arch/arm/plat-omap/dsp/taskwatch.c b/arch/arm/plat-omap/dsp/taskwatch.c
deleted file mode 100644
index 4297b51..0000000
--- a/arch/arm/plat-omap/dsp/taskwatch.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <asm/uaccess.h>
-#include <asm/arch/dsp.h>
-#include "dsp_mbcmd.h"
-#include "dsp.h"
-
-static DECLARE_WAIT_QUEUE_HEAD(read_wait_q);
-static unsigned int change_cnt;
-
-void dsp_twch_touch(void)
-{
- change_cnt++;
- wake_up_interruptible(&read_wait_q);
-}
-
-/*
- * @count: represents the device counts of the user's interst
- */
-static ssize_t dsp_twch_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- long taskstat[TASKDEV_MAX];
- int devcount = count / sizeof(long);
- int i;
- DEFINE_WAIT(wait);
-
- if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
- printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
- return -EINVAL;
- }
-
- prepare_to_wait(&read_wait_q, &wait, TASK_INTERRUPTIBLE);
- if (change_cnt == 0) /* last check */
- schedule();
- finish_wait(&read_wait_q, &wait);
-
- /* unconfigured while waiting ;-( */
- if ((change_cnt == 0) && (dsp_cfgstat_get_stat() != CFGSTAT_READY))
- return -EINVAL;
-
- if (devcount > TASKDEV_MAX)
- devcount = TASKDEV_MAX;
-
- count = devcount * sizeof(long);
- change_cnt = 0;
- for (i = 0; i < devcount; 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))
- return -EFAULT;
-
- return count;
-}
-
-static unsigned int dsp_twch_poll(struct file *file, poll_table *wait)
-{
- unsigned int mask = 0;
-
- poll_wait(file, &read_wait_q, wait);
- if (change_cnt)
- mask |= POLLIN | POLLRDNORM;
-
- return mask;
-}
-
-static int dsp_twch_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- int ret;
-
- switch (cmd) {
- case TWCH_IOCTL_MKDEV:
- {
- char name[TNM_LEN];
- if (copy_from_user(name, (void __user *)arg, TNM_LEN))
- return -EFAULT;
- name[TNM_LEN-1] = '\0';
- ret = dsp_mkdev(name);
- break;
- }
-
- case TWCH_IOCTL_RMDEV:
- {
- char name[TNM_LEN];
- if (copy_from_user(name, (void __user *)arg, TNM_LEN))
- return -EFAULT;
- name[TNM_LEN-1] = '\0';
- ret = dsp_rmdev(name);
- break;
- }
-
- case TWCH_IOCTL_TADD:
- {
- struct omap_dsp_taddinfo ti;
- if (copy_from_user(&ti, (void __user *)arg, sizeof(ti)))
- return -EFAULT;
- ret = dsp_tadd_minor(ti.minor, ti.taskadr);
- break;
- }
-
- case TWCH_IOCTL_TDEL:
- ret = dsp_tdel_minor(arg);
- break;
-
- case TWCH_IOCTL_TKILL:
- ret = dsp_tkill_minor(arg);
- break;
-
- default:
- return -ENOIOCTLCMD;
- }
-
- return ret;
-}
-
-struct file_operations dsp_twch_fops = {
- .owner = THIS_MODULE,
- .read = dsp_twch_read,
- .poll = dsp_twch_poll,
- .ioctl = dsp_twch_ioctl,
-};
-
-void dsp_twch_start(void)
-{
- change_cnt = 1; /* first read will not wait */
-}
-
-void dsp_twch_stop(void)
-{
- wake_up_interruptible(&read_wait_q);
-}
diff --git a/arch/arm/plat-omap/dsp/uaccess_dsp.S b/arch/arm/plat-omap/dsp/uaccess_dsp.S
deleted file mode 100644
index bcf4a54..0000000
--- a/arch/arm/plat-omap/dsp/uaccess_dsp.S
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
- .text
-
-/* Prototype: int __copy_to_user_dsp_2b(void *to, const char *from)
- * Purpose : copy 2 bytes to user memory from kernel(DSP) memory
- * escaping from unexpected byte swap using __copy_to_user()
- * in OMAP architecture.
- * Params : to - user memory
- * : from - kernel(DSP) memory
- * Returns : success = 0, failure = 2
- */
-
-ENTRY(__copy_to_user_dsp_2b)
- stmfd sp!, {r4, lr}
- ldrb r3, [r1], #1
- ldrb r4, [r1], #1
-USER( strbt r4, [r0], #1) @ May fault
-USER( strbt r3, [r0], #1) @ May fault
- mov r0, #0
- ldmfd sp!, {r4, pc}
-
- .section .fixup,"ax"
- .align 0
-9001: mov r0, #2
- ldmfd sp!, {r4, pc}
- .previous
-
-/* Prototype: unsigned long __copy_from_user_dsp_2b(void *to, const void *from);
- * Purpose : copy 2 bytes from user memory to kernel(DSP) memory
- * escaping from unexpected byte swap using __copy_to_user()
- * in OMAP architecture.
- * Params : to - kernel (DSP) memory
- * : from - user memory
- * Returns : success = 0, failure = 2
- */
-
-ENTRY(__copy_from_user_dsp_2b)
- stmfd sp!, {r4, lr}
-USER( ldrbt r3, [r1], #1) @ May fault
-USER( ldrbt r4, [r1], #1) @ May fault
- strb r4, [r0], #1
- strb r3, [r0], #1
- mov r0, #0
- ldmfd sp!, {r4, pc}
-
- .section .fixup,"ax"
- .align 0
-9001: mov r3, #0
- strh r3, [r0], #2
- mov r0, #2
- ldmfd sp!, {r4, pc}
- .previous
diff --git a/arch/arm/plat-omap/dsp/uaccess_dsp.h b/arch/arm/plat-omap/dsp/uaccess_dsp.h
deleted file mode 100644
index 028814f..0000000
--- a/arch/arm/plat-omap/dsp/uaccess_dsp.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
- *
- * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
- *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef _OMAP_DSP_UACCESS_DSP_H
-#define _OMAP_DSP_UACCESS_DSP_H
-
-#include <asm/uaccess.h>
-#include <asm/arch/dsp_common.h>
-#include "dsp.h"
-
-#define HAVE_ASM_COPY_FROM_USER_DSP_2B
-
-#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
-extern unsigned long __copy_from_user_dsp_2b(void *to,
- const void __user *from);
-extern unsigned long __copy_to_user_dsp_2b(void __user *to,
- const void *from);
-#endif
-
-#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
-static inline unsigned long copy_from_user_dsp_2b(void *to,
- const void *from)
-{
- unsigned short tmp;
-
- if (__copy_from_user(&tmp, from, 2))
- return 2;
- /* expecting compiler to generate "strh" instruction */
- *((unsigned short *)to) = tmp;
- return 0;
-}
-#endif
-
-/*
- * @n must be multiple of 2
- */
-static inline unsigned long copy_from_user_dsp(void *to, const void *from,
- unsigned long n)
-{
- if (access_ok(VERIFY_READ, from, n)) {
- if ((is_dsp_internal_mem(to)) &&
- (((unsigned long)to & 2) || (n & 2))) {
- /*
- * DARAM/SARAM with odd word alignment
- */
- unsigned long n4;
- unsigned long last_n;
-
- /* dest not aligned -- copy 2 bytes */
- if (((unsigned long)to & 2) && (n >= 2)) {
-#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
- if (__copy_from_user_dsp_2b(to, from))
-#else
- if (copy_from_user_dsp_2b(to, from))
-#endif
- return n;
- to += 2;
- from += 2;
- n -= 2;
- }
- /* middle 4*n bytes */
- last_n = n & 2;
- n4 = n - last_n;
- if ((n = __copy_from_user(to, from, n4)) != 0)
- return n + last_n;
- /* last 2 bytes */
- if (last_n) {
- to += n4;
- from += n4;
-#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
- if (__copy_from_user_dsp_2b(to, from))
-#else
- if (copy_from_user_dsp_2b(to, from))
-#endif
- return 2;
- n = 0;
- }
- } else {
- /*
- * DARAM/SARAM with 4-byte alignment or
- * external memory
- */
- n = __copy_from_user(to, from, n);
- }
- }
- else /* security hole - plug it */
- memzero(to, n);
- return n;
-}
-
-#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
-static inline unsigned long copy_to_user_dsp_2b(void *to, const void *from)
-{
- /* expecting compiler to generate "strh" instruction */
- unsigned short tmp = *(unsigned short *)from;
-
- return __copy_to_user(to, &tmp, 2);
-}
-#endif
-
-/*
- * @n must be multiple of 2
- */
-static inline unsigned long copy_to_user_dsp(void *to, const void *from,
- unsigned long n)
-{
- if (access_ok(VERIFY_WRITE, to, n)) {
- if ((is_dsp_internal_mem(from)) &&
- (((unsigned long)to & 2) || (n & 2))) {
- /*
- * DARAM/SARAM with odd word alignment
- */
- unsigned long n4;
- unsigned long last_n;
-
- /* dest not aligned -- copy 2 bytes */
- if (((unsigned long)to & 2) && (n >= 2)) {
-#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
- if (__copy_to_user_dsp_2b(to, from))
-#else
- if (copy_to_user_dsp_2b(to, from))
-#endif
- return n;
- to += 2;
- from += 2;
- n -= 2;
- }
- /* middle 4*n bytes */
- last_n = n & 2;
- n4 = n - last_n;
- if ((n = __copy_to_user(to, from, n4)) != 0)
- return n + last_n;
- /* last 2 bytes */
- if (last_n) {
- to += n4;
- from += n4;
-#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
- if (__copy_to_user_dsp_2b(to, from))
-#else
- if (copy_to_user_dsp_2b(to, from))
-#endif
- return 2;
- n = 0;
- }
- } else {
- /*
- * DARAM/SARAM with 4-byte alignment or
- * external memory
- */
- n = __copy_to_user(to, from, n);
- }
- }
- return n;
-}
-
-#endif /* _OMAP_DSP_UACCESS_DSP_H */
diff --git a/drivers/Makefile b/drivers/Makefile
index 94b4442..b10394e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_PARPORT) += parport/
obj-y += base/ block/ misc/ mfd/ net/ media/ cbus/
obj-$(CONFIG_I2C) += i2c/
obj-y += cbus/
+obj-y += dsp/dspgateway/
obj-$(CONFIG_NUBUS) += nubus/
obj-$(CONFIG_ATM) += atm/
obj-y += macintosh/
diff --git a/drivers/dsp/dspgateway/Kconfig b/drivers/dsp/dspgateway/Kconfig
new file mode 100644
index 0000000..122164a
--- /dev/null
+++ b/drivers/dsp/dspgateway/Kconfig
@@ -0,0 +1,24 @@
+
+config OMAP_DSP
+ tristate "OMAP DSP driver (DSP Gateway)"
+ depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP24XX
+ select OMAP_MMU_FWK
+ select OMAP_MBOX_FWK
+ help
+ This enables OMAP DSP driver, DSP Gateway.
+
+config OMAP_DSP_MBCMD_VERBOSE
+ bool "Mailbox Command Verbose LOG"
+ depends on OMAP_DSP
+ help
+ This enables kernel log output in the Mailbox command exchanges
+ in the DSP Gateway driver.
+
+config OMAP_DSP_FBEXPORT
+ bool "Framebuffer export to DSP"
+ depends on OMAP_DSP && FB
+ help
+ This enables to map the frame buffer to DSP.
+ By doing this, DSP can access the frame buffer directly without
+ bothering ARM.
+
diff --git a/drivers/dsp/dspgateway/Makefile b/drivers/dsp/dspgateway/Makefile
new file mode 100644
index 0000000..c7d86f3
--- /dev/null
+++ b/drivers/dsp/dspgateway/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the OMAP DSP driver.
+#
+
+# The target object and module list name.
+
+obj-y := dsp_common.o
+
+obj-$(CONFIG_OMAP_DSP) += dsp.o
+
+# Declare multi-part drivers
+
+dsp-objs := dsp_core.o ipbuf.o mblog.o task.o \
+ dsp_ctl_core.o dsp_ctl.o taskwatch.o error.o dsp_mem.o \
+ uaccess_dsp.o
diff --git a/drivers/dsp/dspgateway/dsp.h b/drivers/dsp/dspgateway/dsp.h
new file mode 100644
index 0000000..23321be
--- /dev/null
+++ b/drivers/dsp/dspgateway/dsp.h
@@ -0,0 +1,391 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __PLAT_OMAP_DSP_DSP_H
+#define __PLAT_OMAP_DSP_DSP_H
+
+#include "hardware_dsp.h"
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/mmu.h>
+
+
+#ifdef CONFIG_ARCH_OMAP2
+#include "../../../arch/arm/mach-omap2/prm.h"
+#include "../../../arch/arm/mach-omap2/prm_regbits_24xx.h"
+#include "../../../arch/arm/mach-omap2/cm.h"
+#include "../../../arch/arm/mach-omap2/cm_regbits_24xx.h"
+#endif
+
+/*
+ * MAJOR device number: !! allocated arbitrary !!
+ */
+#define OMAP_DSP_CTL_MAJOR 96
+#define OMAP_DSP_TASK_MAJOR 97
+
+#define OLD_BINARY_SUPPORT y
+
+#ifdef OLD_BINARY_SUPPORT
+#define MBREV_3_0 0x0017
+#define MBREV_3_2 0x0018
+#endif
+
+#define DSP_INIT_PAGE 0xfff000
+
+#ifdef CONFIG_ARCH_OMAP1
+/* idle program will be placed at IDLEPG_BASE. */
+#define IDLEPG_BASE 0xfffe00
+#define IDLEPG_SIZE 0x100
+#endif /* CONFIG_ARCH_OMAP1 */
+
+/* timeout value for DSP response */
+#define DSP_TIMEOUT (10 * HZ)
+
+enum dsp_mem_type_e {
+ MEM_TYPE_CROSSING = -1,
+ MEM_TYPE_NONE = 0,
+ MEM_TYPE_DARAM,
+ MEM_TYPE_SARAM,
+ MEM_TYPE_EXTERN,
+};
+
+
+typedef int __bitwise arm_dsp_dir_t;
+#define DIR_A2D ((__force arm_dsp_dir_t) 1)
+#define DIR_D2A ((__force arm_dsp_dir_t) 2)
+
+enum cfgstat_e {
+ CFGSTAT_CLEAN = 0,
+ CFGSTAT_READY,
+ CFGSTAT_SUSPEND,
+ CFGSTAT_RESUME, /* request only */
+ CFGSTAT_MAX
+};
+
+enum errcode_e {
+ ERRCODE_WDT = 0,
+ ERRCODE_MMU,
+ ERRCODE_MAX
+};
+
+/* keep 2 entries for TID_FREE and TID_ANON */
+#define TASKDEV_MAX 254
+
+#define MK32(uw,lw) (((u32)(uw)) << 16 | (lw))
+#define MKLONG(uw,lw) (((unsigned long)(uw)) << 16 | (lw))
+#define MKVIRT(uw,lw) dspword_to_virt(MKLONG((uw), (lw)));
+
+struct sync_seq {
+ u16 da_dsp;
+ u16 da_arm;
+ u16 ad_dsp;
+ u16 ad_arm;
+};
+
+struct mem_sync_struct {
+ struct sync_seq *DARAM;
+ struct sync_seq *SARAM;
+ struct sync_seq *SDRAM;
+};
+
+/* struct mbcmd and union mbcmd_hw must be compatible */
+struct mbcmd {
+ u32 data:16;
+ u32 cmd_l:8;
+ u32 cmd_h:7;
+ u32 seq:1;
+};
+
+#define MBCMD_INIT(h, l, d) { \
+ .cmd_h = (h), \
+ .cmd_l = (l), \
+ .data = (d), \
+ }
+
+struct mb_exarg {
+ u8 tid;
+ int argc;
+ u16 *argv;
+};
+
+typedef u32 dsp_long_t; /* must have ability to carry TADD_ABORTADR */
+
+extern void dsp_mbox_start(void);
+extern void dsp_mbox_stop(void);
+extern int dsp_mbox_config(void *p);
+extern int sync_with_dsp(u16 *syncwd, u16 tid, int try_cnt);
+extern int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+ int recovery_flag);
+#define dsp_mbcmd_send(mb) __dsp_mbcmd_send_exarg((mb), NULL, 0)
+#define dsp_mbcmd_send_exarg(mb, arg) __dsp_mbcmd_send_exarg((mb), (arg), 0)
+extern int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+ wait_queue_head_t *q);
+#define dsp_mbcmd_send_and_wait(mb, q) \
+ dsp_mbcmd_send_and_wait_exarg((mb), NULL, (q))
+
+static inline int __mbcompose_send_exarg(u8 cmd_h, u8 cmd_l, u16 data,
+ struct mb_exarg *arg,
+ int recovery_flag)
+{
+ struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
+ return __dsp_mbcmd_send_exarg(&mb, arg, recovery_flag);
+}
+#define mbcompose_send(cmd_h, cmd_l, data) \
+ __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 0)
+#define mbcompose_send_exarg(cmd_h, cmd_l, data, arg) \
+ __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), arg, 0)
+#define mbcompose_send_recovery(cmd_h, cmd_l, data) \
+ __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 1)
+
+static inline int __mbcompose_send_and_wait_exarg(u8 cmd_h, u8 cmd_l,
+ u16 data,
+ struct mb_exarg *arg,
+ wait_queue_head_t *q)
+{
+ struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
+ return dsp_mbcmd_send_and_wait_exarg(&mb, arg, q);
+}
+#define mbcompose_send_and_wait(cmd_h, cmd_l, data, q) \
+ __mbcompose_send_and_wait_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), \
+ NULL, (q))
+#define mbcompose_send_and_wait_exarg(cmd_h, cmd_l, data, arg, q) \
+ __mbcompose_send_and_wait_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), \
+ (arg), (q))
+
+extern struct ipbuf_head *bid_to_ipbuf(u16 bid);
+extern void ipbuf_start(void);
+extern void ipbuf_stop(void);
+extern int ipbuf_config(u16 ln, u16 lsz, void *base);
+extern int ipbuf_sys_config(void *p, arm_dsp_dir_t dir);
+extern int ipbuf_p_validate(void *p, arm_dsp_dir_t dir);
+extern struct ipbuf_head *get_free_ipbuf(u8 tid);
+extern void release_ipbuf(struct ipbuf_head *ipb_h);
+extern void balance_ipbuf(void);
+extern void unuse_ipbuf(struct ipbuf_head *ipb_h);
+extern void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h);
+
+#define release_ipbuf_pvt(ipbuf_pvt) \
+ do { \
+ (ipbuf_pvt)->s = TID_FREE; \
+ } while(0)
+
+extern int mbox_revision;
+
+extern int dsp_cfgstat_request(enum cfgstat_e st);
+extern enum cfgstat_e dsp_cfgstat_get_stat(void);
+extern int dsp_set_runlevel(u8 level);
+
+extern int dsp_task_config_all(u8 n);
+extern void dsp_task_unconfig_all(void);
+extern u8 dsp_task_count(void);
+extern int dsp_taskmod_busy(void);
+extern int dsp_mkdev(char *name);
+extern int dsp_rmdev(char *name);
+extern int dsp_tadd_minor(unsigned char minor, dsp_long_t adr);
+extern int dsp_tdel_minor(unsigned char minor);
+extern int dsp_tkill_minor(unsigned char minor);
+extern long taskdev_state_stale(unsigned char minor);
+extern int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz);
+extern void dsp_dbg_stop(void);
+
+extern int ipbuf_is_held(u8 tid, u16 bid);
+
+extern int dsp_mem_sync_inc(void);
+extern int dsp_mem_sync_config(struct mem_sync_struct *sync);
+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, ...);
+#ifdef CONFIG_ARCH_OMAP1
+extern void dsp_mem_usecount_clear(void);
+#endif
+extern void exmap_use(void *vadr, size_t len);
+extern void exmap_unuse(void *vadr, size_t len);
+extern unsigned long dsp_virt_to_phys(void *vadr, size_t *len);
+extern void dsp_mem_start(void);
+extern void dsp_mem_stop(void);
+
+extern void dsp_twch_start(void);
+extern void dsp_twch_stop(void);
+extern void dsp_twch_touch(void);
+
+extern void dsp_err_start(void);
+extern void dsp_err_stop(void);
+extern void dsp_err_set(enum errcode_e code, unsigned long arg);
+extern void dsp_err_clear(enum errcode_e code);
+extern int dsp_err_isset(enum errcode_e code);
+
+enum cmd_l_type_e {
+ CMD_L_TYPE_NULL,
+ CMD_L_TYPE_TID,
+ CMD_L_TYPE_SUBCMD,
+};
+
+struct cmdinfo {
+ char *name;
+ enum cmd_l_type_e cmd_l_type;
+ void (*handler)(struct mbcmd *mb);
+};
+
+extern const struct cmdinfo *cmdinfo[];
+
+#define cmd_name(mb) (cmdinfo[(mb).cmd_h]->name)
+extern char *subcmd_name(struct mbcmd *mb);
+
+extern void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir);
+
+extern struct omap_mmu dsp_mmu;
+
+#define dsp_mem_enable(addr) omap_mmu_mem_enable(&dsp_mmu, (addr))
+#define dsp_mem_disable(addr) omap_mmu_mem_disable(&dsp_mmu, (addr))
+
+#define DSPSPACE_SIZE 0x1000000
+
+#define omap_set_bit_regw(b,r) \
+ do { omap_writew(omap_readw(r) | (b), (r)); } while(0)
+#define omap_clr_bit_regw(b,r) \
+ do { omap_writew(omap_readw(r) & ~(b), (r)); } while(0)
+#define omap_set_bit_regl(b,r) \
+ do { omap_writel(omap_readl(r) | (b), (r)); } while(0)
+#define omap_clr_bit_regl(b,r) \
+ do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0)
+#define omap_set_bits_regl(val,mask,r) \
+ do { omap_writel((omap_readl(r) & ~(mask)) | (val), (r)); } while(0)
+
+#define dspword_to_virt(dw) ((void *)(dspmem_base + ((dw) << 1)))
+#define dspbyte_to_virt(db) ((void *)(dspmem_base + (db)))
+#define virt_to_dspword(va) \
+ ((dsp_long_t)(((unsigned long)(va) - dspmem_base) >> 1))
+#define virt_to_dspbyte(va) \
+ ((dsp_long_t)((unsigned long)(va) - dspmem_base))
+#define is_dsp_internal_mem(va) \
+ (((unsigned long)(va) >= dspmem_base) && \
+ ((unsigned long)(va) < dspmem_base + dspmem_size))
+#define is_dspbyte_internal_mem(db) ((db) < dspmem_size)
+#define is_dspword_internal_mem(dw) (((dw) << 1) < dspmem_size)
+
+#ifdef CONFIG_ARCH_OMAP1
+/*
+ * MPUI byteswap/wordswap on/off
+ * default setting: wordswap = all, byteswap = APIMEM only
+ */
+#define mpui_wordswap_on() \
+ omap_set_bits_regl(MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL_WORDSWAP_MASK, \
+ MPUI_CTRL)
+
+#define mpui_wordswap_off() \
+ omap_set_bits_regl(MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL_WORDSWAP_MASK, \
+ MPUI_CTRL)
+
+#define mpui_byteswap_on() \
+ omap_set_bits_regl(MPUI_CTRL_BYTESWAP_API, MPUI_CTRL_BYTESWAP_MASK, \
+ MPUI_CTRL)
+
+#define mpui_byteswap_off() \
+ omap_set_bits_regl(MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL_BYTESWAP_MASK, \
+ 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() omap_clr_bit_regl(TC_ENDIANISM_EN, TC_ENDIANISM)
+
+/*
+ * enable priority registers, EMIF, MPUI control logic
+ */
+#define __dsp_enable() omap_set_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
+#define __dsp_disable() omap_clr_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1)
+#define __dsp_run() omap_set_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
+#define __dsp_reset() omap_clr_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1)
+#endif /* CONFIG_ARCH_OMAP1 */
+
+#ifdef CONFIG_ARCH_OMAP2
+/*
+ * PRCM / IPI control logic
+ *
+ * REVISIT: these macros should probably be static inline functions
+ */
+#define __dsp_core_enable() \
+ do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
+ & ~OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
+#define __dsp_core_disable() \
+ do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
+ | OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
+#define __dsp_per_enable() \
+ do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
+ & ~OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
+#define __dsp_per_disable() \
+ do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \
+ | OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0)
+#endif /* CONFIG_ARCH_OMAP2 */
+
+#if defined(CONFIG_ARCH_OMAP1)
+extern struct clk *dsp_ck_handle;
+extern struct clk *api_ck_handle;
+#elif defined(CONFIG_ARCH_OMAP2)
+extern struct clk *dsp_fck_handle;
+extern struct clk *dsp_ick_handle;
+#endif
+extern dsp_long_t dspmem_base, dspmem_size,
+ daram_base, daram_size,
+ saram_base, saram_size;
+
+enum cpustat_e {
+ CPUSTAT_RESET = 0,
+#ifdef CONFIG_ARCH_OMAP1
+ CPUSTAT_GBL_IDLE,
+ CPUSTAT_CPU_IDLE,
+#endif
+ CPUSTAT_RUN,
+ CPUSTAT_MAX
+};
+
+int dsp_set_rstvect(dsp_long_t adr);
+dsp_long_t dsp_get_rstvect(void);
+void dsp_set_idle_boot_base(dsp_long_t adr, size_t size);
+void dsp_reset_idle_boot_base(void);
+void dsp_cpustat_request(enum cpustat_e req);
+enum cpustat_e dsp_cpustat_get_stat(void);
+u16 dsp_cpustat_get_icrmask(void);
+void dsp_cpustat_set_icrmask(u16 mask);
+void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void));
+void dsp_unregister_mem_cb(void);
+
+#if defined(CONFIG_ARCH_OMAP1)
+#define command_dvfs_stop(m) (0)
+#define command_dvfs_start(m) (0)
+#elif defined(CONFIG_ARCH_OMAP2)
+#define command_dvfs_stop(m) \
+ (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_STOP))
+#define command_dvfs_start(m) \
+ (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_START))
+#endif
+
+extern struct omap_dsp *omap_dsp;
+
+extern int dsp_late_init(void);
+
+#endif /* __PLAT_OMAP_DSP_DSP_H */
diff --git a/drivers/dsp/dspgateway/dsp_common.c b/drivers/dsp/dspgateway/dsp_common.c
new file mode 100644
index 0000000..99be995
--- /dev/null
+++ b/drivers/dsp/dspgateway/dsp_common.c
@@ -0,0 +1,627 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/tlbflush.h>
+#include <asm/irq.h>
+#include <asm/arch/dsp_common.h>
+#include "dsp.h"
+
+#ifdef CONFIG_ARCH_OMAP1
+#include <asm/arch/tc.h>
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1)
+#define dsp_boot_config(mode) omap_writew((mode), MPUI_DSP_BOOT_CONFIG)
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#define dsp_boot_config(mode) writel((mode), DSP_IPI_DSPBOOTCONFIG)
+#endif
+
+struct omap_dsp *omap_dsp;
+
+#if defined(CONFIG_ARCH_OMAP1)
+struct clk *dsp_ck_handle;
+struct clk *api_ck_handle;
+#elif defined(CONFIG_ARCH_OMAP2)
+struct clk *dsp_fck_handle;
+struct clk *dsp_ick_handle;
+#endif
+dsp_long_t dspmem_base, dspmem_size,
+ daram_base, daram_size,
+ saram_base, saram_size;
+
+static struct cpustat {
+ struct mutex lock;
+ enum cpustat_e stat;
+ enum cpustat_e req;
+ u16 icrmask;
+#ifdef CONFIG_ARCH_OMAP1
+ struct {
+ int mpui;
+ int mem;
+ int mem_delayed;
+ } usecount;
+ int (*mem_req_cb)(void);
+ void (*mem_rel_cb)(void);
+#endif
+} cpustat = {
+ .stat = CPUSTAT_RESET,
+ .icrmask = 0xffff,
+};
+
+int dsp_set_rstvect(dsp_long_t adr)
+{
+ unsigned long *dst_adr;
+
+ if (adr >= DSPSPACE_SIZE)
+ return -EINVAL;
+
+ dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT);
+ /* word swap */
+ *dst_adr = ((adr & 0xffff) << 16) | (adr >> 16);
+ /* fill 8 bytes! */
+ *(dst_adr + 1) = 0;
+ /* direct boot */
+ dsp_boot_config(DSP_BOOT_CONFIG_DIRECT);
+
+ return 0;
+}
+
+dsp_long_t dsp_get_rstvect(void)
+{
+ unsigned long *dst_adr;
+
+ dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT);
+ return ((*dst_adr & 0xffff) << 16) | (*dst_adr >> 16);
+}
+
+#ifdef CONFIG_ARCH_OMAP1
+static void simple_load_code(unsigned char *src_c, u16 *dst, int len)
+{
+ int i;
+ u16 *src = (u16 *)src_c;
+ int len_w;
+
+ /* len must be multiple of 2. */
+ if (len & 1)
+ BUG();
+
+ len_w = len / 2;
+ for (i = 0; i < len_w; i++) {
+ /* byte swap copy */
+ *dst = ((*src & 0x00ff) << 8) |
+ ((*src & 0xff00) >> 8);
+ src++;
+ dst++;
+ }
+}
+
+/* program size must be multiple of 2 */
+#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 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 */ \
+ 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 /* 0x20: nop */ \
+}
+
+/*
+ * idle_boot base:
+ * Initialized with DSP_BOOT_ADR_MPUI (=0x010000).
+ * This value is used before DSP Gateway driver is initialized.
+ * DSP Gateway driver will overwrite this value with other value,
+ * to avoid confliction with the user program.
+ */
+static dsp_long_t idle_boot_base = DSP_BOOT_ADR_MPUI;
+
+static void dsp_gbl_idle(void)
+{
+ unsigned char idle_text[GBL_IDLE_TEXT_SIZE] = GBL_IDLE_TEXT_INIT;
+
+ __dsp_reset();
+ clk_enable(api_ck_handle);
+
+#if 0
+ dsp_boot_config(DSP_BOOT_CONFIG_IDLE);
+#endif
+ simple_load_code(idle_text, dspbyte_to_virt(idle_boot_base),
+ GBL_IDLE_TEXT_SIZE);
+ if (idle_boot_base == DSP_BOOT_ADR_MPUI)
+ dsp_boot_config(DSP_BOOT_CONFIG_MPUI);
+ else
+ dsp_set_rstvect(idle_boot_base);
+
+ __dsp_run();
+ udelay(100); /* to make things stable */
+ clk_disable(api_ck_handle);
+}
+
+static void dsp_cpu_idle(void)
+{
+ u16 icr_tmp;
+ unsigned char icrh, icrl;
+
+ __dsp_reset();
+ clk_enable(api_ck_handle);
+
+ /*
+ * icr settings:
+ * DMA should not sleep for DARAM/SARAM access
+ * DPLL should not sleep while any other domain is active
+ */
+ icr_tmp = cpustat.icrmask & ~(DSPREG_ICR_DMA | DSPREG_ICR_DPLL);
+ icrh = icr_tmp >> 8;
+ icrl = icr_tmp & 0xff;
+ {
+ 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),
+ CPU_IDLE_TEXT_SIZE);
+ }
+ if (idle_boot_base == DSP_BOOT_ADR_MPUI)
+ dsp_boot_config(DSP_BOOT_CONFIG_MPUI);
+ else
+ dsp_set_rstvect(idle_boot_base);
+ __dsp_run();
+ udelay(100); /* to make things stable */
+ clk_disable(api_ck_handle);
+}
+
+void dsp_set_idle_boot_base(dsp_long_t adr, size_t size)
+{
+ if (adr == idle_boot_base)
+ return;
+ idle_boot_base = adr;
+ if ((size < GBL_IDLE_TEXT_SIZE) ||
+ (size < CPU_IDLE_TEXT_SIZE)) {
+ printk(KERN_ERR
+ "omapdsp: size for idle program is not enough!\n");
+ BUG();
+ }
+
+ /* 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();
+}
+
+void dsp_reset_idle_boot_base(void)
+{
+ idle_boot_base = DSP_BOOT_ADR_MPUI;
+}
+#else
+void dsp_reset_idle_boot_base(void) { }
+#endif /* CONFIG_ARCH_OMAP1 */
+
+static int init_done;
+
+static int omap_dsp_init(void)
+{
+ mutex_init(&cpustat.lock);
+
+ dspmem_size = 0;
+#ifdef CONFIG_ARCH_OMAP15XX
+ if (cpu_is_omap15xx()) {
+ 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
+#ifdef CONFIG_ARCH_OMAP24XX
+ if (cpu_is_omap24xx()) {
+ dspmem_base = DSP_MEM_24XX_VIRT;
+ dspmem_size = DSP_MEM_24XX_SIZE;
+ daram_base = OMAP24XX_DARAM_BASE;
+ daram_size = OMAP24XX_DARAM_SIZE;
+ saram_base = OMAP24XX_SARAM_BASE;
+ saram_size = OMAP24XX_SARAM_SIZE;
+ }
+#endif
+#ifdef CONFIG_ARCH_OMAP34XX
+ /* To be Revisited for 3430 */
+ if (cpu_is_omap34xx()) {
+ return -ENODEV;
+ }
+#endif
+ if (dspmem_size == 0) {
+ printk(KERN_ERR "omapdsp: unsupported omap architecture.\n");
+ return -ENODEV;
+ }
+
+#if defined(CONFIG_ARCH_OMAP1)
+ dsp_ck_handle = clk_get(NULL, "dsp_ck");
+ if (IS_ERR(dsp_ck_handle)) {
+ printk(KERN_ERR "omapdsp: could not acquire dsp_ck handle.\n");
+ return PTR_ERR(dsp_ck_handle);
+ }
+
+ api_ck_handle = clk_get(NULL, "api_ck");
+ if (IS_ERR(api_ck_handle)) {
+ printk(KERN_ERR "omapdsp: could not acquire api_ck handle.\n");
+ if (dsp_ck_handle != NULL)
+ clk_put(dsp_ck_handle);
+ return PTR_ERR(api_ck_handle);
+ }
+
+ /* This is needed for McBSP init, released in late_initcall */
+ clk_enable(api_ck_handle);
+
+ __dsp_enable();
+ mpui_byteswap_off();
+ mpui_wordswap_on();
+ tc_wordswap();
+#elif defined(CONFIG_ARCH_OMAP2)
+ dsp_fck_handle = clk_get(NULL, "dsp_fck");
+ if (IS_ERR(dsp_fck_handle)) {
+ printk(KERN_ERR "omapdsp: could not acquire dsp_fck handle.\n");
+ return PTR_ERR(dsp_fck_handle);
+ }
+
+ dsp_ick_handle = clk_get(NULL, "dsp_ick");
+ if (IS_ERR(dsp_ick_handle)) {
+ printk(KERN_ERR "omapdsp: could not acquire dsp_ick handle.\n");
+ if (dsp_fck_handle != NULL)
+ clk_put(dsp_fck_handle);
+ return PTR_ERR(dsp_ick_handle);
+ }
+#endif
+
+ init_done = 1;
+ pr_info("omap_dsp_init() done\n");
+ return 0;
+}
+
+#if defined(CONFIG_ARCH_OMAP1)
+static int __dsp_late_init(void)
+{
+ clk_disable(api_ck_handle);
+ return 0;
+}
+late_initcall(__dsp_late_init);
+#endif
+
+static void dsp_cpustat_update(void)
+{
+ if (!init_done)
+ omap_dsp_init();
+
+ if (cpustat.req == CPUSTAT_RUN) {
+ if (cpustat.stat < CPUSTAT_RUN) {
+#if defined(CONFIG_ARCH_OMAP1)
+ __dsp_reset();
+ clk_enable(api_ck_handle);
+ udelay(10);
+ __dsp_run();
+#elif defined(CONFIG_ARCH_OMAP2)
+ __dsp_core_disable();
+ udelay(10);
+ __dsp_core_enable();
+#endif
+ cpustat.stat = CPUSTAT_RUN;
+ }
+ return;
+ }
+
+ /* cpustat.req < CPUSTAT_RUN */
+
+ if (cpustat.stat == CPUSTAT_RUN) {
+#ifdef CONFIG_ARCH_OMAP1
+ clk_disable(api_ck_handle);
+#endif
+ }
+
+#ifdef CONFIG_ARCH_OMAP1
+ /*
+ * (1) when ARM wants DARAM access, MPUI should be SAM and
+ * DSP needs to be on.
+ * (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;
+ }
+#endif /* CONFIG_ARCH_OMAP1 */
+
+ /*
+ * no user, no request
+ */
+ if (cpustat.stat != CPUSTAT_RESET) {
+#if defined(CONFIG_ARCH_OMAP1)
+ __dsp_reset();
+#elif defined(CONFIG_ARCH_OMAP2)
+ __dsp_core_disable();
+#endif
+ cpustat.stat = CPUSTAT_RESET;
+ }
+}
+
+void dsp_cpustat_request(enum cpustat_e req)
+{
+ mutex_lock(&cpustat.lock);
+ cpustat.req = req;
+ dsp_cpustat_update();
+ mutex_unlock(&cpustat.lock);
+}
+
+enum cpustat_e dsp_cpustat_get_stat(void)
+{
+ return cpustat.stat;
+}
+
+u16 dsp_cpustat_get_icrmask(void)
+{
+ return cpustat.icrmask;
+}
+
+void dsp_cpustat_set_icrmask(u16 mask)
+{
+ mutex_lock(&cpustat.lock);
+ cpustat.icrmask = mask;
+ dsp_cpustat_update();
+ mutex_unlock(&cpustat.lock);
+}
+
+#ifdef CONFIG_ARCH_OMAP1
+void omap_dsp_request_mpui(void)
+{
+ mutex_lock(&cpustat.lock);
+ if (cpustat.usecount.mpui++ == 0)
+ dsp_cpustat_update();
+ mutex_unlock(&cpustat.lock);
+}
+
+void omap_dsp_release_mpui(void)
+{
+ mutex_lock(&cpustat.lock);
+ 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();
+ mutex_unlock(&cpustat.lock);
+}
+
+int omap_dsp_request_mem(void)
+{
+ int ret = 0;
+
+ mutex_lock(&cpustat.lock);
+ 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:
+ mutex_unlock(&cpustat.lock);
+
+ return ret;
+}
+
+/*
+ * release_mem will be delayed.
+ */
+static void do_release_mem(struct work_struct *dummy)
+{
+ mutex_lock(&cpustat.lock);
+ cpustat.usecount.mem_delayed = 0;
+ if (cpustat.usecount.mem == 0) {
+ dsp_cpustat_update();
+ if (cpustat.mem_rel_cb)
+ cpustat.mem_rel_cb();
+ }
+ mutex_unlock(&cpustat.lock);
+}
+
+static DECLARE_DELAYED_WORK(mem_rel_work, do_release_mem);
+
+int omap_dsp_release_mem(void)
+{
+ mutex_lock(&cpustat.lock);
+
+ /* 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);
+ }
+
+ mutex_unlock(&cpustat.lock);
+
+ return 0;
+}
+
+void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void))
+{
+ mutex_lock(&cpustat.lock);
+
+ 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);
+
+ mutex_unlock(&cpustat.lock);
+}
+
+void dsp_unregister_mem_cb(void)
+{
+ mutex_lock(&cpustat.lock);
+ cpustat.mem_req_cb = NULL;
+ cpustat.mem_rel_cb = NULL;
+ mutex_unlock(&cpustat.lock);
+}
+#else
+void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void)) { }
+void dsp_unregister_mem_cb(void) { }
+#endif /* CONFIG_ARCH_OMAP1 */
+
+arch_initcall(omap_dsp_init);
+
+#ifdef CONFIG_ARCH_OMAP1
+EXPORT_SYMBOL(omap_dsp_request_mpui);
+EXPORT_SYMBOL(omap_dsp_release_mpui);
+EXPORT_SYMBOL(omap_dsp_request_mem);
+EXPORT_SYMBOL(omap_dsp_release_mem);
+#endif /* CONFIG_ARCH_OMAP1 */
+
+#ifdef CONFIG_OMAP_DSP_MODULE
+#if defined(CONFIG_ARCH_OMAP1)
+EXPORT_SYMBOL(dsp_ck_handle);
+EXPORT_SYMBOL(api_ck_handle);
+#elif defined(CONFIG_ARCH_OMAP2)
+EXPORT_SYMBOL(dsp_fck_handle);
+EXPORT_SYMBOL(dsp_ick_handle);
+#endif
+EXPORT_SYMBOL(omap_dsp);
+EXPORT_SYMBOL(dspmem_base);
+EXPORT_SYMBOL(dspmem_size);
+EXPORT_SYMBOL(daram_base);
+EXPORT_SYMBOL(daram_size);
+EXPORT_SYMBOL(saram_base);
+EXPORT_SYMBOL(saram_size);
+EXPORT_SYMBOL(dsp_set_rstvect);
+EXPORT_SYMBOL(dsp_get_rstvect);
+#ifdef CONFIG_ARCH_OMAP1
+EXPORT_SYMBOL(dsp_set_idle_boot_base);
+EXPORT_SYMBOL(dsp_reset_idle_boot_base);
+#endif /* CONFIG_ARCH_OMAP1 */
+EXPORT_SYMBOL(dsp_cpustat_request);
+EXPORT_SYMBOL(dsp_cpustat_get_stat);
+EXPORT_SYMBOL(dsp_cpustat_get_icrmask);
+EXPORT_SYMBOL(dsp_cpustat_set_icrmask);
+EXPORT_SYMBOL(dsp_register_mem_cb);
+EXPORT_SYMBOL(dsp_unregister_mem_cb);
+
+EXPORT_SYMBOL(__cpu_flush_kern_tlb_range);
+EXPORT_SYMBOL(cpu_architecture);
+EXPORT_SYMBOL(pmd_clear_bad);
+#endif
diff --git a/drivers/dsp/dspgateway/dsp_core.c b/drivers/dsp/dspgateway/dsp_core.c
new file mode 100644
index 0000000..05274be
--- /dev/null
+++ b/drivers/dsp/dspgateway/dsp_core.c
@@ -0,0 +1,663 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <asm/delay.h>
+#include <asm/arch/mailbox.h>
+#include <asm/arch/dsp.h>
+#include <asm/arch/dsp_common.h>
+#include "dsp_mbcmd.h"
+#include "dsp.h"
+#include "ipbuf.h"
+
+MODULE_AUTHOR("Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>");
+MODULE_DESCRIPTION("OMAP DSP driver module");
+MODULE_LICENSE("GPL");
+
+static struct sync_seq *mbseq;
+static u16 mbseq_expect_tmp;
+static u16 *mbseq_expect = &mbseq_expect_tmp;
+
+extern int dsp_mem_late_init(void);
+
+/*
+ * mailbox commands
+ */
+extern void mbox_wdsnd(struct mbcmd *mb);
+extern void mbox_wdreq(struct mbcmd *mb);
+extern void mbox_bksnd(struct mbcmd *mb);
+extern void mbox_bkreq(struct mbcmd *mb);
+extern void mbox_bkyld(struct mbcmd *mb);
+extern void mbox_bksndp(struct mbcmd *mb);
+extern void mbox_bkreqp(struct mbcmd *mb);
+extern void mbox_tctl(struct mbcmd *mb);
+extern void mbox_poll(struct mbcmd *mb);
+#ifdef OLD_BINARY_SUPPORT
+/* v3.3 obsolete */
+extern void mbox_wdt(struct mbcmd *mb);
+#endif
+extern void mbox_suspend(struct mbcmd *mb);
+static void mbox_kfunc(struct mbcmd *mb);
+extern void mbox_tcfg(struct mbcmd *mb);
+extern void mbox_tadd(struct mbcmd *mb);
+extern void mbox_tdel(struct mbcmd *mb);
+extern void mbox_dspcfg(struct mbcmd *mb);
+extern void mbox_regrw(struct mbcmd *mb);
+extern void mbox_getvar(struct mbcmd *mb);
+extern void mbox_err(struct mbcmd *mb);
+extern void mbox_dbg(struct mbcmd *mb);
+
+static const struct cmdinfo
+ cif_wdsnd = { "WDSND", CMD_L_TYPE_TID, mbox_wdsnd },
+ cif_wdreq = { "WDREQ", CMD_L_TYPE_TID, mbox_wdreq },
+ cif_bksnd = { "BKSND", CMD_L_TYPE_TID, mbox_bksnd },
+ cif_bkreq = { "BKREQ", CMD_L_TYPE_TID, mbox_bkreq },
+ cif_bkyld = { "BKYLD", CMD_L_TYPE_NULL, mbox_bkyld },
+ cif_bksndp = { "BKSNDP", CMD_L_TYPE_TID, mbox_bksndp },
+ cif_bkreqp = { "BKREQP", CMD_L_TYPE_TID, mbox_bkreqp },
+ cif_tctl = { "TCTL", CMD_L_TYPE_TID, mbox_tctl },
+ cif_poll = { "POLL", CMD_L_TYPE_NULL, mbox_poll },
+#ifdef OLD_BINARY_SUPPORT
+ /* v3.3 obsolete */
+ cif_wdt = { "WDT", CMD_L_TYPE_NULL, mbox_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, mbox_suspend },
+ cif_kfunc = { "KFUNC", CMD_L_TYPE_SUBCMD, mbox_kfunc },
+ cif_tcfg = { "TCFG", CMD_L_TYPE_TID, mbox_tcfg },
+ cif_tadd = { "TADD", CMD_L_TYPE_TID, mbox_tadd },
+ cif_tdel = { "TDEL", CMD_L_TYPE_TID, mbox_tdel },
+ cif_tstop = { "TSTOP", CMD_L_TYPE_TID, NULL },
+ cif_dspcfg = { "DSPCFG", CMD_L_TYPE_SUBCMD, mbox_dspcfg },
+ cif_regrw = { "REGRW", CMD_L_TYPE_SUBCMD, mbox_regrw },
+ cif_getvar = { "GETVAR", CMD_L_TYPE_SUBCMD, mbox_getvar },
+ cif_setvar = { "SETVAR", CMD_L_TYPE_SUBCMD, NULL },
+ cif_err = { "ERR", CMD_L_TYPE_SUBCMD, mbox_err },
+ cif_dbg = { "DBG", CMD_L_TYPE_NULL, mbox_dbg };
+
+#define MBOX_CMD_MAX 0x80
+const struct cmdinfo *cmdinfo[MBOX_CMD_MAX] = {
+ [MBOX_CMD_DSP_WDSND] = &cif_wdsnd,
+ [MBOX_CMD_DSP_WDREQ] = &cif_wdreq,
+ [MBOX_CMD_DSP_BKSND] = &cif_bksnd,
+ [MBOX_CMD_DSP_BKREQ] = &cif_bkreq,
+ [MBOX_CMD_DSP_BKYLD] = &cif_bkyld,
+ [MBOX_CMD_DSP_BKSNDP] = &cif_bksndp,
+ [MBOX_CMD_DSP_BKREQP] = &cif_bkreqp,
+ [MBOX_CMD_DSP_TCTL] = &cif_tctl,
+ [MBOX_CMD_DSP_POLL] = &cif_poll,
+#ifdef OLD_BINARY_SUPPORT
+ [MBOX_CMD_DSP_WDT] = &cif_wdt, /* v3.3 obsolete */
+#endif
+ [MBOX_CMD_DSP_RUNLEVEL] = &cif_runlevel,
+ [MBOX_CMD_DSP_PM] = &cif_pm,
+ [MBOX_CMD_DSP_SUSPEND] = &cif_suspend,
+ [MBOX_CMD_DSP_KFUNC] = &cif_kfunc,
+ [MBOX_CMD_DSP_TCFG] = &cif_tcfg,
+ [MBOX_CMD_DSP_TADD] = &cif_tadd,
+ [MBOX_CMD_DSP_TDEL] = &cif_tdel,
+ [MBOX_CMD_DSP_TSTOP] = &cif_tstop,
+ [MBOX_CMD_DSP_DSPCFG] = &cif_dspcfg,
+ [MBOX_CMD_DSP_REGRW] = &cif_regrw,
+ [MBOX_CMD_DSP_GETVAR] = &cif_getvar,
+ [MBOX_CMD_DSP_SETVAR] = &cif_setvar,
+ [MBOX_CMD_DSP_ERR] = &cif_err,
+ [MBOX_CMD_DSP_DBG] = &cif_dbg,
+};
+
+#define list_for_each_entry_safe_natural(p,n,h,m) \
+ list_for_each_entry_safe(p,n,h,m)
+#define __BUILD_KFUNC(fn, dir) \
+static int __dsp_kfunc_##fn##_devices(struct omap_dsp *dsp, int type, int stage)\
+{ \
+ struct dsp_kfunc_device *p, *tmp; \
+ int ret, fail = 0; \
+ \
+ list_for_each_entry_safe_##dir(p, tmp, dsp->kdev_list, entry) { \
+ if (type && (p->type != type)) \
+ continue; \
+ if (p->fn == NULL) \
+ continue; \
+ ret = p->fn(p, stage); \
+ if (ret) { \
+ printk(KERN_ERR "%s %s failed\n", #fn, p->name); \
+ fail++; \
+ } \
+ } \
+ return fail; \
+}
+#define BUILD_KFUNC(fn, dir) \
+__BUILD_KFUNC(fn, dir) \
+static inline int dsp_kfunc_##fn##_devices(struct omap_dsp *dsp) \
+{ \
+ return __dsp_kfunc_##fn##_devices(dsp, 0, 0); \
+}
+#define BUILD_KFUNC_CTL(fn, dir) \
+__BUILD_KFUNC(fn, dir) \
+static inline int dsp_kfunc_##fn##_devices(struct omap_dsp *dsp, int type, int stage) \
+{ \
+ return __dsp_kfunc_##fn##_devices(dsp, type, stage); \
+}
+
+BUILD_KFUNC(probe, natural)
+BUILD_KFUNC(remove, reverse)
+BUILD_KFUNC_CTL(enable, natural)
+BUILD_KFUNC_CTL(disable, reverse)
+
+int sync_with_dsp(u16 *adr, u16 val, int try_cnt)
+{
+ int try;
+
+ if (*(volatile u16 *)adr == val)
+ return 0;
+
+ for (try = 0; try < try_cnt; try++) {
+ udelay(1);
+ if (*(volatile u16 *)adr == val) {
+ /* success! */
+ pr_info("omapdsp: sync_with_dsp(): try = %d\n", try);
+ return 0;
+ }
+ }
+
+ /* fail! */
+ return -1;
+}
+
+static int mbcmd_sender_prepare(void *data)
+{
+ struct mb_exarg *arg = data;
+ int i, ret = 0;
+ /*
+ * 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, TID_FREE, 10) < 0) {
+ printk(KERN_ERR "omapdsp: ipbuf_sys_ad is busy.\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ for (i = 0; i < arg->argc; i++) {
+ ipbuf_sys_ad->d[i] = arg->argv[i];
+ }
+ ipbuf_sys_ad->s = arg->tid;
+ out:
+ dsp_mem_disable(ipbuf_sys_ad);
+ return ret;
+}
+
+/*
+ * __dsp_mbcmd_send_exarg(): mailbox dispatcher
+ */
+int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+ int recovery_flag)
+{
+ int ret = 0;
+
+ if (unlikely(omap_dsp->enabled == 0)) {
+ ret = dsp_kfunc_enable_devices(omap_dsp,
+ DSP_KFUNC_DEV_TYPE_COMMON, 0);
+ if (ret == 0)
+ omap_dsp->enabled = 1;
+ }
+
+ /*
+ * while MMU fault is set,
+ * only recovery command can be executed
+ */
+ if (dsp_err_isset(ERRCODE_MMU) && !recovery_flag) {
+ printk(KERN_ERR
+ "mbox: mmu interrupt is set. %s is aborting.\n",
+ cmd_name(*mb));
+ goto out;
+ }
+
+ ret = omap_mbox_msg_send(omap_dsp->mbox,
+ *(mbox_msg_t *)mb, (void*)arg);
+ if (ret)
+ goto out;
+
+ if (mbseq)
+ mbseq->ad_arm++;
+
+ mblog_add(mb, DIR_A2D);
+ out:
+ return ret;
+}
+
+int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg,
+ wait_queue_head_t *q)
+{
+ int ret;
+
+ DEFINE_WAIT(wait);
+ prepare_to_wait(q, &wait, TASK_INTERRUPTIBLE);
+ ret = dsp_mbcmd_send_exarg(mb, arg);
+ if (ret < 0)
+ goto out;
+ schedule_timeout(DSP_TIMEOUT);
+ out:
+ finish_wait(q, &wait);
+ return ret;
+}
+
+/*
+ * mbcmd receiver
+ */
+static int mbcmd_receiver(void* msg)
+{
+ struct mbcmd *mb = (struct mbcmd *)&msg;
+
+ if (cmdinfo[mb->cmd_h] == NULL) {
+ printk(KERN_ERR
+ "invalid message (%08x) for mbcmd_receiver().\n",
+ (mbox_msg_t)msg);
+ return -1;
+ }
+
+ (*mbseq_expect)++;
+
+ mblog_add(mb, DIR_D2A);
+
+ /* call handler for the command */
+ if (cmdinfo[mb->cmd_h]->handler)
+ cmdinfo[mb->cmd_h]->handler(mb);
+ else
+ printk(KERN_ERR "mbox: %s is not allowed from DSP.\n",
+ cmd_name(*mb));
+ return 0;
+}
+
+static int mbsync_hold_mem_active;
+
+void dsp_mbox_start(void)
+{
+ omap_mbox_init_seq(omap_dsp->mbox);
+ mbseq_expect_tmp = 0;
+}
+
+void dsp_mbox_stop(void)
+{
+ mbseq = NULL;
+ mbseq_expect = &mbseq_expect_tmp;
+}
+
+int dsp_mbox_config(void *p)
+{
+ 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;
+}
+
+static int __init dsp_mbox_init(void)
+{
+ omap_dsp->mbox = omap_mbox_get("dsp");
+ if (IS_ERR(omap_dsp->mbox)) {
+ printk(KERN_ERR "failed to get mailbox handler for DSP.\n");
+ return -ENODEV;
+ }
+
+ omap_dsp->mbox->rxq->callback = mbcmd_receiver;
+ omap_dsp->mbox->txq->callback = mbcmd_sender_prepare;
+
+ return 0;
+}
+
+static void dsp_mbox_exit(void)
+{
+ omap_dsp->mbox->txq->callback = NULL;
+ omap_dsp->mbox->rxq->callback = NULL;
+
+ omap_mbox_put(omap_dsp->mbox);
+
+ if (mbsync_hold_mem_active) {
+ dsp_mem_disable((void *)daram_base);
+ mbsync_hold_mem_active = 0;
+ }
+}
+
+/*
+ * kernel function dispatcher
+ */
+extern void mbox_fbctl_upd(void);
+extern void mbox_fbctl_disable(struct mbcmd *mb);
+
+static void mbox_kfunc_fbctl(struct mbcmd *mb)
+{
+ switch (mb->data) {
+ case FBCTL_UPD:
+ mbox_fbctl_upd();
+ break;
+ case FBCTL_DISABLE:
+ mbox_fbctl_disable(mb);
+ break;
+ default:
+ printk(KERN_ERR
+ "mbox: Unknown FBCTL from DSP: 0x%04x\n", mb->data);
+ }
+}
+
+/*
+ * dspgw: KFUNC message handler
+ */
+static void mbox_kfunc_power(unsigned short data)
+{
+ int ret = -1;
+
+ switch (data) {
+ case DVFS_START: /* ACK from DSP */
+ /* TBD */
+ break;
+ case AUDIO_PWR_UP:
+ ret = dsp_kfunc_enable_devices(omap_dsp,
+ DSP_KFUNC_DEV_TYPE_AUDIO, 0);
+ if (ret == 0)
+ ret++;
+ break;
+ case AUDIO_PWR_DOWN: /* == AUDIO_PWR_DOWN1 */
+ ret = dsp_kfunc_disable_devices(omap_dsp,
+ DSP_KFUNC_DEV_TYPE_AUDIO, 1);
+ break;
+ case AUDIO_PWR_DOWN2:
+ ret = dsp_kfunc_disable_devices(omap_dsp,
+ DSP_KFUNC_DEV_TYPE_AUDIO, 2);
+ break;
+ case DSP_PWR_DOWN:
+ ret = dsp_kfunc_disable_devices(omap_dsp,
+ DSP_KFUNC_DEV_TYPE_COMMON, 0);
+ if (ret == 0)
+ omap_dsp->enabled = 0;
+ break;
+ default:
+ printk(KERN_ERR
+ "mailbox: Unknown PWR from DSP: 0x%04x\n", data);
+ break;
+ }
+
+ if (unlikely(ret < 0)) {
+ printk(KERN_ERR "mailbox: PWR(0x%04x) failed\n", data);
+ return;
+ }
+
+ if (likely(ret == 0))
+ return;
+
+ mbcompose_send(KFUNC, KFUNC_POWER, data);
+}
+
+static void mbox_kfunc(struct mbcmd *mb)
+{
+ switch (mb->cmd_l) {
+ case KFUNC_FBCTL:
+ mbox_kfunc_fbctl(mb);
+ break;
+ case KFUNC_POWER:
+ mbox_kfunc_power(mb->data);
+ break;
+ default:
+ printk(KERN_ERR
+ "mbox: Unknown KFUNC from DSP: 0x%02x\n", mb->cmd_l);
+ }
+}
+
+#if defined(CONFIG_ARCH_OMAP1)
+static inline void dsp_clk_enable(void) {}
+static inline void dsp_clk_disable(void) {}
+#elif defined(CONFIG_ARCH_OMAP2)
+static inline void dsp_clk_enable(void)
+{
+ u32 r;
+
+ /*XXX should be handled in mach-omap[1,2] XXX*/
+ prm_write_mod_reg(OMAP24XX_FORCESTATE | (1 << OMAP_POWERSTATE_SHIFT),
+ OMAP24XX_DSP_MOD, PM_PWSTCTRL);
+
+ r = cm_read_mod_reg(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
+ r |= OMAP2420_AUTO_DSP_IPI;
+ cm_write_mod_reg(r, OMAP24XX_DSP_MOD, CM_AUTOIDLE);
+
+ r = cm_read_mod_reg(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
+ r |= OMAP24XX_AUTOSTATE_DSP;
+ cm_write_mod_reg(r, OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
+
+ clk_enable(dsp_fck_handle);
+ clk_enable(dsp_ick_handle);
+ __dsp_per_enable();
+}
+static inline void dsp_clk_disable(void)
+{
+ __dsp_per_disable();
+ clk_disable(dsp_ick_handle);
+ clk_disable(dsp_fck_handle);
+
+ prm_write_mod_reg(OMAP24XX_FORCESTATE | (3 << OMAP_POWERSTATE_SHIFT),
+ OMAP24XX_DSP_MOD, PM_PWSTCTRL);
+}
+#endif
+
+int dsp_late_init(void)
+{
+ int ret;
+
+ dsp_clk_enable();
+ ret = dsp_mem_late_init();
+ if (ret)
+ return ret;
+ ret = dsp_mbox_init();
+ if (ret)
+ goto fail_mbox;
+#ifdef CONFIG_ARCH_OMAP1
+ dsp_set_idle_boot_base(IDLEPG_BASE, IDLEPG_SIZE);
+#endif
+ ret = dsp_kfunc_enable_devices(omap_dsp,
+ DSP_KFUNC_DEV_TYPE_COMMON, 0);
+ if (ret)
+ goto fail_kfunc;
+ omap_dsp->enabled = 1;
+
+ return 0;
+
+ fail_kfunc:
+ dsp_mbox_exit();
+ fail_mbox:
+ dsp_clk_disable();
+
+ return ret;
+}
+
+extern int dsp_ctl_core_init(void);
+extern void dsp_ctl_core_exit(void);
+extern int dsp_ctl_init(void);
+extern void dsp_ctl_exit(void);
+extern int dsp_mem_init(void);
+extern void dsp_mem_exit(void);
+extern void mblog_init(void);
+extern void mblog_exit(void);
+extern int dsp_taskmod_init(void);
+extern void dsp_taskmod_exit(void);
+
+/*
+ * driver functions
+ */
+static int __init dsp_drv_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct omap_dsp *info;
+ struct dsp_platform_data *pdata = pdev->dev.platform_data;
+
+ dev_info(&pdev->dev, "OMAP DSP driver initialization\n");
+
+ info = kzalloc(sizeof(struct omap_dsp), GFP_KERNEL);
+ if (unlikely(info == NULL)) {
+ dev_dbg(&pdev->dev, "no memory for info\n");
+ return -ENOMEM;
+ }
+ platform_set_drvdata(pdev, info);
+ omap_dsp = info;
+
+ mutex_init(&info->lock);
+ info->dev = &pdev->dev;
+ info->kdev_list = &pdata->kdev_list;
+
+ ret = dsp_kfunc_probe_devices(info);
+ if (ret) {
+ ret = -ENXIO;
+ goto fail_kfunc;
+ }
+
+ ret = dsp_ctl_core_init();
+ if (ret)
+ goto fail_ctl_core;
+ ret = dsp_mem_init();
+ if (ret)
+ goto fail_mem;
+ ret = dsp_ctl_init();
+ if (unlikely(ret))
+ goto fail_ctl_init;
+ mblog_init();
+ ret = dsp_taskmod_init();
+ if (ret)
+ goto fail_taskmod;
+
+ return 0;
+
+ fail_taskmod:
+ mblog_exit();
+ dsp_ctl_exit();
+ fail_ctl_init:
+ dsp_mem_exit();
+ fail_mem:
+ dsp_ctl_core_exit();
+ fail_ctl_core:
+ dsp_kfunc_remove_devices(info);
+ fail_kfunc:
+ kfree(info);
+
+ return ret;
+}
+
+static int dsp_drv_remove(struct platform_device *pdev)
+{
+ struct omap_dsp *info = platform_get_drvdata(pdev);
+
+ dsp_cpustat_request(CPUSTAT_RESET);
+
+ dsp_cfgstat_request(CFGSTAT_CLEAN);
+ dsp_mbox_exit();
+ dsp_taskmod_exit();
+ mblog_exit();
+ dsp_ctl_exit();
+ dsp_mem_exit();
+
+ dsp_ctl_core_exit();
+
+#ifdef CONFIG_ARCH_OMAP2
+ __dsp_per_disable();
+ clk_disable(dsp_ick_handle);
+ clk_disable(dsp_fck_handle);
+#endif
+ dsp_kfunc_remove_devices(info);
+ kfree(info);
+
+ return 0;
+}
+
+#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP1)
+static int dsp_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ dsp_cfgstat_request(CFGSTAT_SUSPEND);
+
+ return 0;
+}
+
+static int dsp_drv_resume(struct platform_device *pdev)
+{
+ dsp_cfgstat_request(CFGSTAT_RESUME);
+
+ return 0;
+}
+#else
+#define dsp_drv_suspend NULL
+#define dsp_drv_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver dsp_driver = {
+ .probe = dsp_drv_probe,
+ .remove = dsp_drv_remove,
+ .suspend = dsp_drv_suspend,
+ .resume = dsp_drv_resume,
+ .driver = {
+ .name = "dsp",
+ },
+};
+
+static int __init omap_dsp_mod_init(void)
+{
+ return platform_driver_register(&dsp_driver);
+}
+
+static void __exit omap_dsp_mod_exit(void)
+{
+ platform_driver_unregister(&dsp_driver);
+}
+
+/* module dependency: need mailbox module that have mbox_dsp_info */
+extern struct omap_mbox mbox_dsp_info;
+struct omap_mbox *mbox_dep = &mbox_dsp_info;
+
+module_init(omap_dsp_mod_init);
+module_exit(omap_dsp_mod_exit);
diff --git a/drivers/dsp/dspgateway/dsp_ctl.c b/drivers/dsp/dspgateway/dsp_ctl.c
new file mode 100644
index 0000000..79c1fdf
--- /dev/null
+++ b/drivers/dsp/dspgateway/dsp_ctl.c
@@ -0,0 +1,1069 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/ioctls.h>
+#include <asm/arch/mailbox.h>
+#include <asm/arch/dsp.h>
+#include "hardware_dsp.h"
+#include "dsp_mbcmd.h"
+#include "dsp.h"
+#include "ipbuf.h"
+
+enum dsp_space_e {
+ SPACE_MEM,
+ SPACE_IO,
+};
+
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+static enum fbstat_e {
+ FBSTAT_DISABLED = 0,
+ FBSTAT_ENABLED,
+ FBSTAT_MAX,
+} fbstat = FBSTAT_ENABLED;
+#endif
+
+static enum cfgstat_e cfgstat;
+int mbox_revision;
+static u8 n_stask;
+
+static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
+static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+
+#define __ATTR_RW(_name, _mode) { \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
+ .show = _name##_show, \
+ .store = _name##_store, \
+}
+
+static struct device_attribute dev_attr_ifver = __ATTR_RO(ifver);
+static struct device_attribute dev_attr_cpustat = __ATTR_RO(cpustat);
+static struct device_attribute dev_attr_icrmask = __ATTR_RW(icrmask, 0644);
+static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
+
+/*
+ * misc interactive mailbox command operations
+ */
+static struct misc_mb_wait_struct {
+ struct mutex lock;
+ wait_queue_head_t wait_q;
+ u8 cmd_h;
+ u8 cmd_l;
+ u16 *retvp;
+} misc_mb_wait = {
+ .lock = __MUTEX_INITIALIZER(misc_mb_wait.lock),
+ .wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(misc_mb_wait.wait_q),
+};
+
+static int __misc_mbcompose_send_and_wait(u8 cmd_h, u8 cmd_l, u16 data,
+ u16 *retvp)
+{
+ struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
+ int ret = 0;
+
+ if (mutex_lock_interruptible(&misc_mb_wait.lock))
+ return -EINTR;
+
+ misc_mb_wait.cmd_h = mb.cmd_h;
+ misc_mb_wait.cmd_l = mb.cmd_l;
+ misc_mb_wait.retvp = retvp;
+ dsp_mbcmd_send_and_wait(&mb, &misc_mb_wait.wait_q);
+
+ if (misc_mb_wait.cmd_h != 0)
+ ret = -EINVAL;
+
+ mutex_unlock(&misc_mb_wait.lock);
+ return ret;
+}
+
+#define misc_mbcompose_send_and_wait(cmd_h, cmd_l, data, retvp) \
+ __misc_mbcompose_send_and_wait(MBOX_CMD_DSP_##cmd_h, (cmd_l), \
+ (data), (retvp));
+
+static int misc_mbcmd_response(struct mbcmd *mb, int argc, int match_cmd_l_flag)
+{
+ volatile u16 *buf;
+ int i;
+
+ /* if match_cmd_l_v flag is set, cmd_l needs to be matched as well. */
+ if (!waitqueue_active(&misc_mb_wait.wait_q) ||
+ (misc_mb_wait.cmd_h != mb->cmd_h) ||
+ (match_cmd_l_flag && (misc_mb_wait.cmd_l != mb->cmd_l))) {
+ const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
+ char cmdstr[32];
+
+ if (ci->cmd_l_type == CMD_L_TYPE_SUBCMD)
+ sprintf(cmdstr, "%s:%s", ci->name, subcmd_name(mb));
+ else
+ strcpy(cmdstr, ci->name);
+ printk(KERN_WARNING
+ "mbox: unexpected command %s received!\n", cmdstr);
+ return -1;
+ }
+
+ /*
+ * if argc == 1, receive data through mbox:data register.
+ * if argc > 1, receive through ipbuf_sys.
+ */
+ if (argc == 1)
+ misc_mb_wait.retvp[0] = mb->data;
+ else if (argc > 1) {
+ if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+ printk(KERN_ERR "mbox: %s - ipbuf_sys_da read failed!\n",
+ cmdinfo[mb->cmd_h]->name);
+ return -1;
+ }
+ if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
+ printk(KERN_ERR "mbox: %s - IPBUF sync failed!\n",
+ cmdinfo[mb->cmd_h]->name);
+ dsp_mem_disable(ipbuf_sys_da);
+ return -1;
+ }
+ /* need word access. do not use memcpy. */
+ buf = ipbuf_sys_da->d;
+ for (i = 0; i < argc; i++)
+ misc_mb_wait.retvp[i] = buf[i];
+ release_ipbuf_pvt(ipbuf_sys_da);
+ dsp_mem_disable(ipbuf_sys_da);
+ }
+
+ misc_mb_wait.cmd_h = 0;
+ wake_up_interruptible(&misc_mb_wait.wait_q);
+ return 0;
+}
+
+static int dsp_regread(enum dsp_space_e space, u16 adr, u16 *val)
+{
+ u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMR : REGRW_IOR;
+ int ret;
+
+ ret = misc_mbcompose_send_and_wait(REGRW, cmd_l, adr, val);
+ if ((ret < 0) && (ret != -EINTR))
+ printk(KERN_ERR "omapdsp: register read error!\n");
+
+ return ret;
+}
+
+static int dsp_regwrite(enum dsp_space_e space, u16 adr, u16 val)
+{
+ u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMW : REGRW_IOW;
+ struct mb_exarg arg = {
+ .tid = TID_ANON,
+ .argc = 1,
+ .argv = &val,
+ };
+
+ mbcompose_send_exarg(REGRW, cmd_l, adr, &arg);
+ return 0;
+}
+
+static int dsp_getvar(u8 varid, u16 *val)
+{
+ int ret;
+
+ ret = misc_mbcompose_send_and_wait(GETVAR, varid, 0, val);
+ if ((ret < 0) && (ret != -EINTR))
+ printk(KERN_ERR "omapdsp: variable read error!\n");
+
+ return ret;
+}
+
+static int dsp_setvar(u8 varid, u16 val)
+{
+ mbcompose_send(SETVAR, varid, val);
+ return 0;
+}
+
+/*
+ * dsp_cfg() return value
+ * = 0: OK
+ * = 1: failed, but state is clear. (DSPCFG command failed)
+ * < 0: failed. need cleanup.
+ */
+static int dsp_cfg(void)
+{
+ int ret = 0;
+
+#ifdef CONFIG_ARCH_OMAP1
+ /* for safety */
+ dsp_mem_usecount_clear();
+#endif
+
+ /*
+ * DSPCFG command and dsp_mem_start() must be called
+ * while internal mem is on.
+ */
+ dsp_mem_enable((void *)dspmem_base);
+
+ dsp_mbox_start();
+ dsp_twch_start();
+ dsp_mem_start();
+ dsp_err_start();
+
+ mbox_revision = -1;
+
+ ret = misc_mbcompose_send_and_wait(DSPCFG, DSPCFG_REQ, 0, NULL);
+ if (ret < 0) {
+ if (ret != -EINTR)
+ printk(KERN_ERR "omapdsp: configuration error!\n");
+ ret = 1;
+ goto out;
+ }
+
+#if defined(CONFIG_ARCH_OMAP1) && defined(OLD_BINARY_SUPPORT)
+ /*
+ * MBREV 3.2 or earlier doesn't assume DMA domain is on
+ * when DSPCFG command is sent
+ */
+ if ((mbox_revision == MBREV_3_0) ||
+ (mbox_revision == MBREV_3_2)) {
+ if ((ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA)) < 0)
+ goto out;
+ }
+#endif
+
+ if ((ret = dsp_task_config_all(n_stask)) < 0)
+ goto out;
+
+ /* initialization */
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+ fbstat = FBSTAT_ENABLED;
+#endif
+
+ /* send parameter */
+ ret = dsp_setvar(VARID_ICRMASK, dsp_cpustat_get_icrmask());
+ if (ret < 0)
+ goto out;
+
+ /* create runtime sysfs entries */
+ ret = device_create_file(omap_dsp->dev, &dev_attr_loadinfo);
+ if (ret)
+ printk(KERN_ERR "device_create_file failed: %d\n", ret);
+ out:
+ dsp_mem_disable((void *)dspmem_base);
+ return ret;
+}
+
+static int dsp_uncfg(void)
+{
+ if (dsp_taskmod_busy()) {
+ printk(KERN_WARNING "omapdsp: tasks are busy.\n");
+ return -EBUSY;
+ }
+
+ /* FIXME: lock task module */
+
+ /* remove runtime sysfs entries */
+ device_remove_file(omap_dsp->dev, &dev_attr_loadinfo);
+
+ dsp_mbox_stop();
+ dsp_twch_stop();
+ dsp_mem_stop();
+ dsp_err_stop();
+ dsp_dbg_stop();
+ dsp_task_unconfig_all();
+ ipbuf_stop();
+
+ return 0;
+}
+
+static int dsp_suspend(void)
+{
+ int ret;
+
+ ret = misc_mbcompose_send_and_wait(SUSPEND, 0, 0, NULL);
+ if (ret < 0) {
+ if (ret != -EINVAL)
+ printk(KERN_ERR "omapdsp: DSP suspend error!\n");
+ return ret;
+ }
+
+ udelay(100); /* wait for DSP-side execution */
+ return 0;
+}
+
+int dsp_cfgstat_request(enum cfgstat_e st_req)
+{
+ static DEFINE_MUTEX(cfgstat_lock);
+ int ret = 0, ret_override = 0;
+
+ if (mutex_lock_interruptible(&cfgstat_lock))
+ return -EINTR;
+
+again:
+ switch (st_req) {
+
+ /* cfgstat takes CLEAN, READY or SUSPEND,
+ while st_req can take SUSPEND in addition. */
+
+ case CFGSTAT_CLEAN:
+ if (cfgstat == CFGSTAT_CLEAN)
+ goto up_out;
+ if ((ret = dsp_uncfg()) < 0)
+ goto up_out;
+ break;
+
+ case CFGSTAT_READY:
+ if (cfgstat != CFGSTAT_CLEAN) {
+ printk(KERN_ERR "omapdsp: DSP is ready already!\n");
+ ret = -EINVAL;
+ goto up_out;
+ }
+
+ ret = dsp_cfg();
+ if (ret > 0) { /* failed, but state is clear. */
+ ret = -EINVAL;
+ goto up_out;
+ } else if (ret < 0) { /* failed, need cleanup. */
+ st_req = CFGSTAT_CLEAN;
+ ret_override = ret;
+ goto again;
+ }
+ break;
+
+ /*
+ * suspend / resume
+ * DSP is not reset within this code, but done in omap_pm_suspend.
+ * so if these functions are called from sysfs,
+ * DSP should be reset / unreset out of these functions.
+ */
+ case CFGSTAT_SUSPEND:
+ switch (cfgstat) {
+
+ case CFGSTAT_CLEAN:
+ if (dsp_cpustat_get_stat() == CPUSTAT_RUN) {
+ printk(KERN_WARNING
+ "omapdsp: illegal operation -- trying "
+ "suspend DSP while it is running but "
+ "not configured.\n"
+ " Resetting DSP.\n");
+ dsp_cpustat_request(CPUSTAT_RESET);
+ ret = -EINVAL;
+ }
+ goto up_out;
+
+ case CFGSTAT_READY:
+ if ((ret = dsp_suspend()) < 0)
+ goto up_out;
+ break;
+
+ case CFGSTAT_SUSPEND:
+ goto up_out;
+
+ default:
+ BUG();
+
+ }
+
+ break;
+
+ case CFGSTAT_RESUME:
+ if (cfgstat != CFGSTAT_SUSPEND) {
+ printk(KERN_WARNING
+ "omapdsp: DSP resume request, but DSP is not in "
+ "suspend state.\n");
+ ret = -EINVAL;
+ goto up_out;
+ }
+ st_req = CFGSTAT_READY;
+ break;
+
+ default:
+ BUG();
+
+ }
+
+ cfgstat = st_req;
+up_out:
+ mutex_unlock(&cfgstat_lock);
+ return ret_override ? ret_override : ret;
+}
+
+enum cfgstat_e dsp_cfgstat_get_stat(void)
+{
+ return cfgstat;
+}
+
+/*
+ * polls all tasks
+ */
+static int dsp_poll(void)
+{
+ int ret;
+
+ ret = misc_mbcompose_send_and_wait(POLL, 0, 0, NULL);
+ if ((ret < 0) && (ret != -EINTR))
+ printk(KERN_ERR "omapdsp: poll error!\n");
+
+ return ret;
+}
+
+int dsp_set_runlevel(u8 level)
+{
+ if (level == RUNLEVEL_RECOVERY) {
+ if (mbcompose_send_recovery(RUNLEVEL, level, 0) < 0)
+ return -EINVAL;
+ } else {
+ if ((level < RUNLEVEL_USER) ||
+ (level > RUNLEVEL_SUPER))
+ return -EINVAL;
+ if (mbcompose_send(RUNLEVEL, level, 0) < 0)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+static void dsp_fbctl_enable(void)
+{
+ mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_ENABLE);
+}
+
+static int dsp_fbctl_disable(void)
+{
+ int ret;
+
+ ret = misc_mbcompose_send_and_wait(KFUNC, KFUNC_FBCTL, FBCTL_DISABLE,
+ NULL);
+ if ((ret < 0) && (ret != -EINTR))
+ printk(KERN_ERR "omapdsp: fb disable error!\n");
+
+ return 0;
+}
+
+static int dsp_fbstat_request(enum fbstat_e st)
+{
+ static DEFINE_MUTEX(fbstat_lock);
+ int ret = 0;
+
+ if (mutex_lock_interruptible(&fbstat_lock))
+ return -EINTR;
+
+ if (st == fbstat)
+ goto up_out;
+
+ switch (st) {
+ case FBSTAT_ENABLED:
+ dsp_fbctl_enable();
+ break;
+ case FBSTAT_DISABLED:
+ if ((ret = dsp_fbctl_disable()) < 0)
+ goto up_out;
+ break;
+ default:
+ BUG();
+ }
+
+ fbstat = st;
+up_out:
+ mutex_unlock(&fbstat_lock);
+ return 0;
+}
+#endif /* CONFIG_OMAP_DSP_FBEXPORT */
+
+/*
+ * DSP control device file operations
+ */
+static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ /*
+ * command level 1: commands which don't need lock
+ */
+ case DSPCTL_IOCTL_RUN:
+ dsp_cpustat_request(CPUSTAT_RUN);
+ break;
+
+ case DSPCTL_IOCTL_RESET:
+ dsp_cpustat_request(CPUSTAT_RESET);
+ break;
+
+ case DSPCTL_IOCTL_SETRSTVECT:
+ ret = dsp_set_rstvect((dsp_long_t)arg);
+ break;
+
+#ifdef CONFIG_ARCH_OMAP1
+ case DSPCTL_IOCTL_CPU_IDLE:
+ dsp_cpustat_request(CPUSTAT_CPU_IDLE);
+ break;
+
+ case DSPCTL_IOCTL_GBL_IDLE:
+ dsp_cpustat_request(CPUSTAT_GBL_IDLE);
+ break;
+
+ case DSPCTL_IOCTL_MPUI_WORDSWAP_ON:
+ mpui_wordswap_on();
+ break;
+
+ case DSPCTL_IOCTL_MPUI_WORDSWAP_OFF:
+ mpui_wordswap_off();
+ break;
+
+ case DSPCTL_IOCTL_MPUI_BYTESWAP_ON:
+ mpui_byteswap_on();
+ break;
+
+ case DSPCTL_IOCTL_MPUI_BYTESWAP_OFF:
+ mpui_byteswap_off();
+ break;
+#endif /* CONFIG_ARCH_OMAP1 */
+
+ case DSPCTL_IOCTL_TASKCNT:
+ ret = dsp_task_count();
+ break;
+
+ case DSPCTL_IOCTL_MBSEND:
+ {
+ struct omap_dsp_mailbox_cmd u_cmd;
+ mbox_msg_t msg;
+ if (copy_from_user(&u_cmd, (void *)arg, sizeof(u_cmd)))
+ return -EFAULT;
+ msg = (u_cmd.cmd << 16) | u_cmd.data;
+ ret = dsp_mbcmd_send((struct mbcmd *)&msg);
+ break;
+ }
+
+ case DSPCTL_IOCTL_SETVAR:
+ {
+ struct omap_dsp_varinfo var;
+ if (copy_from_user(&var, (void *)arg, sizeof(var)))
+ return -EFAULT;
+ ret = dsp_setvar(var.varid, var.val[0]);
+ break;
+ }
+
+ case DSPCTL_IOCTL_RUNLEVEL:
+ ret = dsp_set_runlevel(arg);
+ break;
+
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+ case DSPCTL_IOCTL_FBEN:
+ ret = dsp_fbstat_request(FBSTAT_ENABLED);
+ break;
+#endif
+
+ /*
+ * command level 2: commands which need lock
+ */
+ case DSPCTL_IOCTL_DSPCFG:
+ ret = dsp_cfgstat_request(CFGSTAT_READY);
+ break;
+
+ case DSPCTL_IOCTL_DSPUNCFG:
+ ret = dsp_cfgstat_request(CFGSTAT_CLEAN);
+ break;
+
+ case DSPCTL_IOCTL_POLL:
+ ret = dsp_poll();
+ break;
+
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+ case DSPCTL_IOCTL_FBDIS:
+ ret = dsp_fbstat_request(FBSTAT_DISABLED);
+ break;
+#endif
+
+ case DSPCTL_IOCTL_SUSPEND:
+ if ((ret = dsp_cfgstat_request(CFGSTAT_SUSPEND)) < 0)
+ break;
+ dsp_cpustat_request(CPUSTAT_RESET);
+ break;
+
+ case DSPCTL_IOCTL_RESUME:
+ if ((ret = dsp_cfgstat_request(CFGSTAT_RESUME)) < 0)
+ break;
+ dsp_cpustat_request(CPUSTAT_RUN);
+ break;
+
+ case DSPCTL_IOCTL_REGMEMR:
+ {
+ struct omap_dsp_reginfo *u_reg = (void *)arg;
+ u16 adr, val;
+
+ if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
+ return -EFAULT;
+ if ((ret = dsp_regread(SPACE_MEM, adr, &val)) < 0)
+ return ret;
+ if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
+ return -EFAULT;
+ break;
+ }
+
+ case DSPCTL_IOCTL_REGMEMW:
+ {
+ struct omap_dsp_reginfo reg;
+
+ if (copy_from_user(®, (void *)arg, sizeof(reg)))
+ return -EFAULT;
+ ret = dsp_regwrite(SPACE_MEM, reg.adr, reg.val);
+ break;
+ }
+
+ case DSPCTL_IOCTL_REGIOR:
+ {
+ struct omap_dsp_reginfo *u_reg = (void *)arg;
+ u16 adr, val;
+
+ if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
+ return -EFAULT;
+ if ((ret = dsp_regread(SPACE_IO, adr, &val)) < 0)
+ return ret;
+ if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
+ return -EFAULT;
+ break;
+ }
+
+ case DSPCTL_IOCTL_REGIOW:
+ {
+ struct omap_dsp_reginfo reg;
+
+ if (copy_from_user(®, (void *)arg, sizeof(reg)))
+ return -EFAULT;
+ ret = dsp_regwrite(SPACE_IO, reg.adr, reg.val);
+ break;
+ }
+
+ case DSPCTL_IOCTL_GETVAR:
+ {
+ struct omap_dsp_varinfo *u_var = (void *)arg;
+ u8 varid;
+ u16 val[5]; /* maximum */
+ int argc;
+
+ if (copy_from_user(&varid, &u_var->varid, sizeof(u8)))
+ return -EFAULT;
+ switch (varid) {
+ case VARID_ICRMASK:
+ argc = 1;
+ break;
+ case VARID_LOADINFO:
+ argc = 5;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if ((ret = dsp_getvar(varid, val)) < 0)
+ return ret;
+ if (copy_to_user(&u_var->val, val, sizeof(u16) * argc))
+ return -EFAULT;
+ break;
+ }
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return ret;
+}
+
+/*
+ * functions called from mailbox interrupt routine
+ */
+void mbox_suspend(struct mbcmd *mb)
+{
+ misc_mbcmd_response(mb, 0, 0);
+}
+
+void mbox_dspcfg(struct mbcmd *mb)
+{
+ u8 last = mb->cmd_l & 0x80;
+ u8 cfgcmd = mb->cmd_l & 0x7f;
+ static dsp_long_t tmp_ipb_adr;
+
+ if (!waitqueue_active(&misc_mb_wait.wait_q) ||
+ (misc_mb_wait.cmd_h != MBOX_CMD_DSP_DSPCFG)) {
+ printk(KERN_WARNING
+ "mbox: DSPCFG command received, "
+ "but nobody is waiting for it...\n");
+ return;
+ }
+
+ /* mailbox protocol check */
+ if (cfgcmd == DSPCFG_PROTREV) {
+ mbox_revision = mb->data;
+ if (mbox_revision == MBPROT_REVISION)
+ return;
+#ifdef OLD_BINARY_SUPPORT
+ else if ((mbox_revision == MBREV_3_0) ||
+ (mbox_revision == MBREV_3_2)) {
+ printk(KERN_WARNING
+ "mbox: ***** old DSP binary *****\n"
+ " Please update your DSP application.\n");
+ return;
+ }
+#endif
+ else {
+ printk(KERN_ERR
+ "mbox: protocol revision check error!\n"
+ " expected=0x%04x, received=0x%04x\n",
+ MBPROT_REVISION, mb->data);
+ mbox_revision = -1;
+ goto abort1;
+ }
+ }
+
+ /*
+ * following commands are accepted only after
+ * revision check has been passed.
+ */
+ if (!mbox_revision < 0) {
+ pr_info("mbox: DSPCFG command received, "
+ "but revision check has not been passed.\n");
+ return;
+ }
+
+ switch (cfgcmd) {
+ case DSPCFG_SYSADRH:
+ tmp_ipb_adr = (u32)mb->data << 16;
+ break;
+
+ case DSPCFG_SYSADRL:
+ tmp_ipb_adr |= mb->data;
+ break;
+
+ case DSPCFG_ABORT:
+ goto abort1;
+
+ default:
+ printk(KERN_ERR
+ "mbox: Unknown CFG command: cmd_l=0x%02x, data=0x%04x\n",
+ mb->cmd_l, mb->data);
+ return;
+ }
+
+ if (last) {
+ void *badr;
+ u16 bln;
+ u16 bsz;
+ volatile u16 *buf;
+ void *ipb_sys_da, *ipb_sys_ad;
+ void *mbseq; /* FIXME: 3.4 obsolete */
+ short *dbg_buf;
+ u16 dbg_buf_sz, dbg_line_sz;
+ struct mem_sync_struct mem_sync, *mem_syncp;
+
+ ipb_sys_da = dspword_to_virt(tmp_ipb_adr);
+ if (ipbuf_sys_config(ipb_sys_da, DIR_D2A) < 0)
+ goto abort1;
+
+ if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+ printk(KERN_ERR "mbox: DSPCFG - ipbuf_sys_da read failed!\n");
+ goto abort1;
+ }
+ if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
+ printk(KERN_ERR "mbox: DSPCFG - IPBUF sync failed!\n");
+ dsp_mem_disable(ipbuf_sys_da);
+ goto abort1;
+ }
+ /*
+ * read configuration data on system IPBUF
+ * we must read with 16bit-access
+ */
+#ifdef OLD_BINARY_SUPPORT
+ if (mbox_revision == MBPROT_REVISION) {
+#endif
+ 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 = 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 (mbox_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 (mbox_revision == MBREV_3_0) {
+ buf = ipbuf_sys_da->d;
+ 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 */
+ dsp_mem_disable(ipbuf_sys_da);
+ goto abort1;
+ }
+#endif /* OLD_BINARY_SUPPORT */
+
+ release_ipbuf_pvt(ipbuf_sys_da);
+ dsp_mem_disable(ipbuf_sys_da);
+
+ /*
+ * following configurations need to be done before
+ * 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_mbox_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;
+
+ misc_mb_wait.cmd_h = 0;
+ wake_up_interruptible(&misc_mb_wait.wait_q);
+ }
+ return;
+
+abort2:
+ ipbuf_stop();
+abort1:
+ wake_up_interruptible(&misc_mb_wait.wait_q);
+ return;
+}
+
+void mbox_poll(struct mbcmd *mb)
+{
+ misc_mbcmd_response(mb, 0, 0);
+}
+
+void mbox_regrw(struct mbcmd *mb)
+{
+ switch (mb->cmd_l) {
+ case REGRW_DATA:
+ misc_mbcmd_response(mb, 1, 0);
+ break;
+ default:
+ printk(KERN_ERR
+ "mbox: Illegal REGRW command: "
+ "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
+ return;
+ }
+}
+
+void mbox_getvar(struct mbcmd *mb)
+{
+ switch (mb->cmd_l) {
+ case VARID_ICRMASK:
+ misc_mbcmd_response(mb, 1, 1);
+ break;
+ case VARID_LOADINFO:
+ misc_mbcmd_response(mb, 5, 1);
+ break;
+ default:
+ printk(KERN_ERR
+ "mbox: Illegal GETVAR command: "
+ "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
+ return;
+ }
+}
+
+void mbox_fbctl_disable(struct mbcmd *mb)
+{
+ misc_mbcmd_response(mb, 0, 0);
+}
+
+struct file_operations dsp_ctl_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = dsp_ctl_ioctl,
+};
+
+/*
+ * sysfs files
+ */
+
+/* ifver */
+static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int len = 0;
+
+ /*
+ * I/F VERSION descriptions:
+ *
+ * 3.2: sysfs / udev support
+ * KMEM_RESERVE / KMEM_RELEASE ioctls for mem device
+ * 3.3: added following ioctls
+ * DSPCTL_IOCTL_GBL_IDLE
+ * DSPCTL_IOCTL_CPU_IDLE (instead of DSPCTL_IOCTL_IDLE)
+ * DSPCTL_IOCTL_POLL
+ */
+
+ /*
+ * print all supporting I/F VERSIONs, like followings.
+ *
+ * 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;
+}
+
+/* cpustat */
+static char *cpustat_name[CPUSTAT_MAX] = {
+ [CPUSTAT_RESET] = "reset",
+#ifdef CONFIG_ARCH_OMAP1
+ [CPUSTAT_GBL_IDLE] = "gbl_idle",
+ [CPUSTAT_CPU_IDLE] = "cpu_idle",
+#endif
+ [CPUSTAT_RUN] = "run",
+};
+
+static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", cpustat_name[dsp_cpustat_get_stat()]);
+}
+
+/* icrmask */
+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)
+{
+ u16 mask;
+ int ret;
+
+ mask = simple_strtol(buf, NULL, 16);
+ dsp_cpustat_set_icrmask(mask);
+
+ if (dsp_cfgstat_get_stat() == CFGSTAT_READY) {
+ ret = dsp_setvar(VARID_ICRMASK, mask);
+ if (ret < 0)
+ return ret;
+ }
+
+ return count;
+}
+
+/* loadinfo */
+static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int len;
+ int ret;
+ u16 val[5];
+
+ if ((ret = dsp_getvar(VARID_LOADINFO, val)) < 0)
+ return ret;
+
+ /*
+ * load info value range is 0(free) - 10000(busy):
+ * if CPU load is not measured on DSP, it sets 0xffff at val[0].
+ */
+
+ if (val[0] == 0xffff) {
+ len = sprintf(buf,
+ "currently DSP load info is not available.\n");
+ goto out;
+ }
+
+ len = sprintf(buf,
+ "DSP load info:\n"
+ " 10ms average = %3d.%02d%%\n"
+ " 1sec average = %3d.%02d%% busiest 10ms = %3d.%02d%%\n"
+ " 1min average = %3d.%02d%% busiest 1s = %3d.%02d%%\n",
+ val[0]/100, val[0]%100,
+ val[1]/100, val[1]%100, val[2]/100, val[2]%100,
+ val[3]/100, val[3]%100, val[4]/100, val[4]%100);
+out:
+ return len;
+}
+
+int __init dsp_ctl_init(void)
+{
+ int ret;
+
+ ret = device_create_file(omap_dsp->dev, &dev_attr_ifver);
+ if (unlikely(ret))
+ return ret;
+ ret = device_create_file(omap_dsp->dev, &dev_attr_cpustat);
+ if (unlikely(ret))
+ goto fail_create_cpustat;
+ ret = device_create_file(omap_dsp->dev, &dev_attr_icrmask);
+ if (unlikely(ret))
+ goto fail_create_icrmask;
+
+ return 0;
+
+fail_create_icrmask:
+ device_remove_file(omap_dsp->dev, &dev_attr_cpustat);
+fail_create_cpustat:
+ device_remove_file(omap_dsp->dev, &dev_attr_ifver);
+
+ return ret;
+}
+
+void dsp_ctl_exit(void)
+{
+ device_remove_file(omap_dsp->dev, &dev_attr_ifver);
+ device_remove_file(omap_dsp->dev, &dev_attr_cpustat);
+ device_remove_file(omap_dsp->dev, &dev_attr_icrmask);
+}
diff --git a/drivers/dsp/dspgateway/dsp_ctl_core.c b/drivers/dsp/dspgateway/dsp_ctl_core.c
new file mode 100644
index 0000000..956ef26
--- /dev/null
+++ b/drivers/dsp/dspgateway/dsp_ctl_core.c
@@ -0,0 +1,132 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include "dsp.h"
+
+#define CTL_MINOR 0
+#define MEM_MINOR 1
+#define TWCH_MINOR 2
+#define ERR_MINOR 3
+
+static struct class *dsp_ctl_class;
+extern struct file_operations dsp_ctl_fops,
+ dsp_mem_fops,
+ dsp_twch_fops,
+ dsp_err_fops;
+
+static int dsp_ctl_core_open(struct inode *inode, struct file *file)
+{
+ static DEFINE_MUTEX(open_lock);
+ int ret = 0;
+
+ if (mutex_lock_interruptible(&open_lock))
+ return -EINTR;
+ if (omap_dsp->initialized == 0) {
+ ret = dsp_late_init();
+ if (ret != 0) {
+ mutex_unlock(&open_lock);
+ return ret;
+ }
+ omap_dsp->initialized = 1;
+ }
+ mutex_unlock(&open_lock);
+
+ switch (iminor(inode)) {
+ case CTL_MINOR:
+ file->f_op = &dsp_ctl_fops;
+ break;
+ case MEM_MINOR:
+ file->f_op = &dsp_mem_fops;
+ break;
+ case TWCH_MINOR:
+ file->f_op = &dsp_twch_fops;
+ break;
+ case ERR_MINOR:
+ file->f_op = &dsp_err_fops;
+ break;
+ default:
+ return -ENXIO;
+ }
+ if (file->f_op && file->f_op->open)
+ return file->f_op->open(inode, file);
+ return 0;
+}
+
+static struct file_operations dsp_ctl_core_fops = {
+ .owner = THIS_MODULE,
+ .open = dsp_ctl_core_open,
+};
+
+static const struct dev_list {
+ unsigned int minor;
+ char *devname;
+ umode_t mode;
+} dev_list[] = {
+ {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)
+{
+ int retval;
+ int i;
+
+ retval = register_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl",
+ &dsp_ctl_core_fops);
+ if (retval < 0) {
+ printk(KERN_ERR
+ "omapdsp: failed to register dspctl device: %d\n",
+ retval);
+ return retval;
+ }
+
+ dsp_ctl_class = class_create(THIS_MODULE, "dspctl");
+ for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
+ device_create(dsp_ctl_class, NULL,
+ MKDEV(OMAP_DSP_CTL_MAJOR,
+ dev_list[i].minor),
+ dev_list[i].devname);
+ }
+
+ return 0;
+}
+
+void dsp_ctl_core_exit(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
+ device_destroy(dsp_ctl_class,
+ MKDEV(OMAP_DSP_CTL_MAJOR,
+ dev_list[i].minor));
+ }
+ class_destroy(dsp_ctl_class);
+
+ unregister_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl");
+}
diff --git a/drivers/dsp/dspgateway/dsp_mbcmd.h b/drivers/dsp/dspgateway/dsp_mbcmd.h
new file mode 100644
index 0000000..fb35749
--- /dev/null
+++ b/drivers/dsp/dspgateway/dsp_mbcmd.h
@@ -0,0 +1,147 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __PLAT_OMAP_DSP_MBCMD_H
+#define __PLAT_OMAP_DSP_MBCMD_H
+/*
+ * mailbox command: 0x00 - 0x7f
+ * when a driver wants to use mailbox, it must reserve mailbox commands here.
+ */
+#define MBOX_CMD_DSP_WDSND 0x10
+#define MBOX_CMD_DSP_WDREQ 0x11
+#define MBOX_CMD_DSP_BKSND 0x20
+#define MBOX_CMD_DSP_BKREQ 0x21
+#define MBOX_CMD_DSP_BKYLD 0x23
+#define MBOX_CMD_DSP_BKSNDP 0x24
+#define MBOX_CMD_DSP_BKREQP 0x25
+#define MBOX_CMD_DSP_TCTL 0x30
+#define MBOX_CMD_DSP_TCTLDATA 0x31
+#define MBOX_CMD_DSP_POLL 0x32
+#define MBOX_CMD_DSP_WDT 0x50
+#define MBOX_CMD_DSP_RUNLEVEL 0x51
+#define MBOX_CMD_DSP_PM 0x52
+#define MBOX_CMD_DSP_SUSPEND 0x53
+#define MBOX_CMD_DSP_KFUNC 0x54
+#define MBOX_CMD_DSP_TCFG 0x60
+#define MBOX_CMD_DSP_TADD 0x62
+#define MBOX_CMD_DSP_TDEL 0x63
+#define MBOX_CMD_DSP_TSTOP 0x65
+#define MBOX_CMD_DSP_DSPCFG 0x70
+#define MBOX_CMD_DSP_REGRW 0x72
+#define MBOX_CMD_DSP_GETVAR 0x74
+#define MBOX_CMD_DSP_SETVAR 0x75
+#define MBOX_CMD_DSP_ERR 0x78
+#define MBOX_CMD_DSP_DBG 0x79
+
+/*
+ * DSP mailbox protocol definitions
+ */
+#define MBPROT_REVISION 0x0019
+
+#define TCTL_TINIT 0x0000
+#define TCTL_TEN 0x0001
+#define TCTL_TDIS 0x0002
+#define TCTL_TCLR 0x0003
+#define TCTL_TCLR_FORCE 0x0004
+
+#define RUNLEVEL_USER 0x01
+#define RUNLEVEL_SUPER 0x0e
+#define RUNLEVEL_RECOVERY 0x10
+
+#define PM_DISABLE 0x00
+#define PM_ENABLE 0x01
+
+#define KFUNC_FBCTL 0x00
+#define KFUNC_POWER 0x01
+
+#define FBCTL_UPD 0x0000
+#define FBCTL_ENABLE 0x0002
+#define FBCTL_DISABLE 0x0003
+
+/* KFUNC_POWER */
+#define AUDIO_PWR_UP 0x0000 /* ARM(exe/ack) <-> DSP(req) */
+#define AUDIO_PWR_DOWN 0x0001 /* ARM(exe) <- DSP(req) */
+#define AUDIO_PWR_DOWN1 AUDIO_PWR_DOWN
+#define AUDIO_PWR_DOWN2 0x0002
+#define DSP_PWR_UP 0x0003 /* ARM(exe/snd) -> DSP(exe) */
+#define DSP_PWR_DOWN 0x0004 /* ARM(exe) <- DSP(req) */
+#define DVFS_START 0x0006 /* ARM(req) <-> DSP(exe/ack)*/
+#define DVFS_STOP 0x0007 /* ARM(req) -> DSP(exe) */
+
+#define TDEL_SAFE 0x0000
+#define TDEL_KILL 0x0001
+
+#define DSPCFG_REQ 0x00
+#define DSPCFG_SYSADRH 0x28
+#define DSPCFG_SYSADRL 0x29
+#define DSPCFG_PROTREV 0x70
+#define DSPCFG_ABORT 0x78
+#define DSPCFG_LAST 0x80
+
+#define REGRW_MEMR 0x00
+#define REGRW_MEMW 0x01
+#define REGRW_IOR 0x02
+#define REGRW_IOW 0x03
+#define REGRW_DATA 0x04
+
+#define VARID_ICRMASK 0x00
+#define VARID_LOADINFO 0x01
+
+#define TTYP_ARCV 0x0001
+#define TTYP_ASND 0x0002
+#define TTYP_BKMD 0x0004
+#define TTYP_BKDM 0x0008
+#define TTYP_PVMD 0x0010
+#define TTYP_PVDM 0x0020
+
+#define EID_BADTID 0x10
+#define EID_BADTCN 0x11
+#define EID_BADBID 0x20
+#define EID_BADCNT 0x21
+#define EID_NOTLOCKED 0x22
+#define EID_STVBUF 0x23
+#define EID_BADADR 0x24
+#define EID_BADTCTL 0x30
+#define EID_BADPARAM 0x50
+#define EID_FATAL 0x58
+#define EID_NOMEM 0xc0
+#define EID_NORES 0xc1
+#define EID_IPBFULL 0xc2
+#define EID_WDT 0xd0
+#define EID_TASKNOTRDY 0xe0
+#define EID_TASKBSY 0xe1
+#define EID_TASKERR 0xef
+#define EID_BADCFGTYP 0xf0
+#define EID_DEBUG 0xf8
+#define EID_BADSEQ 0xfe
+#define EID_BADCMD 0xff
+
+#define TNM_LEN 16
+
+#define TID_FREE 0xff
+#define TID_ANON 0xfe
+
+#define BID_NULL 0xffff
+#define BID_PVT 0xfffe
+
+#endif /* __PLAT_OMAP_DSP_MBCMD_H */
diff --git a/drivers/dsp/dspgateway/dsp_mem.c b/drivers/dsp/dspgateway/dsp_mem.c
new file mode 100644
index 0000000..6d3148f
--- /dev/null
+++ b/drivers/dsp/dspgateway/dsp_mem.c
@@ -0,0 +1,484 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * Conversion to mempool API and ARM MMU section mapping
+ * by Paul Mundt <paul.mundt@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mempool.h>
+#include <linux/clk.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/omapfb.h>
+#include <asm/arch/dsp.h>
+#include <asm/arch/mailbox.h>
+#include <asm/arch/mmu.h>
+#include "dsp_mbcmd.h"
+#include "dsp.h"
+#include "ipbuf.h"
+
+#if 0
+#if defined(CONFIG_ARCH_OMAP1)
+#include "../../mach-omap1/mmu.h"
+#elif defined(CONFIG_ARCH_OMAP2)
+#include "../../mach-omap2/mmu.h"
+#endif
+#endif
+
+#include "mmu.h"
+
+static struct mem_sync_struct mem_sync;
+
+int dsp_mem_sync_inc(void)
+{
+ if (dsp_mem_enable((void *)dspmem_base) < 0)
+ return -1;
+ 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_disable((void *)dspmem_base);
+
+ return 0;
+}
+
+/*
+ * dsp_mem_sync_config() is called from mbox1 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;
+}
+
+
+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(&dsp_mmu.exmap_sem);
+ if (exmap_valid(&dsp_mmu, vadr, len))
+ ret = MEM_TYPE_EXTERN;
+ else
+ ret = MEM_TYPE_NONE;
+ up_read(&dsp_mmu.exmap_sem);
+ return ret;
+ }
+}
+
+int dsp_address_validate(void *p, size_t len, char *fmt, ...)
+{
+ char s[64];
+ va_list args;
+
+ if (dsp_mem_type(p, len) > 0)
+ return 0;
+
+ if (fmt == NULL)
+ goto out;
+
+ 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 external memory\n"
+ "space where no actual memory is mapped)\n", s, p, len);
+ out:
+ return -1;
+}
+
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+
+static inline unsigned long lineup_offset(unsigned long adr,
+ unsigned long ref,
+ unsigned long mask)
+{
+ unsigned long newadr;
+
+ newadr = (adr & ~mask) | (ref & mask);
+ if (newadr < adr)
+ newadr += mask + 1;
+ return newadr;
+}
+
+/*
+ * fb update functions:
+ * fbupd_response() is executed by the workqueue.
+ * fbupd_cb() is called when fb update is done, in interrupt context.
+ * mbox_fbupd() is called when KFUNC:FBCTL:UPD is received from DSP.
+ */
+static void fbupd_response(struct work_struct *unused)
+{
+ int status;
+
+ status = mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_UPD);
+ if (status == 0)
+ return;
+
+ /* FIXME: DSP is busy !! */
+ printk(KERN_ERR
+ "omapdsp:"
+ "DSP is busy when trying to send FBCTL:UPD response!\n");
+}
+
+static DECLARE_WORK(fbupd_response_work, fbupd_response);
+
+static void fbupd_cb(void *arg)
+{
+ schedule_work(&fbupd_response_work);
+}
+
+void mbox_fbctl_upd(void)
+{
+ struct omapfb_update_window win;
+ volatile unsigned short *buf = ipbuf_sys_da->d;
+
+ if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 5000) < 0) {
+ printk(KERN_ERR "mbox: FBCTL:UPD - IPBUF sync failed!\n");
+ return;
+ }
+ win.x = buf[0];
+ win.y = buf[1];
+ win.width = buf[2];
+ win.height = buf[3];
+ win.format = buf[4];
+ release_ipbuf_pvt(ipbuf_sys_da);
+
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+ if (!omapfb_ready) {
+ printk(KERN_WARNING
+ "omapdsp: fbupd() called while HWA742 is not ready!\n");
+ return;
+ }
+#endif
+ omapfb_update_window_async(registered_fb[0], &win, fbupd_cb, NULL);
+}
+
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+static int omapfb_notifier_cb(struct notifier_block *omapfb_nb,
+ unsigned long event, void *fbi)
+{
+ pr_info("omapfb_notifier_cb(): event = %s\n",
+ (event == OMAPFB_EVENT_READY) ? "READY" :
+ (event == OMAPFB_EVENT_DISABLED) ? "DISABLED" : "Unknown");
+ if (event == OMAPFB_EVENT_READY)
+ omapfb_ready = 1;
+ else if (event == OMAPFB_EVENT_DISABLED)
+ omapfb_ready = 0;
+ return 0;
+}
+#endif
+
+static int dsp_fbexport(dsp_long_t *dspadr)
+{
+ dsp_long_t dspadr_actual;
+ unsigned long padr_sys, padr, fbsz_sys, fbsz;
+ int cnt;
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+ int status;
+#endif
+
+ pr_debug( "omapdsp: frame buffer export\n");
+
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+ if (omapfb_nb) {
+ printk(KERN_WARNING
+ "omapdsp: frame buffer has been exported already!\n");
+ return -EBUSY;
+ }
+#endif
+
+ if (num_registered_fb == 0) {
+ pr_info("omapdsp: frame buffer not registered.\n");
+ return -EINVAL;
+ }
+ if (num_registered_fb != 1) {
+ pr_info("omapdsp: %d frame buffers found. we use first one.\n",
+ num_registered_fb);
+ }
+ padr_sys = registered_fb[0]->fix.smem_start;
+ fbsz_sys = registered_fb[0]->fix.smem_len;
+ if (fbsz_sys == 0) {
+ printk(KERN_ERR
+ "omapdsp: framebuffer doesn't seem to be configured "
+ "correctly! (size=0)\n");
+ return -EINVAL;
+ }
+
+ /*
+ * align padr and fbsz to 4kB boundary
+ * (should be noted to the user afterwards!)
+ */
+ padr = padr_sys & ~(SZ_4K-1);
+ fbsz = (fbsz_sys + padr_sys - padr + SZ_4K-1) & ~(SZ_4K-1);
+
+ /* line up dspadr offset with padr */
+ dspadr_actual =
+ (fbsz > SZ_1M) ? lineup_offset(*dspadr, padr, SZ_1M-1) :
+ (fbsz > SZ_64K) ? lineup_offset(*dspadr, padr, SZ_64K-1) :
+ /* (fbsz > SZ_4KB) ? */ *dspadr;
+ if (dspadr_actual != *dspadr)
+ pr_debug(
+ "omapdsp: actual dspadr for FBEXPORT = %08x\n",
+ dspadr_actual);
+ *dspadr = dspadr_actual;
+
+ cnt = omap_mmu_exmap(&dsp_mmu, dspadr_actual, padr, fbsz,
+ EXMAP_TYPE_FB);
+ if (cnt < 0) {
+ printk(KERN_ERR "omapdsp: exmap failure.\n");
+ return cnt;
+ }
+
+ if ((padr != padr_sys) || (fbsz != fbsz_sys)) {
+ printk(KERN_WARNING
+" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+" !! screen base address or size is not aligned in 4kB: !!\n"
+" !! actual screen adr = %08lx, size = %08lx !!\n"
+" !! exporting adr = %08lx, size = %08lx !!\n"
+" !! Make sure that the framebuffer is allocated with 4kB-order! !!\n"
+" !! Otherwise DSP can corrupt the kernel memory. !!\n"
+" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",
+ padr_sys, fbsz_sys, padr, fbsz);
+ }
+
+ /* increase the DMA priority */
+ set_emiff_dma_prio(15);
+
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+ omapfb_nb = kzalloc(sizeof(struct omapfb_notifier_block), GFP_KERNEL);
+ if (omapfb_nb == NULL) {
+ printk(KERN_ERR
+ "omapdsp: failed to allocate memory for omapfb_nb!\n");
+ omap_mmu_exunmap(&dsp_mmu, (unsigned long)dspadr);
+ return -ENOMEM;
+ }
+
+ status = omapfb_register_client(omapfb_nb, omapfb_notifier_cb, NULL);
+ if (status)
+ pr_info("omapfb_register_client(): failure(%d)\n", status);
+#endif
+
+ return cnt;
+}
+#else
+void mbox_fbctl_upd(void) { }
+#endif
+
+/* dsp/mem fops: backward compatibility */
+static ssize_t dsp_mem_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct bin_attribute attr;
+
+ return __omap_mmu_mem_read(&dsp_mmu, &attr,
+ (char __user *)buf, *ppos, count);
+}
+
+static ssize_t dsp_mem_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct bin_attribute attr;
+
+ return __omap_mmu_mem_write(&dsp_mmu, &attr,
+ (char __user *)buf, *ppos, count);
+}
+
+static int dsp_mem_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct omap_dsp_mapinfo mapinfo;
+ __u32 size;
+
+ switch (cmd) {
+ case MEM_IOCTL_MMUINIT:
+ if (dsp_mmu.exmap_tbl)
+ omap_mmu_unregister(&dsp_mmu);
+ dsp_mem_ipi_init();
+ return omap_mmu_register(&dsp_mmu);
+
+ case MEM_IOCTL_EXMAP:
+ if (copy_from_user(&mapinfo, (void __user *)arg,
+ sizeof(mapinfo)))
+ return -EFAULT;
+ return omap_mmu_exmap(&dsp_mmu, mapinfo.dspadr,
+ 0, mapinfo.size, EXMAP_TYPE_MEM);
+
+ case MEM_IOCTL_EXUNMAP:
+ return omap_mmu_exunmap(&dsp_mmu, (unsigned long)arg);
+
+ case MEM_IOCTL_EXMAP_FLUSH:
+ omap_mmu_exmap_flush(&dsp_mmu);
+ return 0;
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+ case MEM_IOCTL_FBEXPORT:
+ {
+ dsp_long_t dspadr;
+ int ret;
+ if (copy_from_user(&dspadr, (void __user *)arg,
+ sizeof(dsp_long_t)))
+ return -EFAULT;
+ ret = dsp_fbexport(&dspadr);
+ if (copy_to_user((void __user *)arg, &dspadr,
+ sizeof(dsp_long_t)))
+ return -EFAULT;
+ return ret;
+ }
+#endif
+ case MEM_IOCTL_MMUITACK:
+ return dsp_mmu_itack();
+
+ case MEM_IOCTL_KMEM_RESERVE:
+
+ if (copy_from_user(&size, (void __user *)arg,
+ sizeof(__u32)))
+ return -EFAULT;
+ return omap_mmu_kmem_reserve(&dsp_mmu, size);
+
+
+ case MEM_IOCTL_KMEM_RELEASE:
+ omap_mmu_kmem_release();
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+struct file_operations dsp_mem_fops = {
+ .owner = THIS_MODULE,
+ .read = dsp_mem_read,
+ .write = dsp_mem_write,
+ .ioctl = dsp_mem_ioctl,
+};
+
+void dsp_mem_start(void)
+{
+ 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();
+}
+
+static void dsp_mmu_irq_work(struct work_struct *work)
+{
+ struct omap_mmu *mmu = container_of(work, struct omap_mmu, irq_work);
+
+ if (dsp_cfgstat_get_stat() == CFGSTAT_READY) {
+ dsp_err_set(ERRCODE_MMU, mmu->fault_address);
+ return;
+ }
+ omap_mmu_itack(mmu);
+ pr_info("Resetting DSP...\n");
+ dsp_cpustat_request(CPUSTAT_RESET);
+ omap_mmu_enable(mmu, 0);
+}
+
+/*
+ * later half of dsp memory initialization
+ */
+int dsp_mem_late_init(void)
+{
+ int ret;
+
+ dsp_mem_ipi_init();
+
+ INIT_WORK(&dsp_mmu.irq_work, dsp_mmu_irq_work);
+ ret = omap_mmu_register(&dsp_mmu);
+ if (ret) {
+ dsp_reset_idle_boot_base();
+ goto out;
+ }
+ omap_dsp->mmu = &dsp_mmu;
+ out:
+ return ret;
+}
+
+int __init dsp_mem_init(void)
+{
+#ifdef CONFIG_ARCH_OMAP2
+ dsp_mmu.clk = dsp_fck_handle;
+ dsp_mmu.memclk = dsp_ick_handle;
+#elif defined(CONFIG_ARCH_OMAP1)
+ dsp_mmu.clk = dsp_ck_handle;
+ dsp_mmu.memclk = api_ck_handle;
+#endif
+ return 0;
+}
+
+void dsp_mem_exit(void)
+{
+ dsp_reset_idle_boot_base();
+ omap_mmu_unregister(&dsp_mmu);
+}
diff --git a/drivers/dsp/dspgateway/error.c b/drivers/dsp/dspgateway/error.c
new file mode 100644
index 0000000..d2276f9
--- /dev/null
+++ b/drivers/dsp/dspgateway/error.c
@@ -0,0 +1,227 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/arch/mailbox.h>
+#include <asm/uaccess.h>
+#include "dsp_mbcmd.h"
+#include "dsp.h"
+
+/*
+ * value seen through read()
+ */
+#define DSP_ERR_WDT 0x00000001
+#define DSP_ERR_MMU 0x00000002
+static unsigned long errval;
+
+static DECLARE_WAIT_QUEUE_HEAD(err_wait_q);
+static int errcnt;
+static u16 wdtval; /* FIXME: read through ioctl */
+static u32 mmu_fadr; /* FIXME: read through ioctl */
+
+/*
+ * DSP error detection device file operations
+ */
+static ssize_t dsp_err_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ unsigned long flags;
+ int status;
+ DEFINE_WAIT(wait);
+
+ if (count < 4)
+ return 0;
+
+ prepare_to_wait(&err_wait_q, &wait, TASK_INTERRUPTIBLE);
+ if (errcnt == 0)
+ schedule();
+ finish_wait(&err_wait_q, &wait);
+ if (signal_pending(current))
+ return -EINTR;
+
+ local_irq_save(flags);
+ status = copy_to_user(buf, &errval, 4);
+ if (status) {
+ local_irq_restore(flags);
+ return -EFAULT;
+ }
+ errcnt = 0;
+ local_irq_restore(flags);
+
+ return 4;
+}
+
+static unsigned int dsp_err_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+
+ poll_wait(file, &err_wait_q, wait);
+ if (errcnt != 0)
+ mask |= POLLIN | POLLRDNORM;
+
+ return mask;
+}
+
+struct file_operations dsp_err_fops = {
+ .owner = THIS_MODULE,
+ .poll = dsp_err_poll,
+ .read = dsp_err_read,
+};
+
+/*
+ * set / clear functions
+ */
+
+/* DSP MMU */
+static void dsp_err_mmu_set(unsigned long arg)
+{
+ disable_irq(omap_dsp->mmu->irq);
+ mmu_fadr = (u32)arg;
+}
+
+static void dsp_err_mmu_clr(void)
+{
+ enable_irq(omap_dsp->mmu->irq);
+}
+
+/* WDT */
+static void dsp_err_wdt_set(unsigned long arg)
+{
+ wdtval = (u16)arg;
+}
+
+/*
+ * error code handler
+ */
+static struct {
+ unsigned long val;
+ void (*set)(unsigned long arg);
+ void (*clr)(void);
+} dsp_err_desc[ERRCODE_MAX] = {
+ [ERRCODE_MMU] = { DSP_ERR_MMU, dsp_err_mmu_set, dsp_err_mmu_clr },
+ [ERRCODE_WDT] = { DSP_ERR_WDT, dsp_err_wdt_set, NULL },
+};
+
+void dsp_err_set(enum errcode_e code, unsigned long arg)
+{
+ if (dsp_err_desc[code].set != NULL)
+ dsp_err_desc[code].set(arg);
+
+ errval |= dsp_err_desc[code].val;
+ errcnt++;
+ wake_up_interruptible(&err_wait_q);
+}
+
+void dsp_err_clear(enum errcode_e code)
+{
+ errval &= ~dsp_err_desc[code].val;
+
+ if (dsp_err_desc[code].clr != NULL)
+ dsp_err_desc[code].clr();
+}
+
+int dsp_err_isset(enum errcode_e code)
+{
+ return (errval & dsp_err_desc[code].val) ? 1 : 0;
+}
+
+void dsp_err_notify(void)
+{
+ /* new error code should be assigned */
+ dsp_err_set(DSP_ERR_WDT, 0);
+}
+
+/*
+ * functions called from mailbox interrupt routine
+ */
+static void mbox_err_wdt(u16 data)
+{
+ dsp_err_set(DSP_ERR_WDT, (unsigned long)data);
+}
+
+#ifdef OLD_BINARY_SUPPORT
+/* v3.3 obsolete */
+void mbox_wdt(struct mbcmd *mb)
+{
+ mbox_err_wdt(mb->data);
+}
+#endif
+
+extern void mbox_err_ipbfull(void);
+extern void mbox_err_fatal(u8 tid);
+
+void mbox_err(struct mbcmd *mb)
+{
+ u8 eid = mb->cmd_l;
+ char *eidnm = subcmd_name(mb);
+ u8 tid;
+
+ if (eidnm) {
+ printk(KERN_WARNING
+ "mbox: ERR from DSP (%s): 0x%04x\n", eidnm, mb->data);
+ } else {
+ printk(KERN_WARNING
+ "mbox: ERR from DSP (unknown EID=%02x): %04x\n",
+ eid, mb->data);
+ }
+
+ switch (eid) {
+ case EID_IPBFULL:
+ mbox_err_ipbfull();
+ break;
+
+ case EID_FATAL:
+ tid = mb->data & 0x00ff;
+ mbox_err_fatal(tid);
+ break;
+
+ case EID_WDT:
+ mbox_err_wdt(mb->data);
+ break;
+ }
+}
+
+/*
+ *
+ */
+void dsp_err_start(void)
+{
+ enum errcode_e i;
+
+ for (i = 0; i < ERRCODE_MAX; i++) {
+ if (dsp_err_isset(i))
+ dsp_err_clear(i);
+ }
+ omap_dsp->mbox->err_notify = dsp_err_notify;
+ errcnt = 0;
+}
+
+void dsp_err_stop(void)
+{
+ wake_up_interruptible(&err_wait_q);
+ omap_dsp->mbox->err_notify = NULL;
+}
diff --git a/drivers/dsp/dspgateway/hardware_dsp.h b/drivers/dsp/dspgateway/hardware_dsp.h
new file mode 100644
index 0000000..5af46f8
--- /dev/null
+++ b/drivers/dsp/dspgateway/hardware_dsp.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_DSP_HARDWARE_DSP_H
+#define __OMAP_DSP_HARDWARE_DSP_H
+
+#ifdef CONFIG_ARCH_OMAP1
+#include "omap1_dsp.h"
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3430)
+#include "omap2_dsp.h"
+#endif
+
+#endif /* __OMAP_DSP_HARDWARE_DSP_H */
diff --git a/drivers/dsp/dspgateway/ipbuf.c b/drivers/dsp/dspgateway/ipbuf.c
new file mode 100644
index 0000000..aba8e74
--- /dev/null
+++ b/drivers/dsp/dspgateway/ipbuf.c
@@ -0,0 +1,353 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <asm/arch/mailbox.h>
+#include "dsp_mbcmd.h"
+#include "dsp.h"
+#include "ipbuf.h"
+
+static struct ipbuf_head *g_ipbuf;
+struct ipbcfg ipbcfg;
+struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
+static struct ipblink ipb_free = IPBLINK_INIT;
+static int ipbuf_sys_hold_mem_active;
+
+static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
+ char *buf);
+static struct device_attribute dev_attr_ipbuf = __ATTR_RO(ipbuf);
+
+void ipbuf_stop(void)
+{
+ int i;
+
+ device_remove_file(omap_dsp->dev, &dev_attr_ipbuf);
+
+ spin_lock(&ipb_free.lock);
+ RESET_IPBLINK(&ipb_free);
+ spin_unlock(&ipb_free.lock);
+
+ ipbcfg.ln = 0;
+ if (g_ipbuf) {
+ kfree(g_ipbuf);
+ g_ipbuf = NULL;
+ }
+ for (i = 0; i < ipbuf_sys_hold_mem_active; i++) {
+ dsp_mem_disable((void *)daram_base);
+ }
+ ipbuf_sys_hold_mem_active = 0;
+}
+
+int ipbuf_config(u16 ln, u16 lsz, void *base)
+{
+ size_t lsz_byte = ((size_t)lsz) << 1;
+ size_t size;
+ int ret = 0;
+ int i;
+
+ /*
+ * global IPBUF
+ */
+ if (((unsigned long)base) & 0x3) {
+ printk(KERN_ERR
+ "omapdsp: global ipbuf address(0x%p) is not "
+ "32-bit aligned!\n", base);
+ return -EINVAL;
+ }
+ size = lsz_byte * ln;
+ if (dsp_address_validate(base, size, "global ipbuf") < 0)
+ return -EINVAL;
+
+ g_ipbuf = kmalloc(sizeof(struct ipbuf_head) * ln, GFP_KERNEL);
+ if (g_ipbuf == NULL) {
+ printk(KERN_ERR
+ "omapdsp: memory allocation for ipbuf failed.\n");
+ return -ENOMEM;
+ }
+ for (i = 0; i < ln; i++) {
+ void *top, *btm;
+
+ top = base + (sizeof(struct ipbuf) + lsz_byte) * i;
+ btm = base + (sizeof(struct ipbuf) + lsz_byte) * (i+1) - 1;
+ g_ipbuf[i].p = (struct ipbuf *)top;
+ g_ipbuf[i].bid = i;
+ if (((unsigned long)top & 0xfffe0000) !=
+ ((unsigned long)btm & 0xfffe0000)) {
+ /*
+ * an ipbuf line should not cross
+ * 64k-word boundary.
+ */
+ printk(KERN_ERR
+ "omapdsp: ipbuf[%d] crosses 64k-word boundary!\n"
+ " @0x%p, size=0x%08x\n", i, top, lsz_byte);
+ ret = -EINVAL;
+ goto free_out;
+ }
+ }
+ ipbcfg.ln = ln;
+ ipbcfg.lsz = lsz;
+ ipbcfg.base = base;
+ ipbcfg.bsycnt = ln; /* DSP holds all ipbufs initially. */
+ ipbcfg.cnt_full = 0;
+
+ pr_info("omapdsp: IPBUF configuration\n"
+ " %d words * %d lines at 0x%p.\n",
+ ipbcfg.lsz, ipbcfg.ln, ipbcfg.base);
+
+ ret = device_create_file(omap_dsp->dev, &dev_attr_ipbuf);
+ if (ret)
+ printk(KERN_ERR "device_create_file failed: %d\n", ret);
+
+ return ret;
+
+ free_out:
+ kfree(g_ipbuf);
+ g_ipbuf = NULL;
+ return ret;
+}
+
+int ipbuf_sys_config(void *p, arm_dsp_dir_t 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, arm_dsp_dir_t 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);
+}
+
+/*
+ * Global IPBUF operations
+ */
+struct ipbuf_head *bid_to_ipbuf(u16 bid)
+{
+ return &g_ipbuf[bid];
+}
+
+struct ipbuf_head *get_free_ipbuf(u8 tid)
+{
+ struct ipbuf_head *ipb_h;
+
+ if (dsp_mem_enable_ipbuf() < 0)
+ return NULL;
+
+ spin_lock(&ipb_free.lock);
+
+ if (ipblink_empty(&ipb_free)) {
+ /* FIXME: wait on queue when not available. */
+ ipb_h = NULL;
+ goto out;
+ }
+ ipb_h = &g_ipbuf[ipb_free.top];
+ ipb_h->p->la = tid; /* lock */
+ __ipblink_del_top(&ipb_free);
+out:
+ spin_unlock(&ipb_free.lock);
+ dsp_mem_disable_ipbuf();
+
+ return ipb_h;
+}
+
+void release_ipbuf(struct ipbuf_head *ipb_h)
+{
+ if (ipb_h->p->la == TID_FREE) {
+ printk(KERN_WARNING
+ "omapdsp: attempt to release unlocked IPBUF[%d].\n",
+ ipb_h->bid);
+ /*
+ * FIXME: re-calc bsycnt
+ */
+ return;
+ }
+ ipb_h->p->la = TID_FREE;
+ ipb_h->p->sa = TID_FREE;
+ ipblink_add_tail(&ipb_free, ipb_h->bid);
+}
+
+static int try_yld(struct ipbuf_head *ipb_h)
+{
+ int status;
+
+ ipb_h->p->sa = TID_ANON;
+ status = mbcompose_send(BKYLD, 0, ipb_h->bid);
+ if (status < 0) {
+ /* DSP is busy and ARM keeps this line. */
+ release_ipbuf(ipb_h);
+ return status;
+ }
+
+ ipb_bsycnt_inc(&ipbcfg);
+ return 0;
+}
+
+/*
+ * balancing ipbuf lines with DSP
+ */
+static void do_balance_ipbuf(struct work_struct *unused)
+{
+ while (ipbcfg.bsycnt <= ipbcfg.ln / 4) {
+ struct ipbuf_head *ipb_h;
+
+ if ((ipb_h = get_free_ipbuf(TID_ANON)) == NULL)
+ return;
+ if (try_yld(ipb_h) < 0)
+ return;
+ }
+}
+
+static DECLARE_WORK(balance_ipbuf_work, do_balance_ipbuf);
+
+void balance_ipbuf(void)
+{
+ schedule_work(&balance_ipbuf_work);
+}
+
+/* for process context */
+void unuse_ipbuf(struct ipbuf_head *ipb_h)
+{
+ if (ipbcfg.bsycnt > ipbcfg.ln / 4) {
+ /* we don't have enough IPBUF lines. let's keep it. */
+ release_ipbuf(ipb_h);
+ } else {
+ /* we have enough IPBUF lines. let's return this line to DSP. */
+ ipb_h->p->la = TID_ANON;
+ try_yld(ipb_h);
+ balance_ipbuf();
+ }
+}
+
+/* for interrupt context */
+void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h)
+{
+ release_ipbuf(ipb_h);
+ balance_ipbuf();
+}
+
+/*
+ * functions called from mailbox interrupt routine
+ */
+
+void mbox_err_ipbfull(void)
+{
+ ipbcfg.cnt_full++;
+}
+
+/*
+ * sysfs files
+ */
+static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int len = 0;
+ u16 bid;
+
+ for (bid = 0; bid < ipbcfg.ln; bid++) {
+ struct ipbuf_head *ipb_h = &g_ipbuf[bid];
+ u16 la = ipb_h->p->la;
+ u16 ld = ipb_h->p->ld;
+ u16 c = ipb_h->p->c;
+
+ if (len > PAGE_SIZE - 100) {
+ len += sprintf(buf + len, "out of buffer.\n");
+ goto finish;
+ }
+
+ len += sprintf(buf + len, "ipbuf[%d]: adr = 0x%p\n",
+ bid, ipb_h->p);
+ if (la == TID_FREE) {
+ len += sprintf(buf + len,
+ " DSPtask[%d]->Linux "
+ "(already read and now free for Linux)\n",
+ ld);
+ } else if (ld == TID_FREE) {
+ len += sprintf(buf + len,
+ " Linux->DSPtask[%d] "
+ "(already read and now free for DSP)\n",
+ la);
+ } else if (ipbuf_is_held(ld, bid)) {
+ len += sprintf(buf + len,
+ " DSPtask[%d]->Linux "
+ "(waiting to be read)\n"
+ " count = %d\n", ld, c);
+ } else {
+ len += sprintf(buf + len,
+ " Linux->DSPtask[%d] "
+ "(waiting to be read)\n"
+ " count = %d\n", la, c);
+ }
+ }
+
+ len += sprintf(buf + len, "\nFree IPBUF link: ");
+ spin_lock(&ipb_free.lock);
+ ipblink_for_each(bid, &ipb_free) {
+ len += sprintf(buf + len, "%d ", bid);
+ }
+ spin_unlock(&ipb_free.lock);
+ len += sprintf(buf + len, "\n");
+ len += sprintf(buf + len, "IPBFULL error count: %ld\n",
+ ipbcfg.cnt_full);
+
+finish:
+ return len;
+}
diff --git a/drivers/dsp/dspgateway/ipbuf.h b/drivers/dsp/dspgateway/ipbuf.h
new file mode 100644
index 0000000..926d353
--- /dev/null
+++ b/drivers/dsp/dspgateway/ipbuf.h
@@ -0,0 +1,193 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __PLAT_OMAP_DSP_IPBUF_H
+#define __PLAT_OMAP_DSP_IPBUF_H
+
+struct ipbuf {
+ u16 c; /* count */
+ u16 next; /* link */
+ u16 la; /* lock owner (ARM side) */
+ u16 sa; /* sync word (ARM->DSP) */
+ u16 ld; /* lock owner (DSP side) */
+ u16 sd; /* sync word (DSP->ARM) */
+ unsigned char d[0]; /* data */
+};
+
+struct ipbuf_p {
+ u16 c; /* count */
+ u16 s; /* sync word */
+ u16 al; /* data address lower */
+ u16 ah; /* data address upper */
+};
+
+#define IPBUF_SYS_DLEN 31
+
+struct ipbuf_sys {
+ u16 s; /* sync word */
+ u16 d[IPBUF_SYS_DLEN]; /* data */
+};
+
+struct ipbcfg {
+ u16 ln;
+ u16 lsz;
+ void *base;
+ u16 bsycnt;
+ unsigned long cnt_full; /* count of IPBFULL error */
+};
+
+struct ipbuf_head {
+ u16 bid;
+ struct ipbuf *p;
+};
+
+extern struct ipbcfg ipbcfg;
+extern struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad;
+
+#define ipb_bsycnt_inc(ipbcfg) atomic_inc((atomic_t *)&((ipbcfg)->bsycnt))
+#define ipb_bsycnt_dec(ipbcfg) atomic_dec((atomic_t *)&((ipbcfg)->bsycnt))
+
+#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;
+ u16 top;
+ u16 tail;
+};
+
+#define IPBLINK_INIT { \
+ .lock = SPIN_LOCK_UNLOCKED, \
+ .top = BID_NULL, \
+ .tail = BID_NULL, \
+ }
+
+#define INIT_IPBLINK(link) \
+ do { \
+ spin_lock_init(&(link)->lock); \
+ (link)->top = BID_NULL; \
+ (link)->tail = BID_NULL; \
+ } while(0)
+
+#define RESET_IPBLINK(link) \
+ do { \
+ (link)->top = BID_NULL; \
+ (link)->tail = BID_NULL; \
+ } while(0)
+
+#define ipblink_empty(link) ((link)->top == BID_NULL)
+
+static inline void __ipblink_del_top(struct ipblink *link)
+{
+ struct ipbuf_head *ipb_h = bid_to_ipbuf(link->top);
+
+ if ((link->top = ipb_h->p->next) == BID_NULL)
+ link->tail = BID_NULL;
+ else
+ ipb_h->p->next = BID_NULL;
+}
+
+static inline void ipblink_del_top(struct ipblink *link)
+{
+ spin_lock(&link->lock);
+ __ipblink_del_top(link);
+ spin_unlock(&link->lock);
+}
+
+static inline void __ipblink_add_tail(struct ipblink *link, u16 bid)
+{
+ if (ipblink_empty(link))
+ link->top = bid;
+ else
+ bid_to_ipbuf(link->tail)->p->next = bid;
+ link->tail = bid;
+}
+
+static inline void ipblink_add_tail(struct ipblink *link, u16 bid)
+{
+ spin_lock(&link->lock);
+ __ipblink_add_tail(link, bid);
+ spin_unlock(&link->lock);
+}
+
+static inline void __ipblink_flush(struct ipblink *link)
+{
+ u16 bid;
+
+ while (!ipblink_empty(link)) {
+ bid = link->top;
+ __ipblink_del_top(link);
+ unuse_ipbuf(bid_to_ipbuf(bid));
+ }
+}
+
+static inline void ipblink_flush(struct ipblink *link)
+{
+ spin_lock(&link->lock);
+ __ipblink_flush(link);
+ spin_unlock(&link->lock);
+}
+
+static inline void __ipblink_add_pvt(struct ipblink *link)
+{
+ link->top = BID_PVT;
+ link->tail = BID_PVT;
+}
+
+static inline void ipblink_add_pvt(struct ipblink *link)
+{
+ spin_lock(&link->lock);
+ __ipblink_add_pvt(link);
+ spin_unlock(&link->lock);
+}
+
+static inline void __ipblink_del_pvt(struct ipblink *link)
+{
+ link->top = BID_NULL;
+ link->tail = BID_NULL;
+}
+
+static inline void ipblink_del_pvt(struct ipblink *link)
+{
+ spin_lock(&link->lock);
+ __ipblink_del_pvt(link);
+ spin_unlock(&link->lock);
+}
+
+static inline void __ipblink_flush_pvt(struct ipblink *link)
+{
+ if (!ipblink_empty(link))
+ ipblink_del_pvt(link);
+}
+
+static inline void ipblink_flush_pvt(struct ipblink *link)
+{
+ spin_lock(&link->lock);
+ __ipblink_flush_pvt(link);
+ spin_unlock(&link->lock);
+}
+
+#define ipblink_for_each(bid, link) \
+ for (bid = (link)->top; bid != BID_NULL; bid = bid_to_ipbuf(bid)->p->next)
+
+#endif /* __PLAT_OMAP_DSP_IPBUF_H */
diff --git a/drivers/dsp/dspgateway/mblog.c b/drivers/dsp/dspgateway/mblog.c
new file mode 100644
index 0000000..2b1e113
--- /dev/null
+++ b/drivers/dsp/dspgateway/mblog.c
@@ -0,0 +1,280 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2003-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <asm/arch/mailbox.h>
+#include "dsp_mbcmd.h"
+#include "dsp.h"
+
+char *subcmd_name(struct mbcmd *mb)
+{
+ u8 cmd_h = mb->cmd_h;
+ u8 cmd_l = mb->cmd_l;
+ char *s;
+
+ switch (cmd_h) {
+ case MBOX_CMD_DSP_RUNLEVEL:
+ s = (cmd_l == RUNLEVEL_USER) ? "USER":
+ (cmd_l == RUNLEVEL_SUPER) ? "SUPER":
+ (cmd_l == RUNLEVEL_RECOVERY) ? "RECOVERY":
+ NULL;
+ break;
+ case MBOX_CMD_DSP_PM:
+ s = (cmd_l == PM_DISABLE) ? "DISABLE":
+ (cmd_l == PM_ENABLE) ? "ENABLE":
+ NULL;
+ break;
+ case MBOX_CMD_DSP_KFUNC:
+ s = (cmd_l == KFUNC_FBCTL) ? "FBCTL":
+ (cmd_l == KFUNC_POWER) ?
+ ((mb->data == AUDIO_PWR_UP) ? "PWR AUD /UP":
+ (mb->data == AUDIO_PWR_DOWN) ? "PWR AUD /DOWN":
+ (mb->data == AUDIO_PWR_DOWN2) ? "PWR AUD /DOWN(2)":
+ (mb->data == DSP_PWR_UP) ? "PWR DSP /UP":
+ (mb->data == DSP_PWR_DOWN) ? "PWR DSP /DOWN":
+ (mb->data == DVFS_START) ? "PWR DVFS/START":
+ (mb->data == DVFS_STOP) ? "PWR DVFS/STOP":
+ NULL):
+
+ NULL;
+ break;
+ case MBOX_CMD_DSP_DSPCFG:
+ {
+ u8 cfgc = cmd_l & 0x7f;
+ s = (cfgc == DSPCFG_REQ) ? "REQ":
+ (cfgc == DSPCFG_SYSADRH) ? "SYSADRH":
+ (cfgc == DSPCFG_SYSADRL) ? "SYSADRL":
+ (cfgc == DSPCFG_ABORT) ? "ABORT":
+ (cfgc == DSPCFG_PROTREV) ? "PROTREV":
+ NULL;
+ break;
+ }
+ case MBOX_CMD_DSP_REGRW:
+ s = (cmd_l == REGRW_MEMR) ? "MEMR":
+ (cmd_l == REGRW_MEMW) ? "MEMW":
+ (cmd_l == REGRW_IOR) ? "IOR":
+ (cmd_l == REGRW_IOW) ? "IOW":
+ (cmd_l == REGRW_DATA) ? "DATA":
+ NULL;
+ break;
+ case MBOX_CMD_DSP_GETVAR:
+ case MBOX_CMD_DSP_SETVAR:
+ s = (cmd_l == VARID_ICRMASK) ? "ICRMASK":
+ (cmd_l == VARID_LOADINFO) ? "LOADINFO":
+ NULL;
+ break;
+ case MBOX_CMD_DSP_ERR:
+ s = (cmd_l == EID_BADTID) ? "BADTID":
+ (cmd_l == EID_BADTCN) ? "BADTCN":
+ (cmd_l == EID_BADBID) ? "BADBID":
+ (cmd_l == EID_BADCNT) ? "BADCNT":
+ (cmd_l == EID_NOTLOCKED) ? "NOTLOCKED":
+ (cmd_l == EID_STVBUF) ? "STVBUF":
+ (cmd_l == EID_BADADR) ? "BADADR":
+ (cmd_l == EID_BADTCTL) ? "BADTCTL":
+ (cmd_l == EID_BADPARAM) ? "BADPARAM":
+ (cmd_l == EID_FATAL) ? "FATAL":
+ (cmd_l == EID_WDT) ? "WDT":
+ (cmd_l == EID_NOMEM) ? "NOMEM":
+ (cmd_l == EID_NORES) ? "NORES":
+ (cmd_l == EID_IPBFULL) ? "IPBFULL":
+ (cmd_l == EID_TASKNOTRDY) ? "TASKNOTRDY":
+ (cmd_l == EID_TASKBSY) ? "TASKBSY":
+ (cmd_l == EID_TASKERR) ? "TASKERR":
+ (cmd_l == EID_BADCFGTYP) ? "BADCFGTYP":
+ (cmd_l == EID_DEBUG) ? "DEBUG":
+ (cmd_l == EID_BADSEQ) ? "BADSEQ":
+ (cmd_l == EID_BADCMD) ? "BADCMD":
+ NULL;
+ break;
+ default:
+ s = NULL;
+ }
+
+ return s;
+}
+
+/* output of show() method should fit to PAGE_SIZE */
+#define MBLOG_DEPTH 64
+
+struct mblogent {
+ unsigned long jiffies;
+ mbox_msg_t msg;
+ arm_dsp_dir_t dir;
+};
+
+static struct {
+ spinlock_t lock;
+ int wp;
+ unsigned long cnt, cnt_ad, cnt_da;
+ struct mblogent ent[MBLOG_DEPTH];
+} mblog = {
+ .lock = SPIN_LOCK_UNLOCKED,
+};
+
+#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
+static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir)
+{
+ const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
+ char *dir_str;
+ char *subname;
+
+ dir_str = (dir == DIR_A2D) ? "sending " : "receiving";
+ switch (ci->cmd_l_type) {
+ case CMD_L_TYPE_SUBCMD:
+ subname = subcmd_name(mb);
+ if (unlikely(!subname))
+ subname = "Unknown";
+ pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n",
+ dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
+ ci->name, subname, mb->data);
+ break;
+ case CMD_L_TYPE_TID:
+ pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n",
+ dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
+ ci->name, mb->cmd_l, mb->data);
+ break;
+ case CMD_L_TYPE_NULL:
+ pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n",
+ dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
+ ci->name, mb->data);
+ break;
+ }
+}
+#else
+static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir) { }
+#endif
+
+void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir)
+{
+ struct mblogent *ent;
+
+ spin_lock(&mblog.lock);
+ ent = &mblog.ent[mblog.wp];
+ ent->jiffies = jiffies;
+ ent->msg = *(mbox_msg_t *)mb;
+ ent->dir = dir;
+ if (mblog.cnt < 0xffffffff)
+ mblog.cnt++;
+ switch (dir) {
+ case DIR_A2D:
+ if (mblog.cnt_ad < 0xffffffff)
+ mblog.cnt_ad++;
+ break;
+ case DIR_D2A:
+ if (mblog.cnt_da < 0xffffffff)
+ mblog.cnt_da++;
+ break;
+ }
+ if (++mblog.wp == MBLOG_DEPTH)
+ mblog.wp = 0;
+ spin_unlock(&mblog.lock);
+
+ mblog_print_cmd(mb, dir);
+}
+
+/*
+ * sysfs file
+ */
+static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int len = 0;
+ int wp;
+ int i;
+
+ spin_lock(&mblog.lock);
+
+ wp = mblog.wp;
+ len += sprintf(buf + len,
+ "log count:%ld / ARM->DSP:%ld, DSP->ARM:%ld\n",
+ mblog.cnt, mblog.cnt_ad, mblog.cnt_da);
+ if (mblog.cnt == 0)
+ goto done;
+
+ len += sprintf(buf + len, " ARM->DSP ARM<-DSP\n");
+ len += sprintf(buf + len, " jiffies cmd data cmd data\n");
+ i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0;
+ do {
+ struct mblogent *ent = &mblog.ent[i];
+ struct mbcmd *mb = (struct mbcmd *)&ent->msg;
+ char *subname;
+ struct cmdinfo ci_null = {
+ .name = "Unknown",
+ .cmd_l_type = CMD_L_TYPE_NULL,
+ };
+ const struct cmdinfo *ci;
+
+ len += sprintf(buf + len,
+ (ent->dir == DIR_A2D) ?
+ "%08lx %04x %04x ":
+ "%08lx %04x %04x ",
+ ent->jiffies,
+ (ent->msg >> 16) & 0x7fff, ent->msg & 0xffff);
+
+ if ((ci = cmdinfo[mb->cmd_h]) == NULL)
+ ci = &ci_null;
+
+ switch (ci->cmd_l_type) {
+ case CMD_L_TYPE_SUBCMD:
+ if ((subname = subcmd_name(mb)) == NULL)
+ subname = "Unknown";
+ len += sprintf(buf + len, "%s:%s\n",
+ ci->name, subname);
+ break;
+ case CMD_L_TYPE_TID:
+ len += sprintf(buf + len, "%s:task %d\n",
+ ci->name, mb->cmd_l);
+ break;
+ case CMD_L_TYPE_NULL:
+ len += sprintf(buf + len, "%s\n", ci->name);
+ break;
+ }
+
+ if (++i == MBLOG_DEPTH)
+ i = 0;
+ } while (i != wp);
+
+done:
+ spin_unlock(&mblog.lock);
+
+ return len;
+}
+
+static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
+
+void __init mblog_init(void)
+{
+ int ret;
+
+ ret = device_create_file(omap_dsp->dev, &dev_attr_mblog);
+ if (ret)
+ printk(KERN_ERR "device_create_file failed: %d\n", ret);
+}
+
+void mblog_exit(void)
+{
+ device_remove_file(omap_dsp->dev, &dev_attr_mblog);
+}
diff --git a/drivers/dsp/dspgateway/mmu.h b/drivers/dsp/dspgateway/mmu.h
new file mode 100644
index 0000000..9d60e9e
--- /dev/null
+++ b/drivers/dsp/dspgateway/mmu.h
@@ -0,0 +1,140 @@
+#ifndef __PLAT_OMAP_DSP_MMU_H
+#define __PLAT_OMAP_DSP_MMU_H
+
+#ifdef CONFIG_ARCH_OMAP1
+
+#ifdef CONFIG_ARCH_OMAP15XX
+struct omap_mmu dsp_mmu = {
+ .name = "mmu:dsp",
+ .type = OMAP_MMU_DSP,
+ .base = IO_ADDRESS(OMAP1510_DSP_MMU_BASE),
+ .membase = OMAP1510_DSP_BASE,
+ .memsize = OMAP1510_DSP_SIZE,
+ .nr_tlb_entries = 32,
+ .addrspace = 24,
+ .irq = INT_1510_DSP_MMU,
+ .ops = &omap1_mmu_ops,
+};
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+struct omap_mmu dsp_mmu = {
+ .name = "mmu:dsp",
+ .type = OMAP_MMU_DSP,
+ .base = IO_ADDRESS(OMAP16XX_DSP_MMU_BASE),
+ .membase = OMAP16XX_DSP_BASE,
+ .memsize = OMAP16XX_DSP_SIZE,
+ .nr_tlb_entries = 32,
+ .addrspace = 24,
+ .irq = INT_1610_DSP_MMU,
+ .ops = &omap1_mmu_ops,
+};
+#endif
+#else /* OMAP2 */
+struct omap_mmu dsp_mmu = {
+ .name = "mmu:dsp",
+ .type = OMAP_MMU_DSP,
+ .base = DSP_MMU_24XX_VIRT,
+ .membase = DSP_MEM_24XX_VIRT,
+ .memsize = DSP_MEM_24XX_SIZE,
+ .nr_tlb_entries = 32,
+ .addrspace = 24,
+ .irq = INT_24XX_DSP_MMU,
+ .ops = &omap2_mmu_ops,
+};
+
+#define IOMAP_VAL 0x3f
+#endif
+
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+static struct omapfb_notifier_block *omapfb_nb;
+static int omapfb_ready;
+#endif
+
+/*
+ * OMAP1 EMIFF access
+ */
+#ifdef CONFIG_ARCH_OMAP1
+#define EMIF_PRIO_LB_MASK 0x0000f000
+#define EMIF_PRIO_LB_SHIFT 12
+#define EMIF_PRIO_DMA_MASK 0x00000f00
+#define EMIF_PRIO_DMA_SHIFT 8
+#define EMIF_PRIO_DSP_MASK 0x00000070
+#define EMIF_PRIO_DSP_SHIFT 4
+#define EMIF_PRIO_MPU_MASK 0x00000007
+#define EMIF_PRIO_MPU_SHIFT 0
+#define set_emiff_dma_prio(prio) \
+ do { \
+ omap_writel((omap_readl(OMAP_TC_OCPT1_PRIOR) & \
+ ~EMIF_PRIO_DMA_MASK) | \
+ ((prio) << EMIF_PRIO_DMA_SHIFT), \
+ OMAP_TC_OCPT1_PRIOR); \
+ } while(0)
+#else
+#define set_emiff_dma_prio(prio) do { } while (0)
+#endif /* CONFIG_ARCH_OMAP1 */
+
+#ifdef CONFIG_ARCH_OMAP1
+static int dsp_mmu_itack(void)
+{
+ unsigned long dspadr;
+
+ pr_info("omapdsp: sending DSP MMU interrupt ack.\n");
+ if (!dsp_err_isset(ERRCODE_MMU)) {
+ printk(KERN_ERR "omapdsp: DSP MMU error has not been set.\n");
+ return -EINVAL;
+ }
+ dspadr = dsp_mmu.fault_address & ~(SZ_4K-1);
+ /* FIXME: reserve TLB entry for this */
+ omap_mmu_exmap(&dsp_mmu, dspadr, 0, SZ_4K, EXMAP_TYPE_MEM);
+ pr_info("omapdsp: falling into recovery runlevel...\n");
+ dsp_set_runlevel(RUNLEVEL_RECOVERY);
+ omap_mmu_itack(&dsp_mmu);
+ udelay(100);
+ omap_mmu_exunmap(&dsp_mmu, dspadr);
+ dsp_err_clear(ERRCODE_MMU);
+ return 0;
+}
+
+/*
+ * 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.
+ */
+static int intmem_enable(void)
+{
+ int ret = 0;
+
+ if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
+ ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA);
+
+ return ret;
+}
+
+static void intmem_disable(void) {
+ if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
+ mbcompose_send(PM, PM_DISABLE, DSPREG_ICR_DMA);
+}
+#else
+static int intmem_enable(void) { return 0; }
+static void intmem_disable(void) { }
+static int dsp_mmu_itack(void) { return 0; }
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+static inline void dsp_mem_ipi_init(void)
+{
+ int i, dspmem_pg_count;
+ dspmem_pg_count = dspmem_size >> 12;
+ for (i = 0; i < dspmem_pg_count; i++) {
+ writel(i, DSP_IPI_INDEX);
+ writel(DSP_IPI_ENTRY_ELMSIZEVALUE_16, DSP_IPI_ENTRY);
+ }
+ writel(1, DSP_IPI_ENABLE);
+ writel(IOMAP_VAL, DSP_IPI_IOMAP);
+}
+#else
+static inline void dsp_mem_ipi_init(void) { }
+#endif
+
+#endif /* __PLAT_OMAP_DSP_MMU_H */
diff --git a/drivers/dsp/dspgateway/omap1_dsp.h b/drivers/dsp/dspgateway/omap1_dsp.h
new file mode 100644
index 0000000..f4ec73e
--- /dev/null
+++ b/drivers/dsp/dspgateway/omap1_dsp.h
@@ -0,0 +1,114 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_DSP_OMAP1_DSP_H
+#define __OMAP_DSP_OMAP1_DSP_H
+
+#ifdef CONFIG_ARCH_OMAP15XX
+#define OMAP1510_DARAM_BASE (OMAP1510_DSP_BASE + 0x0)
+#define OMAP1510_DARAM_SIZE 0x10000
+#define OMAP1510_SARAM_BASE (OMAP1510_DSP_BASE + 0x10000)
+#define OMAP1510_SARAM_SIZE 0x18000
+#endif
+
+#ifdef CONFIG_ARCH_OMAP16XX
+#define OMAP16XX_DARAM_BASE (OMAP16XX_DSP_BASE + 0x0)
+#define OMAP16XX_DARAM_SIZE 0x10000
+#define OMAP16XX_SARAM_BASE (OMAP16XX_DSP_BASE + 0x10000)
+#define OMAP16XX_SARAM_SIZE 0x18000
+#endif
+
+/*
+ * Reset Control
+ */
+#define ARM_RSTCT1_SW_RST 0x0008
+#define ARM_RSTCT1_DSP_RST 0x0004
+#define ARM_RSTCT1_DSP_EN 0x0002
+#define ARM_RSTCT1_ARM_RST 0x0001
+
+/*
+ * MPUI
+ */
+#define MPUI_CTRL_WORDSWAP_MASK 0x00600000
+#define MPUI_CTRL_WORDSWAP_ALL 0x00000000
+#define MPUI_CTRL_WORDSWAP_NONAPI 0x00200000
+#define MPUI_CTRL_WORDSWAP_API 0x00400000
+#define MPUI_CTRL_WORDSWAP_NONE 0x00600000
+#define MPUI_CTRL_AP_MASK 0x001c0000
+#define MPUI_CTRL_AP_MDH 0x00000000
+#define MPUI_CTRL_AP_MHD 0x00040000
+#define MPUI_CTRL_AP_DMH 0x00080000
+#define MPUI_CTRL_AP_HMD 0x000c0000
+#define MPUI_CTRL_AP_DHM 0x00100000
+#define MPUI_CTRL_AP_HDM 0x00140000
+#define MPUI_CTRL_BYTESWAP_MASK 0x00030000
+#define MPUI_CTRL_BYTESWAP_NONE 0x00000000
+#define MPUI_CTRL_BYTESWAP_NONAPI 0x00010000
+#define MPUI_CTRL_BYTESWAP_ALL 0x00020000
+#define MPUI_CTRL_BYTESWAP_API 0x00030000
+#define MPUI_CTRL_TIMEOUT_MASK 0x0000ff00
+#define MPUI_CTRL_APIF_HNSTB_DIV_MASK 0x000000f0
+#define MPUI_CTRL_S_NABORT_GL 0x00000008
+#define MPUI_CTRL_S_NABORT_32BIT 0x00000004
+#define MPUI_CTRL_EN_TIMEOUT 0x00000002
+#define MPUI_CTRL_HF_MCUCLK 0x00000001
+#define DSP_BOOT_CONFIG_DIRECT 0x00000000
+#define DSP_BOOT_CONFIG_PSD_DIRECT 0x00000001
+#define DSP_BOOT_CONFIG_IDLE 0x00000002
+#define DSP_BOOT_CONFIG_DL16 0x00000003
+#define DSP_BOOT_CONFIG_DL32 0x00000004
+#define DSP_BOOT_CONFIG_MPUI 0x00000005
+#define DSP_BOOT_CONFIG_INTERNAL 0x00000006
+
+/*
+ * DSP boot mode
+ * direct: 0xffff00
+ * pseudo direct: 0x080000
+ * MPUI: branch 0x010000
+ * internel: branch 0x024000
+ */
+#define DSP_BOOT_ADR_DIRECT 0xffff00
+#define DSP_BOOT_ADR_PSD_DIRECT 0x080000
+#define DSP_BOOT_ADR_MPUI 0x010000
+#define DSP_BOOT_ADR_INTERNAL 0x024000
+
+/*
+ * TC
+ */
+#define TC_ENDIANISM_SWAP 0x00000002
+#define TC_ENDIANISM_SWAP_WORD 0x00000002
+#define TC_ENDIANISM_SWAP_BYTE 0x00000000
+#define TC_ENDIANISM_EN 0x00000001
+
+/*
+ * DSP ICR
+ */
+#define DSPREG_ICR_RESERVED_BITS 0xffc0
+#define DSPREG_ICR_EMIF 0x0020
+#define DSPREG_ICR_DPLL 0x0010
+#define DSPREG_ICR_PER 0x0008
+#define DSPREG_ICR_CACHE 0x0004
+#define DSPREG_ICR_DMA 0x0002
+#define DSPREG_ICR_CPU 0x0001
+
+#endif /* __OMAP_DSP_OMAP1_DSP_H */
diff --git a/drivers/dsp/dspgateway/omap2_dsp.h b/drivers/dsp/dspgateway/omap2_dsp.h
new file mode 100644
index 0000000..0dc43f0
--- /dev/null
+++ b/drivers/dsp/dspgateway/omap2_dsp.h
@@ -0,0 +1,95 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_DSP_OMAP2_DSP_H
+#define __OMAP_DSP_OMAP2_DSP_H
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define OMAP24XX_DARAM_BASE (DSP_MEM_24XX_VIRT + 0x0)
+#define OMAP24XX_DARAM_SIZE 0x10000
+#define OMAP24XX_SARAM_BASE (DSP_MEM_24XX_VIRT + 0x10000)
+#define OMAP24XX_SARAM_SIZE 0x18000
+#endif
+
+#include <asm/arch/hardware.h>
+
+/*
+ * DSP IPI registers: mapped to 0xe1000000 -- use readX(), writeX()
+ */
+#ifdef CONFIG_ARCH_OMAP24XX
+#define DSP_IPI_BASE DSP_IPI_24XX_VIRT
+#endif
+
+#ifdef CONFIG_ARCH_OMAP34XX
+#define DSP_IPI_BASE DSP_IPI_34XX_VIRT
+#endif
+
+#define DSP_IPI_REVISION (DSP_IPI_BASE + 0x00)
+#define DSP_IPI_SYSCONFIG (DSP_IPI_BASE + 0x10)
+#define DSP_IPI_INDEX (DSP_IPI_BASE + 0x40)
+#define DSP_IPI_ENTRY (DSP_IPI_BASE + 0x44)
+#define DSP_IPI_ENABLE (DSP_IPI_BASE + 0x48)
+#define DSP_IPI_IOMAP (DSP_IPI_BASE + 0x4c)
+#define DSP_IPI_DSPBOOTCONFIG (DSP_IPI_BASE + 0x50)
+
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_MASK 0x00000003
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_8 0x00000000
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_16 0x00000001
+#define DSP_IPI_ENTRY_ELMSIZEVALUE_32 0x00000002
+
+#define DSP_BOOT_CONFIG_DIRECT 0x00000000
+#define DSP_BOOT_CONFIG_PSD_DIRECT 0x00000001
+#define DSP_BOOT_CONFIG_IDLE 0x00000002
+#define DSP_BOOT_CONFIG_DL16 0x00000003
+#define DSP_BOOT_CONFIG_DL32 0x00000004
+#define DSP_BOOT_CONFIG_API 0x00000005
+#define DSP_BOOT_CONFIG_INTERNAL 0x00000006
+
+/*
+ * DSP boot mode
+ * direct: 0xffff00
+ * pseudo direct: 0x080000
+ * API: branch 0x010000
+ * internel: branch 0x024000
+ */
+#define DSP_BOOT_ADR_DIRECT 0xffff00
+#define DSP_BOOT_ADR_PSD_DIRECT 0x080000
+#define DSP_BOOT_ADR_API 0x010000
+#define DSP_BOOT_ADR_INTERNAL 0x024000
+
+/*
+ * DSP ICR
+ */
+#define DSPREG_ICR_RESERVED_BITS 0xfc00
+#define DSPREG_ICR_HWA 0x0200
+#define DSPREG_ICR_IPORT 0x0100
+#define DSPREG_ICR_MPORT 0x0080
+#define DSPREG_ICR_XPORT 0x0040
+#define DSPREG_ICR_DPORT 0x0020
+#define DSPREG_ICR_DPLL 0x0010
+#define DSPREG_ICR_PER 0x0008
+#define DSPREG_ICR_CACHE 0x0004
+#define DSPREG_ICR_DMA 0x0002
+#define DSPREG_ICR_CPU 0x0001
+
+#endif /* __OMAP_DSP_OMAP2_DSP_H */
diff --git a/drivers/dsp/dspgateway/proclist.h b/drivers/dsp/dspgateway/proclist.h
new file mode 100644
index 0000000..666ca4d
--- /dev/null
+++ b/drivers/dsp/dspgateway/proclist.h
@@ -0,0 +1,87 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __PLAT_OMAP_DSP_PROCLIST_H
+#define __PLAT_OMAP_DSP_PROCLIST_H
+
+struct proc_list {
+ struct list_head list_head;
+ pid_t pid;
+ struct file *file;
+};
+
+static inline int proc_list_add(spinlock_t *lock, struct list_head *list,
+ struct task_struct *tsk, struct file *file)
+{
+ struct proc_list *new;
+
+ new = kmalloc(sizeof(struct proc_list), GFP_KERNEL);
+ if (new == NULL)
+ return -ENOMEM;
+ new->pid = tsk->pid;
+ new->file = file;
+ spin_lock(lock);
+ list_add_tail(&new->list_head, list);
+ spin_unlock(lock);
+
+ return 0;
+}
+
+static inline void proc_list_del(spinlock_t *lock, struct list_head *list,
+ struct task_struct *tsk, struct file *file)
+{
+ struct proc_list *pl;
+
+ spin_lock(lock);
+ list_for_each_entry(pl, list, list_head) {
+ if (pl->file == file) {
+ list_del(&pl->list_head);
+ kfree(pl);
+ spin_unlock(lock);
+ return;
+ }
+ }
+
+ /* correspinding file struct isn't found in the list ??? */
+ printk(KERN_ERR "proc_list_del(): proc_list is inconsistent!\n"
+ "struct file (%p) not found\n", file);
+ printk(KERN_ERR "listing proc_list...\n");
+ list_for_each_entry(pl, list, list_head)
+ printk(KERN_ERR " pid:%d file:%p\n", pl->pid, pl->file);
+ spin_unlock(lock);
+}
+
+static inline void proc_list_flush(spinlock_t *lock, struct list_head *list)
+{
+ struct proc_list *pl;
+
+ spin_lock(lock);
+ while (!list_empty(list)) {
+ pl = list_entry(list->next, struct proc_list, list_head);
+ list_del(&pl->list_head);
+ kfree(pl);
+ }
+ spin_unlock(lock);
+}
+
+#endif /* __PLAT_OMAP_DSP_PROCLIST_H */
diff --git a/drivers/dsp/dspgateway/task.c b/drivers/dsp/dspgateway/task.c
new file mode 100644
index 0000000..e5ee8e0
--- /dev/null
+++ b/drivers/dsp/dspgateway/task.c
@@ -0,0 +1,3042 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/kfifo.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/arch/mailbox.h>
+#include <asm/arch/dsp.h>
+#include "uaccess_dsp.h"
+#include "dsp_mbcmd.h"
+#include "dsp.h"
+#include "ipbuf.h"
+#include "proclist.h"
+
+/*
+ * devstate: task device state machine
+ * NOTASK: task is not attached.
+ * ATTACHED: task is attached.
+ * GARBAGE: task is detached. waiting for all processes to close this device.
+ * ADDREQ: requesting for tadd
+ * DELREQ: requesting for tdel. no process is opening this device.
+ * FREEZED: task is attached, but reserved to be killed.
+ * ADDFAIL: tadd failed.
+ * ADDING: tadd in process.
+ * DELING: tdel in process.
+ * KILLING: tkill in process.
+ */
+#define TASKDEV_ST_NOTASK 0x00000001
+#define TASKDEV_ST_ATTACHED 0x00000002
+#define TASKDEV_ST_GARBAGE 0x00000004
+#define TASKDEV_ST_INVALID 0x00000008
+#define TASKDEV_ST_ADDREQ 0x00000100
+#define TASKDEV_ST_DELREQ 0x00000200
+#define TASKDEV_ST_FREEZED 0x00000400
+#define TASKDEV_ST_ADDFAIL 0x00001000
+#define TASKDEV_ST_ADDING 0x00010000
+#define TASKDEV_ST_DELING 0x00020000
+#define TASKDEV_ST_KILLING 0x00040000
+#define TASKDEV_ST_STATE_MASK 0x7fffffff
+#define TASKDEV_ST_STALE 0x80000000
+
+static struct {
+ long state;
+ char *name;
+} devstate_desc[] = {
+ { TASKDEV_ST_NOTASK, "notask" },
+ { TASKDEV_ST_ATTACHED, "attached" },
+ { TASKDEV_ST_GARBAGE, "garbage" },
+ { TASKDEV_ST_INVALID, "invalid" },
+ { TASKDEV_ST_ADDREQ, "addreq" },
+ { TASKDEV_ST_DELREQ, "delreq" },
+ { TASKDEV_ST_FREEZED, "freezed" },
+ { TASKDEV_ST_ADDFAIL, "addfail" },
+ { TASKDEV_ST_ADDING, "adding" },
+ { TASKDEV_ST_DELING, "deling" },
+ { TASKDEV_ST_KILLING, "killing" },
+};
+
+static char *devstate_name(long state)
+{
+ int i;
+ int max = ARRAY_SIZE(devstate_desc);
+
+ for (i = 0; i < max; i++) {
+ if (state & devstate_desc[i].state)
+ return devstate_desc[i].name;
+ }
+ return "unknown";
+}
+
+struct rcvdt_bk_struct {
+ struct ipblink link;
+ unsigned int rp;
+};
+
+struct taskdev {
+ struct bus_type *bus;
+ struct device dev; /* Generic device interface */
+
+ long state;
+ struct rw_semaphore state_sem;
+ wait_queue_head_t state_wait_q;
+ struct mutex usecount_lock;
+ unsigned int usecount;
+ char name[TNM_LEN];
+ struct file_operations fops;
+ spinlock_t proc_list_lock;
+ struct list_head proc_list;
+ struct dsptask *task;
+
+ /* read stuff */
+ wait_queue_head_t read_wait_q;
+ struct mutex read_mutex;
+ spinlock_t read_lock;
+ union {
+ struct kfifo *fifo; /* for active word */
+ struct rcvdt_bk_struct bk;
+ } rcvdt;
+
+ /* write stuff */
+ wait_queue_head_t write_wait_q;
+ struct mutex write_mutex;
+ spinlock_t wsz_lock;
+ size_t wsz;
+
+ /* tctl stuff */
+ wait_queue_head_t tctl_wait_q;
+ struct mutex tctl_mutex;
+ int tctl_stat;
+ int tctl_ret; /* return value for tctl_show() */
+
+ /* device lock */
+ struct mutex lock;
+ pid_t lock_pid;
+};
+
+#define to_taskdev(n) container_of(n, struct taskdev, dev)
+
+struct dsptask {
+ enum {
+ TASK_ST_ERR = 0,
+ TASK_ST_READY,
+ TASK_ST_CFGREQ
+ } state;
+ u8 tid;
+ char name[TNM_LEN];
+ u16 ttyp;
+ struct taskdev *dev;
+
+ /* read stuff */
+ struct ipbuf_p *ipbuf_pvt_r;
+
+ /* write stuff */
+ struct ipbuf_p *ipbuf_pvt_w;
+
+ /* mmap stuff */
+ void *map_base;
+ size_t map_length;
+};
+
+#define sndtyp_acv(ttyp) ((ttyp) & TTYP_ASND)
+#define sndtyp_psv(ttyp) (!((ttyp) & TTYP_ASND))
+#define sndtyp_bk(ttyp) ((ttyp) & TTYP_BKDM)
+#define sndtyp_wd(ttyp) (!((ttyp) & TTYP_BKDM))
+#define sndtyp_pvt(ttyp) ((ttyp) & TTYP_PVDM)
+#define sndtyp_gbl(ttyp) (!((ttyp) & TTYP_PVDM))
+#define rcvtyp_acv(ttyp) ((ttyp) & TTYP_ARCV)
+#define rcvtyp_psv(ttyp) (!((ttyp) & TTYP_ARCV))
+#define rcvtyp_bk(ttyp) ((ttyp) & TTYP_BKMD)
+#define rcvtyp_wd(ttyp) (!((ttyp) & TTYP_BKMD))
+#define rcvtyp_pvt(ttyp) ((ttyp) & TTYP_PVMD)
+#define rcvtyp_gbl(ttyp) (!((ttyp) & TTYP_PVMD))
+
+static inline int has_taskdev_lock(struct taskdev *dev);
+static int dsp_rmdev_minor(unsigned char minor);
+static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor);
+static void taskdev_delete(unsigned char minor);
+static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task);
+static int dsp_tdel_bh(struct taskdev *dev, u16 type);
+
+static struct bus_type dsptask_bus = {
+ .name = "dsptask",
+};
+
+static struct class *dsp_task_class;
+static DEFINE_MUTEX(devmgr_lock);
+static struct taskdev *taskdev[TASKDEV_MAX];
+static struct dsptask *dsptask[TASKDEV_MAX];
+static DEFINE_MUTEX(cfg_lock);
+static u16 cfg_cmd;
+static u8 cfg_tid;
+static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q);
+static u8 n_task; /* static task count */
+static void *heap;
+
+#define is_dynamic_task(tid) ((tid) >= n_task)
+
+#define devstate_read_lock(dev, devstate) \
+ devstate_read_lock_timeout(dev, devstate, 0)
+#define devstate_read_unlock(dev) up_read(&(dev)->state_sem)
+#define devstate_write_lock(dev, devstate) \
+ devstate_write_lock_timeout(dev, devstate, 0)
+#define devstate_write_unlock(dev) up_write(&(dev)->state_sem)
+
+static ssize_t devname_show(struct device *d, struct device_attribute *attr,
+ char *buf);
+static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
+ char *buf);
+static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
+ char *buf);
+static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
+ char *buf);
+static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
+ char *buf);
+static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
+ char *buf);
+static int fifosz_store(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count);
+static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
+ char *buf);
+static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
+ char *buf);
+static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
+ char *buf);
+static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
+ char *buf);
+
+#define __ATTR_RW(_name,_mode) { \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
+ .show = _name##_show, \
+ .store = _name##_store, \
+}
+
+static struct device_attribute dev_attr_devname = __ATTR_RO(devname);
+static struct device_attribute dev_attr_devstate = __ATTR_RO(devstate);
+static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list);
+static struct device_attribute dev_attr_taskname = __ATTR_RO(taskname);
+static struct device_attribute dev_attr_ttyp = __ATTR_RO(ttyp);
+static struct device_attribute dev_attr_fifosz = __ATTR_RW(fifosz, 0666);
+static struct device_attribute dev_attr_fifocnt = __ATTR_RO(fifocnt);
+static struct device_attribute dev_attr_ipblink = __ATTR_RO(ipblink);
+static struct device_attribute dev_attr_wsz = __ATTR_RO(wsz);
+static struct device_attribute dev_attr_mmap = __ATTR_RO(mmap);
+
+static inline void set_taskdev_state(struct taskdev *dev, int state)
+{
+ pr_debug("omapdsp: devstate: CHANGE %s[%d]:\"%s\"->\"%s\"\n",
+ dev->name,
+ (dev->task ? dev->task->tid : -1),
+ devstate_name(dev->state),
+ devstate_name(state));
+ dev->state = state;
+}
+
+/*
+ * devstate_read_lock_timeout()
+ * devstate_write_lock_timeout():
+ * timeout != 0: dev->state can be diffeent from what you want.
+ * timeout == 0: no timeout
+ */
+#define BUILD_DEVSTATE_LOCK_TIMEOUT(rw) \
+static int devstate_##rw##_lock_timeout(struct taskdev *dev, long devstate, \
+ int timeout) \
+{ \
+ DEFINE_WAIT(wait); \
+ down_##rw(&dev->state_sem); \
+ while (!(dev->state & devstate)) { \
+ up_##rw(&dev->state_sem); \
+ prepare_to_wait(&dev->state_wait_q, &wait, TASK_INTERRUPTIBLE); \
+ if (!timeout) \
+ timeout = MAX_SCHEDULE_TIMEOUT; \
+ timeout = schedule_timeout(timeout); \
+ finish_wait(&dev->state_wait_q, &wait); \
+ if (timeout == 0) \
+ return -ETIME; \
+ if (signal_pending(current)) \
+ return -EINTR; \
+ down_##rw(&dev->state_sem); \
+ } \
+ return 0; \
+}
+BUILD_DEVSTATE_LOCK_TIMEOUT(read)
+BUILD_DEVSTATE_LOCK_TIMEOUT(write)
+
+#define BUILD_DEVSTATE_LOCK_AND_TEST(rw) \
+static int devstate_##rw##_lock_and_test(struct taskdev *dev, long devstate) \
+{ \
+ down_##rw(&dev->state_sem); \
+ if (dev->state & devstate) \
+ return 1; /* success */ \
+ /* failure */ \
+ up_##rw(&dev->state_sem); \
+ return 0; \
+}
+BUILD_DEVSTATE_LOCK_AND_TEST(read)
+BUILD_DEVSTATE_LOCK_AND_TEST(write)
+
+static int taskdev_lock_interruptible(struct taskdev *dev,
+ struct mutex *lock)
+{
+ int ret;
+
+ if (has_taskdev_lock(dev))
+ ret = mutex_lock_interruptible(lock);
+ else {
+ if ((ret = mutex_lock_interruptible(&dev->lock)) != 0)
+ return ret;
+ ret = mutex_lock_interruptible(lock);
+ mutex_unlock(&dev->lock);
+ }
+
+ return ret;
+}
+
+static int taskdev_lock_and_statelock_attached(struct taskdev *dev,
+ struct mutex *lock)
+{
+ int ret;
+
+ if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+ return -ENODEV;
+
+ if ((ret = taskdev_lock_interruptible(dev, lock)) != 0)
+ devstate_read_unlock(dev);
+
+ return ret;
+}
+
+static inline void taskdev_unlock_and_stateunlock(struct taskdev *dev,
+ struct mutex *lock)
+{
+ mutex_unlock(lock);
+ devstate_read_unlock(dev);
+}
+
+/*
+ * taskdev_flush_buf()
+ * must be called under state_lock(ATTACHED) and dev->read_mutex.
+ */
+static int taskdev_flush_buf(struct taskdev *dev)
+{
+ u16 ttyp = dev->task->ttyp;
+
+ if (sndtyp_wd(ttyp)) {
+ /* word receiving */
+ kfifo_reset(dev->rcvdt.fifo);
+ } else {
+ /* block receiving */
+ struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
+
+ if (sndtyp_gbl(ttyp))
+ ipblink_flush(&rcvdt->link);
+ else {
+ ipblink_flush_pvt(&rcvdt->link);
+ release_ipbuf_pvt(dev->task->ipbuf_pvt_r);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * taskdev_set_fifosz()
+ * must be called under dev->read_mutex.
+ */
+static int taskdev_set_fifosz(struct taskdev *dev, unsigned long sz)
+{
+ u16 ttyp = dev->task->ttyp;
+
+ if (!(sndtyp_wd(ttyp) && sndtyp_acv(ttyp))) {
+ printk(KERN_ERR
+ "omapdsp: buffer size can be changed only for "
+ "active word sending task.\n");
+ return -EINVAL;
+ }
+ if ((sz == 0) || (sz & 1)) {
+ printk(KERN_ERR "omapdsp: illegal buffer size! (%ld)\n"
+ "it must be even and non-zero value.\n", sz);
+ return -EINVAL;
+ }
+
+ if (kfifo_len(dev->rcvdt.fifo)) {
+ printk(KERN_ERR "omapdsp: buffer is not empty!\n");
+ return -EIO;
+ }
+
+ kfifo_free(dev->rcvdt.fifo);
+ dev->rcvdt.fifo = kfifo_alloc(sz, GFP_KERNEL, &dev->read_lock);
+ if (IS_ERR(dev->rcvdt.fifo)) {
+ printk(KERN_ERR
+ "omapdsp: unable to change receive buffer size. "
+ "(%ld bytes for %s)\n", sz, dev->name);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static inline int has_taskdev_lock(struct taskdev *dev)
+{
+ return (dev->lock_pid == current->pid);
+}
+
+static int taskdev_lock(struct taskdev *dev)
+{
+ if (mutex_lock_interruptible(&dev->lock))
+ return -EINTR;
+ dev->lock_pid = current->pid;
+ return 0;
+}
+
+static int taskdev_unlock(struct taskdev *dev)
+{
+ if (!has_taskdev_lock(dev)) {
+ printk(KERN_ERR
+ "omapdsp: an illegal process attempted to "
+ "unlock the dsptask lock!\n");
+ return -EINVAL;
+ }
+ dev->lock_pid = 0;
+ mutex_unlock(&dev->lock);
+ return 0;
+}
+
+static int dsp_task_config(struct dsptask *task, u8 tid)
+{
+ u16 ttyp;
+ int ret;
+
+ task->tid = tid;
+ dsptask[tid] = task;
+
+ /* TCFG request */
+ task->state = TASK_ST_CFGREQ;
+ if (mutex_lock_interruptible(&cfg_lock)) {
+ ret = -EINTR;
+ goto fail_out;
+ }
+ cfg_cmd = MBOX_CMD_DSP_TCFG;
+ mbcompose_send_and_wait(TCFG, tid, 0, &cfg_wait_q);
+ cfg_cmd = 0;
+ mutex_unlock(&cfg_lock);
+
+ if (task->state != TASK_ST_READY) {
+ printk(KERN_ERR "omapdsp: task %d configuration error!\n", tid);
+ ret = -EINVAL;
+ goto fail_out;
+ }
+
+ if (strlen(task->name) <= 1)
+ sprintf(task->name, "%d", tid);
+ pr_info("omapdsp: task %d: name %s\n", tid, task->name);
+
+ ttyp = task->ttyp;
+
+ /*
+ * task info sanity check
+ */
+
+ /* task type check */
+ if (rcvtyp_psv(ttyp) && rcvtyp_pvt(ttyp)) {
+ 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) &&
+ (ipbuf_p_validate(task->ipbuf_pvt_r, DIR_D2A) < 0)) {
+ ret = -EINVAL;
+ goto fail_out;
+ }
+ 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) &&
+ ((!ALIGN((unsigned long)task->map_base, PAGE_SIZE)) ||
+ (!ALIGN(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;
+ }
+
+ return 0;
+
+fail_out:
+ dsptask[tid] = NULL;
+ return ret;
+}
+
+static void dsp_task_init(struct dsptask *task)
+{
+ mbcompose_send(TCTL, task->tid, TCTL_TINIT);
+}
+
+int dsp_task_config_all(u8 n)
+{
+ int i, ret;
+ struct taskdev *devheap;
+ struct dsptask *taskheap;
+ size_t devheapsz, taskheapsz;
+
+ pr_info("omapdsp: found %d task(s)\n", n);
+ if (n == 0)
+ return 0;
+
+ /*
+ * reducing kmalloc!
+ */
+ devheapsz = sizeof(struct taskdev) * n;
+ taskheapsz = sizeof(struct dsptask) * n;
+ heap = kzalloc(devheapsz + taskheapsz, GFP_KERNEL);
+ if (heap == NULL)
+ return -ENOMEM;
+ devheap = heap;
+ taskheap = heap + devheapsz;
+
+ n_task = n;
+ for (i = 0; i < n; i++) {
+ struct taskdev *dev = &devheap[i];
+ struct dsptask *task = &taskheap[i];
+
+ if ((ret = dsp_task_config(task, i)) < 0)
+ return ret;
+ if ((ret = taskdev_init(dev, task->name, i)) < 0)
+ return ret;
+ if ((ret = taskdev_attach_task(dev, task)) < 0)
+ return ret;
+ dsp_task_init(task);
+ pr_info("omapdsp: taskdev %s enabled.\n", dev->name);
+ }
+
+ return 0;
+}
+
+static void dsp_task_unconfig(struct dsptask *task)
+{
+ dsptask[task->tid] = NULL;
+}
+
+void dsp_task_unconfig_all(void)
+{
+ unsigned char minor;
+ u8 tid;
+ struct dsptask *task;
+
+ for (minor = 0; minor < n_task; minor++) {
+ /*
+ * taskdev[minor] can be NULL in case of
+ * configuration failure
+ */
+ if (taskdev[minor])
+ taskdev_delete(minor);
+ }
+ for (; minor < TASKDEV_MAX; minor++) {
+ if (taskdev[minor])
+ dsp_rmdev_minor(minor);
+ }
+
+ for (tid = 0; tid < n_task; tid++) {
+ /*
+ * dsptask[tid] can be NULL in case of
+ * configuration failure
+ */
+ task = dsptask[tid];
+ if (task)
+ dsp_task_unconfig(task);
+ }
+ for (; tid < TASKDEV_MAX; tid++) {
+ task = dsptask[tid];
+ if (task) {
+ /*
+ * on-demand tasks should be deleted in
+ * rmdev_minor(), but just in case.
+ */
+ dsp_task_unconfig(task);
+ kfree(task);
+ }
+ }
+
+ if (heap) {
+ kfree(heap);
+ heap = NULL;
+ }
+
+ n_task = 0;
+}
+
+static struct device_driver dsptask_driver = {
+ .name = "dsptask",
+ .bus = &dsptask_bus,
+};
+
+u8 dsp_task_count(void)
+{
+ return n_task;
+}
+
+int dsp_taskmod_busy(void)
+{
+ struct taskdev *dev;
+ unsigned char minor;
+ unsigned int usecount;
+
+ for (minor = 0; minor < TASKDEV_MAX; minor++) {
+ dev = taskdev[minor];
+ if (dev == NULL)
+ continue;
+ if ((usecount = dev->usecount) > 0) {
+ printk("dsp_taskmod_busy(): %s: usecount=%d\n",
+ dev->name, usecount);
+ return 1;
+ }
+/*
+ if ((dev->state & (TASKDEV_ST_ADDREQ |
+ TASKDEV_ST_DELREQ)) {
+*/
+ if (dev->state & TASKDEV_ST_ADDREQ) {
+ printk("dsp_taskmod_busy(): %s is in %s\n",
+ dev->name, devstate_name(dev->state));
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * DSP task device file operations
+ */
+static ssize_t dsp_task_read_wd_acv(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+ int ret = 0;
+ DEFINE_WAIT(wait);
+
+ if (count == 0) {
+ return 0;
+ } else if (count & 0x1) {
+ printk(KERN_ERR
+ "omapdsp: odd count is illegal for DSP task device.\n");
+ return -EINVAL;
+ }
+
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
+
+
+ prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE);
+ if (kfifo_len(dev->rcvdt.fifo) == 0)
+ schedule();
+ finish_wait(&dev->read_wait_q, &wait);
+ if (kfifo_len(dev->rcvdt.fifo) == 0) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
+ goto up_out;
+ }
+
+
+ ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count);
+
+ up_out:
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+ return ret;
+}
+
+static ssize_t dsp_task_read_bk_acv(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+ struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
+ ssize_t ret = 0;
+ DEFINE_WAIT(wait);
+
+ if (count == 0) {
+ return 0;
+ } else if (count & 0x1) {
+ printk(KERN_ERR
+ "omapdsp: odd count is illegal for DSP task device.\n");
+ return -EINVAL;
+ } else if ((int)buf & 0x1) {
+ printk(KERN_ERR
+ "omapdsp: buf should be word aligned for "
+ "dsp_task_read().\n");
+ return -EINVAL;
+ }
+
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
+
+ prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE);
+ if (ipblink_empty(&rcvdt->link))
+ schedule();
+ finish_wait(&dev->read_wait_q, &wait);
+ if (ipblink_empty(&rcvdt->link)) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
+ goto up_out;
+ }
+
+ /* copy from delayed IPBUF */
+ if (sndtyp_pvt(dev->task->ttyp)) {
+ /* private */
+ if (!ipblink_empty(&rcvdt->link)) {
+ struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
+ unsigned char *base, *src;
+ size_t bkcnt;
+
+ if (dsp_mem_enable(ipbp) < 0) {
+ ret = -EBUSY;
+ goto up_out;
+ }
+ 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 = -EINVAL;
+ goto pv_out1;
+ }
+ if (dsp_mem_enable(base) < 0) {
+ ret = -EBUSY;
+ goto pv_out1;
+ }
+ src = base + rcvdt->rp;
+ if (bkcnt > count) {
+ if (copy_to_user_dsp(buf, src, count)) {
+ ret = -EFAULT;
+ goto pv_out2;
+ }
+ ret = count;
+ rcvdt->rp += count;
+ } else {
+ if (copy_to_user_dsp(buf, src, bkcnt)) {
+ ret = -EFAULT;
+ goto pv_out2;
+ }
+ ret = bkcnt;
+ ipblink_del_pvt(&rcvdt->link);
+ release_ipbuf_pvt(ipbp);
+ rcvdt->rp = 0;
+ }
+ pv_out2:
+ dsp_mem_disable(src);
+ pv_out1:
+ dsp_mem_disable(ipbp);
+ }
+ } else {
+ /* global */
+ if (dsp_mem_enable_ipbuf() < 0) {
+ ret = -EBUSY;
+ goto up_out;
+ }
+ while (!ipblink_empty(&rcvdt->link)) {
+ unsigned char *src;
+ size_t bkcnt;
+ struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
+
+ src = ipb_h->p->d + rcvdt->rp;
+ bkcnt = ((unsigned long)ipb_h->p->c) * 2 - rcvdt->rp;
+ if (bkcnt > count) {
+ if (copy_to_user_dsp(buf, src, count)) {
+ ret = -EFAULT;
+ goto gb_out;
+ }
+ ret += count;
+ rcvdt->rp += count;
+ break;
+ } else {
+ if (copy_to_user_dsp(buf, src, bkcnt)) {
+ ret = -EFAULT;
+ goto gb_out;
+ }
+ ret += bkcnt;
+ buf += bkcnt;
+ count -= bkcnt;
+ ipblink_del_top(&rcvdt->link);
+ unuse_ipbuf(ipb_h);
+ rcvdt->rp = 0;
+ }
+ }
+ gb_out:
+ dsp_mem_disable_ipbuf();
+ }
+
+ up_out:
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+ return ret;
+}
+
+static ssize_t dsp_task_read_wd_psv(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+ int ret = 0;
+
+ if (count == 0) {
+ return 0;
+ } else if (count & 0x1) {
+ printk(KERN_ERR
+ "omapdsp: odd count is illegal for DSP task device.\n");
+ return -EINVAL;
+ } else {
+ /* force! */
+ count = 2;
+ }
+
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
+
+ mbcompose_send_and_wait(WDREQ, dev->task->tid, 0, &dev->read_wait_q);
+
+ if (kfifo_len(dev->rcvdt.fifo) == 0) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
+ goto up_out;
+ }
+
+ ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count);
+
+up_out:
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+ return ret;
+}
+
+static ssize_t dsp_task_read_bk_psv(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+ struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk;
+ int ret = 0;
+
+ if (count == 0) {
+ return 0;
+ } else if (count & 0x1) {
+ printk(KERN_ERR
+ "omapdsp: odd count is illegal for DSP task device.\n");
+ return -EINVAL;
+ } else if ((int)buf & 0x1) {
+ printk(KERN_ERR
+ "omapdsp: buf should be word aligned for "
+ "dsp_task_read().\n");
+ return -EINVAL;
+ }
+
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
+
+ mbcompose_send_and_wait(BKREQ, dev->task->tid, count/2,
+ &dev->read_wait_q);
+
+ if (ipblink_empty(&rcvdt->link)) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
+ goto up_out;
+ }
+
+ /*
+ * We will not receive more than requested count.
+ */
+ if (sndtyp_pvt(dev->task->ttyp)) {
+ /* private */
+ struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r;
+ size_t rcvcnt;
+ void *src;
+
+ if (dsp_mem_enable(ipbp) < 0) {
+ ret = -EBUSY;
+ goto up_out;
+ }
+ src = MKVIRT(ipbp->ah, ipbp->al);
+ rcvcnt = ((unsigned long)ipbp->c) * 2;
+ if (dsp_address_validate(src, rcvcnt, "task %s read buffer",
+ dev->task->name) < 0) {
+ ret = -EINVAL;
+ goto pv_out1;
+ }
+ if (dsp_mem_enable(src) < 0) {
+ ret = -EBUSY;
+ goto pv_out1;
+ }
+ if (count > rcvcnt)
+ count = rcvcnt;
+ if (copy_to_user_dsp(buf, src, count)) {
+ ret = -EFAULT;
+ goto pv_out2;
+ }
+ ipblink_del_pvt(&rcvdt->link);
+ release_ipbuf_pvt(ipbp);
+ ret = count;
+pv_out2:
+ dsp_mem_disable(src);
+pv_out1:
+ dsp_mem_disable(ipbp);
+ } else {
+ /* global */
+ struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top);
+ size_t rcvcnt;
+
+ if (dsp_mem_enable_ipbuf() < 0) {
+ ret = -EBUSY;
+ goto up_out;
+ }
+ rcvcnt = ((unsigned long)ipb_h->p->c) * 2;
+ if (count > rcvcnt)
+ count = rcvcnt;
+ if (copy_to_user_dsp(buf, ipb_h->p->d, count)) {
+ ret = -EFAULT;
+ goto gb_out;
+ }
+ ipblink_del_top(&rcvdt->link);
+ unuse_ipbuf(ipb_h);
+ ret = count;
+gb_out:
+ dsp_mem_disable_ipbuf();
+ }
+
+up_out:
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+ return ret;
+}
+
+static ssize_t dsp_task_write_wd(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+ u16 wd;
+ int ret = 0;
+ DEFINE_WAIT(wait);
+
+ if (count == 0) {
+ return 0;
+ } else if (count & 0x1) {
+ printk(KERN_ERR
+ "omapdsp: odd count is illegal for DSP task device.\n");
+ return -EINVAL;
+ } else {
+ /* force! */
+ count = 2;
+ }
+
+ if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
+ return -ENODEV;
+
+ prepare_to_wait(&dev->write_wait_q, &wait, TASK_INTERRUPTIBLE);
+ if (dev->wsz == 0)
+ schedule();
+ finish_wait(&dev->write_wait_q, &wait);
+ if (dev->wsz == 0) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
+ goto up_out;
+ }
+
+ if (copy_from_user(&wd, buf, count)) {
+ ret = -EFAULT;
+ goto up_out;
+ }
+
+ spin_lock(&dev->wsz_lock);
+ if (mbcompose_send(WDSND, dev->task->tid, wd) < 0) {
+ spin_unlock(&dev->wsz_lock);
+ goto up_out;
+ }
+ ret = count;
+ if (rcvtyp_acv(dev->task->ttyp))
+ dev->wsz = 0;
+ spin_unlock(&dev->wsz_lock);
+
+ up_out:
+ taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
+ return ret;
+}
+
+static ssize_t dsp_task_write_bk(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+ int ret = 0;
+ DEFINE_WAIT(wait);
+
+ if (count == 0) {
+ return 0;
+ } else if (count & 0x1) {
+ printk(KERN_ERR
+ "omapdsp: odd count is illegal for DSP task device.\n");
+ return -EINVAL;
+ } else if ((int)buf & 0x1) {
+ printk(KERN_ERR
+ "omapdsp: buf should be word aligned for "
+ "dsp_task_write().\n");
+ return -EINVAL;
+ }
+
+ if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex))
+ return -ENODEV;
+
+ prepare_to_wait(&dev->write_wait_q, &wait, TASK_INTERRUPTIBLE);
+ if (dev->wsz == 0)
+ schedule();
+ finish_wait(&dev->write_wait_q, &wait);
+ if (dev->wsz == 0) {
+ /* failure */
+ if (signal_pending(current))
+ ret = -EINTR;
+ goto up_out;
+ }
+
+ if (count > dev->wsz)
+ count = dev->wsz;
+
+ if (rcvtyp_pvt(dev->task->ttyp)) {
+ /* private */
+ struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_w;
+ unsigned char *dst;
+
+ if (dsp_mem_enable(ipbp) < 0) {
+ ret = -EBUSY;
+ goto up_out;
+ }
+ dst = MKVIRT(ipbp->ah, ipbp->al);
+ if (dsp_address_validate(dst, count, "task %s write buffer",
+ dev->task->name) < 0) {
+ ret = -EINVAL;
+ goto pv_out1;
+ }
+ if (dsp_mem_enable(dst) < 0) {
+ ret = -EBUSY;
+ goto pv_out1;
+ }
+ if (copy_from_user_dsp(dst, buf, count)) {
+ ret = -EFAULT;
+ goto pv_out2;
+ }
+ ipbp->c = count/2;
+ ipbp->s = dev->task->tid;
+ spin_lock(&dev->wsz_lock);
+ if (mbcompose_send(BKSNDP, dev->task->tid, 0) == 0) {
+ if (rcvtyp_acv(dev->task->ttyp))
+ dev->wsz = 0;
+ ret = count;
+ }
+ spin_unlock(&dev->wsz_lock);
+ pv_out2:
+ dsp_mem_disable(dst);
+ pv_out1:
+ dsp_mem_disable(ipbp);
+ } else {
+ /* global */
+ struct ipbuf_head *ipb_h;
+
+ if (dsp_mem_enable_ipbuf() < 0) {
+ ret = -EBUSY;
+ goto up_out;
+ }
+ if ((ipb_h = get_free_ipbuf(dev->task->tid)) == NULL)
+ goto gb_out;
+ if (copy_from_user_dsp(ipb_h->p->d, buf, count)) {
+ release_ipbuf(ipb_h);
+ ret = -EFAULT;
+ goto gb_out;
+ }
+ ipb_h->p->c = count/2;
+ ipb_h->p->sa = dev->task->tid;
+ spin_lock(&dev->wsz_lock);
+ if (mbcompose_send(BKSND, dev->task->tid, ipb_h->bid) == 0) {
+ if (rcvtyp_acv(dev->task->ttyp))
+ dev->wsz = 0;
+ ret = count;
+ ipb_bsycnt_inc(&ipbcfg);
+ } else
+ release_ipbuf(ipb_h);
+ spin_unlock(&dev->wsz_lock);
+ gb_out:
+ dsp_mem_disable_ipbuf();
+ }
+
+ up_out:
+ taskdev_unlock_and_stateunlock(dev, &dev->write_mutex);
+ return ret;
+}
+
+static unsigned int dsp_task_poll(struct file * file, poll_table * wait)
+{
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+ struct dsptask *task = dev->task;
+ unsigned int mask = 0;
+
+ if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+ return 0;
+ poll_wait(file, &dev->read_wait_q, wait);
+ poll_wait(file, &dev->write_wait_q, wait);
+ if (sndtyp_psv(task->ttyp) ||
+ (sndtyp_wd(task->ttyp) && kfifo_len(dev->rcvdt.fifo)) ||
+ (sndtyp_bk(task->ttyp) && !ipblink_empty(&dev->rcvdt.bk.link)))
+ mask |= POLLIN | POLLRDNORM;
+ if (dev->wsz)
+ mask |= POLLOUT | POLLWRNORM;
+ devstate_read_unlock(dev);
+
+ return mask;
+}
+
+static int dsp_tctl_issue(struct taskdev *dev, u16 cmd, int argc, u16 argv[])
+{
+ int tctl_argc;
+ struct mb_exarg mbarg, *mbargp;
+ int interactive;
+ u8 tid;
+ int ret = 0;
+
+ if (cmd < 0x8000) {
+ /*
+ * 0x0000 - 0x7fff
+ * system reserved TCTL commands
+ */
+ switch (cmd) {
+ case TCTL_TEN:
+ case TCTL_TDIS:
+ tctl_argc = 0;
+ interactive = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ /*
+ * 0x8000 - 0xffff
+ * user-defined TCTL commands
+ */
+ else if (cmd < 0x8100) {
+ /* 0x8000-0x80ff: no arg, non-interactive */
+ tctl_argc = 0;
+ interactive = 0;
+ } else if (cmd < 0x8200) {
+ /* 0x8100-0x81ff: 1 arg, non-interactive */
+ tctl_argc = 1;
+ interactive = 0;
+ } else if (cmd < 0x9000) {
+ /* 0x8200-0x8fff: reserved */
+ return -EINVAL;
+ } else if (cmd < 0x9100) {
+ /* 0x9000-0x90ff: no arg, interactive */
+ tctl_argc = 0;
+ interactive = 1;
+ } else if (cmd < 0x9200) {
+ /* 0x9100-0x91ff: 1 arg, interactive */
+ tctl_argc = 1;
+ interactive = 1;
+ } else {
+ /* 0x9200-0xffff: reserved */
+ return -EINVAL;
+ }
+
+ /*
+ * if argc < 0, use tctl_argc as is.
+ * if argc >= 0, check arg count.
+ */
+ if ((argc >= 0) && (argc != tctl_argc))
+ return -EINVAL;
+
+ /*
+ * issue TCTL
+ */
+ if (taskdev_lock_interruptible(dev, &dev->tctl_mutex))
+ return -EINTR;
+
+ tid = dev->task->tid;
+ if (tctl_argc > 0) {
+ mbarg.argc = tctl_argc;
+ mbarg.tid = tid;
+ mbarg.argv = argv;
+ mbargp = &mbarg;
+ } else
+ mbargp = NULL;
+
+ if (interactive) {
+ dev->tctl_stat = -EINVAL;
+
+ mbcompose_send_and_wait_exarg(TCTL, tid, cmd, mbargp,
+ &dev->tctl_wait_q);
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ goto up_out;
+ }
+ if ((ret = dev->tctl_stat) < 0) {
+ printk(KERN_ERR "omapdsp: TCTL not responding.\n");
+ goto up_out;
+ }
+ } else
+ mbcompose_send_exarg(TCTL, tid, cmd, mbargp);
+
+up_out:
+ mutex_unlock(&dev->tctl_mutex);
+ return ret;
+}
+
+static int dsp_task_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned int minor = MINOR(inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+ int ret;
+
+ if (cmd < 0x10000) {
+ /* issue TCTL */
+ u16 mbargv[1];
+
+ mbargv[0] = arg & 0xffff;
+ return dsp_tctl_issue(dev, cmd, -1, mbargv);
+ }
+
+ /* non TCTL ioctls */
+ switch (cmd) {
+
+ case TASK_IOCTL_LOCK:
+ ret = taskdev_lock(dev);
+ break;
+
+ case TASK_IOCTL_UNLOCK:
+ ret = taskdev_unlock(dev);
+ break;
+
+ case TASK_IOCTL_BFLSH:
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
+ ret = taskdev_flush_buf(dev);
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+ break;
+
+ case TASK_IOCTL_SETBSZ:
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
+ ret = taskdev_set_fifosz(dev, arg);
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+ break;
+
+ case TASK_IOCTL_GETNAME:
+ ret = 0;
+ if (copy_to_user((void __user *)arg, dev->name,
+ strlen(dev->name) + 1))
+ ret = -EFAULT;
+ break;
+
+ default:
+ ret = -ENOIOCTLCMD;
+
+ }
+
+ 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 & TASKDEV_ST_ATTACHED));
+ task = dev->task;
+ omap_mmu_exmap_use(&dsp_mmu, 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 & TASKDEV_ST_ATTACHED));
+ task = dev->task;
+ omap_mmu_exmap_unuse(&dsp_mmu, 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_mmap_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ return NOPAGE_SIGBUS;
+}
+
+static struct vm_operations_struct dsp_task_vm_ops = {
+ .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)
+{
+ void *tmp_vadr;
+ unsigned long tmp_padr, tmp_vmadr, off;
+ size_t req_len, tmp_len;
+ unsigned int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+ struct dsptask *task;
+ int ret = 0;
+
+ if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+ return -ENODEV;
+ task = dev->task;
+
+ /*
+ * Don't swap this area out
+ * Don't dump this area to a core file
+ */
+ vma->vm_flags |= VM_RESERVED | VM_IO;
+
+ /* Do not cache this area */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ req_len = vma->vm_end - vma->vm_start;
+ off = vma->vm_pgoff << PAGE_SHIFT;
+ tmp_vmadr = vma->vm_start;
+ tmp_vadr = task->map_base + off;
+ do {
+ tmp_padr = omap_mmu_virt_to_phys(&dsp_mmu, tmp_vadr, &tmp_len);
+ if (tmp_padr == 0) {
+ printk(KERN_ERR
+ "omapdsp: task %s: illegal address "
+ "for mmap: %p", task->name, tmp_vadr);
+ /* partial mapping will be cleared in upper layer */
+ ret = -EINVAL;
+ goto unlock_out;
+ }
+ if (tmp_len > req_len)
+ tmp_len = req_len;
+
+ pr_debug("omapdsp: mmap info: "
+ "vmadr = %08lx, padr = %08lx, len = %x\n",
+ tmp_vmadr, tmp_padr, tmp_len);
+ if (remap_pfn_range(vma, tmp_vmadr, tmp_padr >> PAGE_SHIFT,
+ tmp_len, vma->vm_page_prot) != 0) {
+ printk(KERN_ERR
+ "omapdsp: task %s: remap_page_range() failed.\n",
+ task->name);
+ /* partial mapping will be cleared in upper layer */
+ ret = -EINVAL;
+ goto unlock_out;
+ }
+
+ req_len -= tmp_len;
+ tmp_vmadr += tmp_len;
+ tmp_vadr += tmp_len;
+ } while (req_len);
+
+ vma->vm_ops = &dsp_task_vm_ops;
+ vma->vm_private_data = dev;
+ omap_mmu_exmap_use(&dsp_mmu, task->map_base, vma->vm_end - vma->vm_start);
+
+unlock_out:
+ devstate_read_unlock(dev);
+ return ret;
+}
+
+static int dsp_task_open(struct inode *inode, struct file *file)
+{
+ unsigned int minor = MINOR(inode->i_rdev);
+ struct taskdev *dev;
+ int ret = 0;
+
+ if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL))
+ return -ENODEV;
+
+ restart:
+ mutex_lock(&dev->usecount_lock);
+ down_write(&dev->state_sem);
+
+ /* state can be NOTASK, ATTACHED/FREEZED, KILLING, GARBAGE or INVALID here. */
+ switch (dev->state & TASKDEV_ST_STATE_MASK) {
+ case TASKDEV_ST_NOTASK:
+ break;
+ case TASKDEV_ST_ATTACHED:
+ goto attached;
+
+ case TASKDEV_ST_INVALID:
+ up_write(&dev->state_sem);
+ mutex_unlock(&dev->usecount_lock);
+ return -ENODEV;
+
+ case TASKDEV_ST_FREEZED:
+ case TASKDEV_ST_KILLING:
+ case TASKDEV_ST_GARBAGE:
+ case TASKDEV_ST_DELREQ:
+ /* on the kill process. wait until it becomes NOTASK. */
+ up_write(&dev->state_sem);
+ mutex_unlock(&dev->usecount_lock);
+ if (devstate_write_lock(dev, TASKDEV_ST_NOTASK) < 0)
+ return -EINTR;
+ devstate_write_unlock(dev);
+ goto restart;
+ }
+
+ /* NOTASK */
+ set_taskdev_state(dev, TASKDEV_ST_ADDREQ);
+ /* wake up twch daemon for tadd */
+ dsp_twch_touch();
+ up_write(&dev->state_sem);
+ if (devstate_write_lock(dev, TASKDEV_ST_ATTACHED |
+ TASKDEV_ST_ADDFAIL) < 0) {
+ /* cancelled */
+ if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
+ mutex_unlock(&dev->usecount_lock);
+ /* out of control ??? */
+ return -EINTR;
+ }
+ set_taskdev_state(dev, TASKDEV_ST_NOTASK);
+ ret = -EINTR;
+ goto change_out;
+ }
+ if (dev->state & TASKDEV_ST_ADDFAIL) {
+ printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
+ dev->name);
+ ret = -EBUSY;
+ set_taskdev_state(dev, TASKDEV_ST_NOTASK);
+ goto change_out;
+ }
+
+ attached:
+ ret = proc_list_add(&dev->proc_list_lock,
+ &dev->proc_list, current, file);
+ if (ret)
+ goto out;
+
+ dev->usecount++;
+ file->f_op = &dev->fops;
+ up_write(&dev->state_sem);
+ mutex_unlock(&dev->usecount_lock);
+
+#ifdef DSP_PTE_FREE /* not used currently. */
+ dsp_map_update(current);
+ dsp_cur_users_add(current);
+#endif /* DSP_PTE_FREE */
+ return 0;
+
+ change_out:
+ wake_up_interruptible_all(&dev->state_wait_q);
+ out:
+ up_write(&dev->state_sem);
+ mutex_unlock(&dev->usecount_lock);
+ return ret;
+}
+
+static int dsp_task_release(struct inode *inode, struct file *file)
+{
+ unsigned int minor = MINOR(inode->i_rdev);
+ struct taskdev *dev = taskdev[minor];
+
+#ifdef DSP_PTE_FREE /* not used currently. */
+ dsp_cur_users_del(current);
+#endif /* DSP_PTE_FREE */
+
+ if (has_taskdev_lock(dev))
+ taskdev_unlock(dev);
+
+ proc_list_del(&dev->proc_list_lock, &dev->proc_list, current, file);
+ mutex_lock(&dev->usecount_lock);
+ if (--dev->usecount > 0) {
+ /* other processes are using this device. no state change. */
+ mutex_unlock(&dev->usecount_lock);
+ return 0;
+ }
+
+ /* usecount == 0 */
+ down_write(&dev->state_sem);
+
+ /* state can be ATTACHED/FREEZED, KILLING or GARBAGE here. */
+ switch (dev->state & TASKDEV_ST_STATE_MASK) {
+
+ case TASKDEV_ST_KILLING:
+ break;
+
+ case TASKDEV_ST_GARBAGE:
+ set_taskdev_state(dev, TASKDEV_ST_NOTASK);
+ wake_up_interruptible_all(&dev->state_wait_q);
+ break;
+
+ case TASKDEV_ST_ATTACHED:
+ case TASKDEV_ST_FREEZED:
+ if (is_dynamic_task(minor)) {
+ set_taskdev_state(dev, TASKDEV_ST_DELREQ);
+ /* wake up twch daemon for tdel */
+ dsp_twch_touch();
+ }
+ break;
+
+ }
+
+ up_write(&dev->state_sem);
+ mutex_unlock(&dev->usecount_lock);
+ return 0;
+}
+
+/*
+ * mkdev / rmdev
+ */
+int dsp_mkdev(char *name)
+{
+ struct taskdev *dev;
+ int status;
+ unsigned char minor;
+ int ret;
+
+ if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
+ printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
+ return -EINVAL;
+ }
+
+ if (mutex_lock_interruptible(&devmgr_lock))
+ return -EINTR;
+
+ /* naming check */
+ for (minor = 0; minor < TASKDEV_MAX; minor++) {
+ if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
+ printk(KERN_ERR
+ "omapdsp: task device name %s is already "
+ "in use.\n", name);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ /* find free minor number */
+ for (minor = n_task; minor < TASKDEV_MAX; minor++) {
+ if (taskdev[minor] == NULL)
+ goto do_make;
+ }
+ printk(KERN_ERR "omapdsp: Too many task devices.\n");
+ ret = -EBUSY;
+ goto out;
+
+do_make:
+ if ((dev = kzalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ if ((status = taskdev_init(dev, name, minor)) < 0) {
+ kfree(dev);
+ ret = status;
+ goto out;
+ }
+ ret = minor;
+
+out:
+ mutex_unlock(&devmgr_lock);
+ return ret;
+}
+
+int dsp_rmdev(char *name)
+{
+ unsigned char minor;
+ int status;
+ int ret;
+
+ if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
+ printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
+ return -EINVAL;
+ }
+
+ if (mutex_lock_interruptible(&devmgr_lock))
+ return -EINTR;
+
+ /* find in dynamic devices */
+ for (minor = n_task; minor < TASKDEV_MAX; minor++) {
+ if (taskdev[minor] && !strcmp(taskdev[minor]->name, name))
+ goto do_remove;
+ }
+
+ /* find in static devices */
+ for (minor = 0; minor < n_task; minor++) {
+ if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
+ printk(KERN_ERR
+ "omapdsp: task device %s is static.\n", name);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ printk(KERN_ERR "omapdsp: task device %s not found.\n", name);
+ return -EINVAL;
+
+do_remove:
+ ret = minor;
+ if ((status = dsp_rmdev_minor(minor)) < 0)
+ ret = status;
+out:
+ mutex_unlock(&devmgr_lock);
+ return ret;
+}
+
+static int dsp_rmdev_minor(unsigned char minor)
+{
+ struct taskdev *dev = taskdev[minor];
+
+ while (!down_write_trylock(&dev->state_sem)) {
+ down_read(&dev->state_sem);
+ if (dev->state & (TASKDEV_ST_ATTACHED |
+ TASKDEV_ST_FREEZED)) {
+ /*
+ * task is working. kill it.
+ * ATTACHED -> FREEZED can be changed under
+ * down_read of state_sem..
+ */
+ set_taskdev_state(dev, TASKDEV_ST_FREEZED);
+ wake_up_interruptible_all(&dev->read_wait_q);
+ wake_up_interruptible_all(&dev->write_wait_q);
+ wake_up_interruptible_all(&dev->tctl_wait_q);
+ }
+ up_read(&dev->state_sem);
+ schedule();
+ }
+
+ switch (dev->state & TASKDEV_ST_STATE_MASK) {
+
+ case TASKDEV_ST_NOTASK:
+ case TASKDEV_ST_INVALID:
+ /* fine */
+ goto notask;
+
+ case TASKDEV_ST_ATTACHED:
+ case TASKDEV_ST_FREEZED:
+ /* task is working. kill it. */
+ set_taskdev_state(dev, TASKDEV_ST_KILLING);
+ up_write(&dev->state_sem);
+ dsp_tdel_bh(dev, TDEL_KILL);
+ goto invalidate;
+
+ case TASKDEV_ST_ADDREQ:
+ /* open() is waiting. drain it. */
+ set_taskdev_state(dev, TASKDEV_ST_ADDFAIL);
+ wake_up_interruptible_all(&dev->state_wait_q);
+ break;
+
+ case TASKDEV_ST_DELREQ:
+ /* nobody is waiting. */
+ set_taskdev_state(dev, TASKDEV_ST_NOTASK);
+ wake_up_interruptible_all(&dev->state_wait_q);
+ break;
+
+ case TASKDEV_ST_ADDING:
+ case TASKDEV_ST_DELING:
+ case TASKDEV_ST_KILLING:
+ case TASKDEV_ST_GARBAGE:
+ case TASKDEV_ST_ADDFAIL:
+ /* transient state. wait for a moment. */
+ break;
+
+ }
+
+ up_write(&dev->state_sem);
+
+invalidate:
+ /* wait for some time and hope the state is settled */
+ devstate_read_lock_timeout(dev, TASKDEV_ST_NOTASK, 5 * HZ);
+ if (!(dev->state & TASKDEV_ST_NOTASK)) {
+ printk(KERN_WARNING
+ "omapdsp: illegal device state (%s) on rmdev %s.\n",
+ devstate_name(dev->state), dev->name);
+ }
+notask:
+ set_taskdev_state(dev, TASKDEV_ST_INVALID);
+ devstate_read_unlock(dev);
+
+ taskdev_delete(minor);
+ kfree(dev);
+
+ return 0;
+}
+
+static struct file_operations dsp_task_fops = {
+ .owner = THIS_MODULE,
+ .poll = dsp_task_poll,
+ .ioctl = dsp_task_ioctl,
+ .open = dsp_task_open,
+ .release = dsp_task_release,
+};
+
+static void dsptask_dev_release(struct device *dev)
+{
+}
+
+static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
+{
+ int ret;
+ struct device *task_dev;
+
+ taskdev[minor] = dev;
+
+ spin_lock_init(&dev->proc_list_lock);
+ INIT_LIST_HEAD(&dev->proc_list);
+ init_waitqueue_head(&dev->read_wait_q);
+ init_waitqueue_head(&dev->write_wait_q);
+ init_waitqueue_head(&dev->tctl_wait_q);
+ mutex_init(&dev->read_mutex);
+ mutex_init(&dev->write_mutex);
+ mutex_init(&dev->tctl_mutex);
+ mutex_init(&dev->lock);
+ spin_lock_init(&dev->wsz_lock);
+ dev->tctl_ret = -EINVAL;
+ dev->lock_pid = 0;
+
+ strncpy(dev->name, name, TNM_LEN);
+ dev->name[TNM_LEN-1] = '\0';
+ set_taskdev_state(dev, (minor < n_task) ? TASKDEV_ST_ATTACHED : TASKDEV_ST_NOTASK);
+ dev->usecount = 0;
+ mutex_init(&dev->usecount_lock);
+ memcpy(&dev->fops, &dsp_task_fops, sizeof(struct file_operations));
+
+ dev->dev.parent = omap_dsp->dev;
+ dev->dev.bus = &dsptask_bus;
+ sprintf(dev->dev.bus_id, "dsptask%d", minor);
+ dev->dev.release = dsptask_dev_release;
+ ret = device_register(&dev->dev);
+ if (ret) {
+ printk(KERN_ERR "device_register failed: %d\n", ret);
+ return ret;
+ }
+ ret = device_create_file(&dev->dev, &dev_attr_devname);
+ if (ret)
+ goto fail_create_devname;
+ ret = device_create_file(&dev->dev, &dev_attr_devstate);
+ if (ret)
+ goto fail_create_devstate;
+ ret = device_create_file(&dev->dev, &dev_attr_proc_list);
+ if (ret)
+ goto fail_create_proclist;
+
+ task_dev = device_create(dsp_task_class, NULL,
+ MKDEV(OMAP_DSP_TASK_MAJOR, minor),
+ "dsptask%d", (int)minor);
+
+ if (unlikely(IS_ERR(task_dev))) {
+ ret = -EINVAL;
+ goto fail_create_taskclass;
+ }
+
+ init_waitqueue_head(&dev->state_wait_q);
+ init_rwsem(&dev->state_sem);
+
+ return 0;
+
+ fail_create_taskclass:
+ device_remove_file(&dev->dev, &dev_attr_proc_list);
+ fail_create_proclist:
+ device_remove_file(&dev->dev, &dev_attr_devstate);
+ fail_create_devstate:
+ device_remove_file(&dev->dev, &dev_attr_devname);
+ fail_create_devname:
+ device_unregister(&dev->dev);
+ return ret;
+}
+
+static void taskdev_delete(unsigned char minor)
+{
+ struct taskdev *dev = taskdev[minor];
+
+ if (!dev)
+ return;
+ 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);
+ device_destroy(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor));
+ device_unregister(&dev->dev);
+ proc_list_flush(&dev->proc_list_lock, &dev->proc_list);
+ taskdev[minor] = NULL;
+}
+
+static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
+{
+ u16 ttyp = task->ttyp;
+ int ret;
+
+ dev->fops.read =
+ sndtyp_acv(ttyp) ?
+ sndtyp_wd(ttyp) ? dsp_task_read_wd_acv:
+ /* sndtyp_bk */ dsp_task_read_bk_acv:
+ /* sndtyp_psv */
+ sndtyp_wd(ttyp) ? dsp_task_read_wd_psv:
+ /* sndtyp_bk */ dsp_task_read_bk_psv;
+ if (sndtyp_wd(ttyp)) {
+ /* word */
+ size_t fifosz = sndtyp_psv(ttyp) ? 2:32; /* passive:active */
+
+ dev->rcvdt.fifo = kfifo_alloc(fifosz, GFP_KERNEL,
+ &dev->read_lock);
+ if (IS_ERR(dev->rcvdt.fifo)) {
+ printk(KERN_ERR
+ "omapdsp: unable to allocate receive buffer. "
+ "(%d bytes for %s)\n", fifosz, dev->name);
+ return -ENOMEM;
+ }
+ } else {
+ /* block */
+ INIT_IPBLINK(&dev->rcvdt.bk.link);
+ dev->rcvdt.bk.rp = 0;
+ }
+
+ dev->fops.write =
+ rcvtyp_wd(ttyp) ? dsp_task_write_wd:
+ /* rcvbyp_bk */ dsp_task_write_bk;
+ dev->wsz = rcvtyp_acv(ttyp) ? 0 : /* active */
+ rcvtyp_wd(ttyp) ? 2 : /* passive word */
+ ipbcfg.lsz*2; /* passive block */
+
+ if (task->map_length)
+ dev->fops.mmap = dsp_task_mmap;
+
+ ret = device_create_file(&dev->dev, &dev_attr_taskname);
+ if (unlikely(ret))
+ goto fail_create_taskname;
+ ret = device_create_file(&dev->dev, &dev_attr_ttyp);
+ if (unlikely(ret))
+ goto fail_create_ttyp;
+ ret = device_create_file(&dev->dev, &dev_attr_wsz);
+ if (unlikely(ret))
+ goto fail_create_wsz;
+ if (task->map_length) {
+ ret = device_create_file(&dev->dev, &dev_attr_mmap);
+ if (unlikely(ret))
+ goto fail_create_mmap;
+ }
+ if (sndtyp_wd(ttyp)) {
+ ret = device_create_file(&dev->dev, &dev_attr_fifosz);
+ if (unlikely(ret))
+ goto fail_create_fifosz;
+ ret = device_create_file(&dev->dev, &dev_attr_fifocnt);
+ if (unlikely(ret))
+ goto fail_create_fifocnt;
+ } else {
+ ret = device_create_file(&dev->dev, &dev_attr_ipblink);
+ if (unlikely(ret))
+ goto fail_create_ipblink;
+ }
+
+ dev->task = task;
+ task->dev = dev;
+
+ return 0;
+
+ fail_create_fifocnt:
+ device_remove_file(&dev->dev, &dev_attr_fifosz);
+ fail_create_ipblink:
+ fail_create_fifosz:
+ if (task->map_length)
+ device_remove_file(&dev->dev, &dev_attr_mmap);
+ fail_create_mmap:
+ device_remove_file(&dev->dev, &dev_attr_wsz);
+ fail_create_wsz:
+ device_remove_file(&dev->dev, &dev_attr_ttyp);
+ fail_create_ttyp:
+ device_remove_file(&dev->dev, &dev_attr_taskname);
+ fail_create_taskname:
+ if (task->map_length)
+ dev->fops.mmap = NULL;
+
+ dev->fops.write = NULL;
+ dev->wsz = 0;
+
+ dev->fops.read = NULL;
+ taskdev_flush_buf(dev);
+
+ if (sndtyp_wd(ttyp))
+ kfifo_free(dev->rcvdt.fifo);
+
+ dev->task = NULL;
+
+ return ret;
+}
+
+static void taskdev_detach_task(struct taskdev *dev)
+{
+ u16 ttyp = dev->task->ttyp;
+
+ device_remove_file(&dev->dev, &dev_attr_taskname);
+ device_remove_file(&dev->dev, &dev_attr_ttyp);
+ if (sndtyp_wd(ttyp)) {
+ device_remove_file(&dev->dev, &dev_attr_fifosz);
+ device_remove_file(&dev->dev, &dev_attr_fifocnt);
+ } else
+ device_remove_file(&dev->dev, &dev_attr_ipblink);
+ device_remove_file(&dev->dev, &dev_attr_wsz);
+ if (dev->task->map_length) {
+ device_remove_file(&dev->dev, &dev_attr_mmap);
+ dev->fops.mmap = NULL;
+ }
+
+ dev->fops.read = NULL;
+ taskdev_flush_buf(dev);
+ if (sndtyp_wd(ttyp))
+ kfifo_free(dev->rcvdt.fifo);
+
+ dev->fops.write = NULL;
+ dev->wsz = 0;
+
+ pr_info("omapdsp: taskdev %s disabled.\n", dev->name);
+ dev->task = NULL;
+}
+
+/*
+ * tadd / tdel / tkill
+ */
+static int dsp_tadd(struct taskdev *dev, dsp_long_t adr)
+{
+ struct dsptask *task;
+ struct mb_exarg arg;
+ u8 tid, tid_response;
+ u16 argv[2];
+ int ret = 0;
+
+ if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) {
+ printk(KERN_ERR
+ "omapdsp: taskdev %s is not requesting for tadd. "
+ "(state is %s)\n", dev->name, devstate_name(dev->state));
+ return -EINVAL;
+ }
+ set_taskdev_state(dev, TASKDEV_ST_ADDING);
+ devstate_write_unlock(dev);
+
+ if (adr == TADD_ABORTADR) {
+ /* aborting tadd intentionally */
+ pr_info("omapdsp: tadd address is ABORTADR.\n");
+ goto fail_out;
+ }
+ if (adr >= DSPSPACE_SIZE) {
+ printk(KERN_ERR
+ "omapdsp: illegal address 0x%08x for tadd\n", adr);
+ ret = -EINVAL;
+ goto fail_out;
+ }
+
+ adr >>= 1; /* word address */
+ argv[0] = adr >> 16; /* addrh */
+ argv[1] = adr & 0xffff; /* addrl */
+
+ if (mutex_lock_interruptible(&cfg_lock)) {
+ ret = -EINTR;
+ goto fail_out;
+ }
+ cfg_tid = TID_ANON;
+ cfg_cmd = MBOX_CMD_DSP_TADD;
+ arg.tid = TID_ANON;
+ arg.argc = 2;
+ arg.argv = argv;
+
+ if (dsp_mem_sync_inc() < 0) {
+ printk(KERN_ERR "omapdsp: memory sync failed!\n");
+ ret = -EBUSY;
+ goto fail_out;
+ }
+ mbcompose_send_and_wait_exarg(TADD, 0, 0, &arg, &cfg_wait_q);
+
+ tid = cfg_tid;
+ cfg_tid = TID_ANON;
+ cfg_cmd = 0;
+ mutex_unlock(&cfg_lock);
+
+ if (tid == TID_ANON) {
+ printk(KERN_ERR "omapdsp: tadd failed!\n");
+ ret = -EINVAL;
+ goto fail_out;
+ }
+ if ((tid < n_task) || dsptask[tid]) {
+ printk(KERN_ERR "omapdsp: illegal tid (%d)!\n", tid);
+ ret = -EINVAL;
+ goto fail_out;
+ }
+ if ((task = kzalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
+ ret = -ENOMEM;
+ goto del_out;
+ }
+
+ if ((ret = dsp_task_config(task, tid)) < 0)
+ goto free_out;
+
+ if (strcmp(dev->name, task->name)) {
+ printk(KERN_ERR
+ "omapdsp: task name (%s) doesn't match with "
+ "device name (%s).\n", task->name, dev->name);
+ ret = -EINVAL;
+ goto free_out;
+ }
+
+ if ((ret = taskdev_attach_task(dev, task)) < 0)
+ goto free_out;
+
+ dsp_task_init(task);
+ pr_info("omapdsp: taskdev %s enabled.\n", dev->name);
+ set_taskdev_state(dev, TASKDEV_ST_ATTACHED);
+ wake_up_interruptible_all(&dev->state_wait_q);
+ return 0;
+
+free_out:
+ kfree(task);
+
+del_out:
+ printk(KERN_ERR "omapdsp: deleting the task...\n");
+
+ set_taskdev_state(dev, TASKDEV_ST_DELING);
+
+ if (mutex_lock_interruptible(&cfg_lock)) {
+ printk(KERN_ERR "omapdsp: aborting tdel process. "
+ "DSP side could be corrupted.\n");
+ goto fail_out;
+ }
+ cfg_tid = TID_ANON;
+ cfg_cmd = MBOX_CMD_DSP_TDEL;
+ mbcompose_send_and_wait(TDEL, tid, TDEL_KILL, &cfg_wait_q);
+ tid_response = cfg_tid;
+ cfg_tid = TID_ANON;
+ cfg_cmd = 0;
+ mutex_unlock(&cfg_lock);
+
+ if (tid_response != tid)
+ printk(KERN_ERR "omapdsp: tdel failed. "
+ "DSP side could be corrupted.\n");
+
+fail_out:
+ set_taskdev_state(dev, TASKDEV_ST_ADDFAIL);
+ wake_up_interruptible_all(&dev->state_wait_q);
+ return ret;
+}
+
+int dsp_tadd_minor(unsigned char minor, dsp_long_t adr)
+{
+ struct taskdev *dev;
+ int status;
+ int ret;
+
+ if (mutex_lock_interruptible(&devmgr_lock))
+ return -EINTR;
+
+ if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
+ printk(KERN_ERR
+ "omapdsp: no task device with minor %d\n", minor);
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = minor;
+ if ((status = dsp_tadd(dev, adr)) < 0)
+ ret = status;
+
+out:
+ mutex_unlock(&devmgr_lock);
+ return ret;
+}
+
+static int dsp_tdel(struct taskdev *dev)
+{
+ if (!devstate_write_lock_and_test(dev, TASKDEV_ST_DELREQ)) {
+ printk(KERN_ERR
+ "omapdsp: taskdev %s is not requesting for tdel. "
+ "(state is %s)\n", dev->name, devstate_name(dev->state));
+ return -EINVAL;
+ }
+ set_taskdev_state(dev, TASKDEV_ST_DELING);
+ devstate_write_unlock(dev);
+
+ return dsp_tdel_bh(dev, TDEL_SAFE);
+}
+
+int dsp_tdel_minor(unsigned char minor)
+{
+ struct taskdev *dev;
+ int status;
+ int ret;
+
+ if (mutex_lock_interruptible(&devmgr_lock))
+ return -EINTR;
+
+ if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
+ printk(KERN_ERR
+ "omapdsp: no task device with minor %d\n", minor);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = minor;
+ if ((status = dsp_tdel(dev)) < 0)
+ ret = status;
+
+out:
+ mutex_unlock(&devmgr_lock);
+ return ret;
+}
+
+static int dsp_tkill(struct taskdev *dev)
+{
+ while (!down_write_trylock(&dev->state_sem)) {
+ if (!devstate_read_lock_and_test(dev, (TASKDEV_ST_ATTACHED |
+ TASKDEV_ST_FREEZED))) {
+ printk(KERN_ERR
+ "omapdsp: task has not been attached for "
+ "taskdev %s\n", dev->name);
+ return -EINVAL;
+ }
+ /* ATTACHED -> FREEZED can be changed under read semaphore. */
+ set_taskdev_state(dev, TASKDEV_ST_FREEZED);
+ wake_up_interruptible_all(&dev->read_wait_q);
+ wake_up_interruptible_all(&dev->write_wait_q);
+ wake_up_interruptible_all(&dev->tctl_wait_q);
+ devstate_read_unlock(dev);
+ schedule();
+ }
+
+ if (!(dev->state & (TASKDEV_ST_ATTACHED |
+ TASKDEV_ST_FREEZED))) {
+ printk(KERN_ERR
+ "omapdsp: task has not been attached for taskdev %s\n",
+ dev->name);
+ devstate_write_unlock(dev);
+ return -EINVAL;
+ }
+ if (!is_dynamic_task(dev->task->tid)) {
+ printk(KERN_ERR "omapdsp: task %s is not a dynamic task.\n",
+ dev->name);
+ devstate_write_unlock(dev);
+ return -EINVAL;
+ }
+ set_taskdev_state(dev, TASKDEV_ST_KILLING);
+ devstate_write_unlock(dev);
+
+ return dsp_tdel_bh(dev, TDEL_KILL);
+}
+
+int dsp_tkill_minor(unsigned char minor)
+{
+ struct taskdev *dev;
+ int status;
+ int ret;
+
+ if (mutex_lock_interruptible(&devmgr_lock))
+ return -EINTR;
+
+ if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
+ printk(KERN_ERR
+ "omapdsp: no task device with minor %d\n", minor);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = minor;
+ if ((status = dsp_tkill(dev)) < 0)
+ ret = status;
+
+out:
+ mutex_unlock(&devmgr_lock);
+ return ret;
+}
+
+static int dsp_tdel_bh(struct taskdev *dev, u16 type)
+{
+ struct dsptask *task;
+ u8 tid, tid_response;
+ int ret = 0;
+
+ task = dev->task;
+ tid = task->tid;
+ if (mutex_lock_interruptible(&cfg_lock)) {
+ if (type == TDEL_SAFE) {
+ set_taskdev_state(dev, TASKDEV_ST_DELREQ);
+ return -EINTR;
+ } else {
+ tid_response = TID_ANON;
+ ret = -EINTR;
+ goto detach_out;
+ }
+ }
+ cfg_tid = TID_ANON;
+ cfg_cmd = MBOX_CMD_DSP_TDEL;
+ mbcompose_send_and_wait(TDEL, tid, type, &cfg_wait_q);
+ tid_response = cfg_tid;
+ cfg_tid = TID_ANON;
+ cfg_cmd = 0;
+ mutex_unlock(&cfg_lock);
+
+detach_out:
+ taskdev_detach_task(dev);
+ dsp_task_unconfig(task);
+ kfree(task);
+
+ if (tid_response != tid) {
+ printk(KERN_ERR "omapdsp: %s failed!\n",
+ (type == TDEL_SAFE) ? "tdel" : "tkill");
+ ret = -EINVAL;
+ }
+ down_write(&dev->state_sem);
+ set_taskdev_state(dev, (dev->usecount > 0) ? TASKDEV_ST_GARBAGE :
+ TASKDEV_ST_NOTASK);
+ wake_up_interruptible_all(&dev->state_wait_q);
+ up_write(&dev->state_sem);
+
+ return ret;
+}
+
+/*
+ * state inquiry
+ */
+long taskdev_state_stale(unsigned char minor)
+{
+ if (taskdev[minor]) {
+ long state = taskdev[minor]->state;
+ taskdev[minor]->state |= TASKDEV_ST_STALE;
+ return state;
+ } else
+ return TASKDEV_ST_NOTASK;
+}
+
+/*
+ * functions called from mailbox interrupt routine
+ */
+void mbox_wdsnd(struct mbcmd *mb)
+{
+ unsigned int n;
+ u8 tid = mb->cmd_l;
+ u16 data = mb->data;
+ struct dsptask *task = dsptask[tid];
+
+ if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+ printk(KERN_ERR "mbox: WDSND with illegal tid! %d\n", tid);
+ return;
+ }
+ if (sndtyp_bk(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: WDSND from block sending task! (task%d)\n", tid);
+ return;
+ }
+ if (sndtyp_psv(task->ttyp) &&
+ !waitqueue_active(&task->dev->read_wait_q)) {
+ printk(KERN_WARNING
+ "mbox: WDSND from passive sending task (task%d) "
+ "without request!\n", tid);
+ return;
+ }
+
+ n = kfifo_put(task->dev->rcvdt.fifo, (unsigned char *)&data,
+ sizeof(data));
+ if (n != sizeof(data))
+ printk(KERN_WARNING "Receive FIFO(%d) is full\n", tid);
+
+ wake_up_interruptible(&task->dev->read_wait_q);
+}
+
+void mbox_wdreq(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+ struct dsptask *task = dsptask[tid];
+ struct taskdev *dev;
+
+ if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+ printk(KERN_ERR "mbox: WDREQ with illegal tid! %d\n", tid);
+ return;
+ }
+ if (rcvtyp_psv(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: WDREQ from passive receiving task! (task%d)\n",
+ tid);
+ return;
+ }
+
+ dev = task->dev;
+ spin_lock(&dev->wsz_lock);
+ dev->wsz = 2;
+ spin_unlock(&dev->wsz_lock);
+ wake_up_interruptible(&dev->write_wait_q);
+}
+
+void mbox_bksnd(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+ u16 bid = mb->data;
+ struct dsptask *task = dsptask[tid];
+ struct ipbuf_head *ipb_h;
+ u16 cnt;
+
+ if (bid >= ipbcfg.ln) {
+ printk(KERN_ERR "mbox: BKSND with illegal bid! %d\n", bid);
+ return;
+ }
+ ipb_h = bid_to_ipbuf(bid);
+ ipb_bsycnt_dec(&ipbcfg);
+ if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+ printk(KERN_ERR "mbox: BKSND with illegal tid! %d\n", tid);
+ goto unuse_ipbuf_out;
+ }
+ if (sndtyp_wd(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: BKSND from word sending task! (task%d)\n", tid);
+ goto unuse_ipbuf_out;
+ }
+ if (sndtyp_pvt(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: BKSND from private sending task! (task%d)\n", tid);
+ goto unuse_ipbuf_out;
+ }
+ if (sync_with_dsp(&ipb_h->p->sd, tid, 10) < 0) {
+ printk(KERN_ERR "mbox: BKSND - IPBUF sync failed!\n");
+ return;
+ }
+
+ /* should be done in DSP, but just in case. */
+ ipb_h->p->next = BID_NULL;
+
+ cnt = ipb_h->p->c;
+ if (cnt > ipbcfg.lsz) {
+ printk(KERN_ERR "mbox: BKSND cnt(%d) > ipbuf line size(%d)!\n",
+ cnt, ipbcfg.lsz);
+ goto unuse_ipbuf_out;
+ }
+
+ if (cnt == 0) {
+ /* 0-byte send from DSP */
+ unuse_ipbuf_nowait(ipb_h);
+ goto done;
+ }
+ ipblink_add_tail(&task->dev->rcvdt.bk.link, bid);
+ /* we keep coming bid and return alternative line to DSP. */
+ balance_ipbuf();
+
+done:
+ wake_up_interruptible(&task->dev->read_wait_q);
+ return;
+
+unuse_ipbuf_out:
+ unuse_ipbuf_nowait(ipb_h);
+ return;
+}
+
+void mbox_bkreq(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+ u16 cnt = mb->data;
+ struct dsptask *task = dsptask[tid];
+ struct taskdev *dev;
+
+ if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+ printk(KERN_ERR "mbox: BKREQ with illegal tid! %d\n", tid);
+ return;
+ }
+ if (rcvtyp_wd(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: BKREQ from word receiving task! (task%d)\n", tid);
+ return;
+ }
+ if (rcvtyp_pvt(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: BKREQ from private receiving task! (task%d)\n",
+ tid);
+ return;
+ }
+ if (rcvtyp_psv(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: BKREQ from passive receiving task! (task%d)\n",
+ tid);
+ return;
+ }
+
+ dev = task->dev;
+ spin_lock(&dev->wsz_lock);
+ dev->wsz = cnt*2;
+ spin_unlock(&dev->wsz_lock);
+ wake_up_interruptible(&dev->write_wait_q);
+}
+
+void mbox_bkyld(struct mbcmd *mb)
+{
+ u16 bid = mb->data;
+ struct ipbuf_head *ipb_h;
+
+ if (bid >= ipbcfg.ln) {
+ printk(KERN_ERR "mbox: BKYLD with illegal bid! %d\n", bid);
+ return;
+ }
+ ipb_h = bid_to_ipbuf(bid);
+
+ /* should be done in DSP, but just in case. */
+ ipb_h->p->next = BID_NULL;
+
+ /* we don't need to sync with DSP */
+ ipb_bsycnt_dec(&ipbcfg);
+ release_ipbuf(ipb_h);
+}
+
+void mbox_bksndp(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+ struct dsptask *task = dsptask[tid];
+ struct ipbuf_p *ipbp;
+
+ if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+ printk(KERN_ERR "mbox: BKSNDP with illegal tid! %d\n", tid);
+ return;
+ }
+ if (sndtyp_wd(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: BKSNDP from word sending task! (task%d)\n", tid);
+ return;
+ }
+ if (sndtyp_gbl(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: BKSNDP from non-private sending task! (task%d)\n",
+ tid);
+ return;
+ }
+
+ /*
+ * we should not have delayed block at this point
+ * because read() routine releases the lock of the buffer and
+ * until then DSP can't send next data.
+ */
+
+ ipbp = task->ipbuf_pvt_r;
+ if (sync_with_dsp(&ipbp->s, tid, 10) < 0) {
+ printk(KERN_ERR "mbox: BKSNDP - IPBUF sync failed!\n");
+ return;
+ }
+ pr_debug("mbox: ipbuf_pvt_r->a = 0x%08lx\n",
+ MKLONG(ipbp->ah, ipbp->al));
+ ipblink_add_pvt(&task->dev->rcvdt.bk.link);
+ wake_up_interruptible(&task->dev->read_wait_q);
+}
+
+void mbox_bkreqp(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+ struct dsptask *task = dsptask[tid];
+ struct taskdev *dev;
+ struct ipbuf_p *ipbp;
+
+ if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+ printk(KERN_ERR "mbox: BKREQP with illegal tid! %d\n", tid);
+ return;
+ }
+ if (rcvtyp_wd(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: BKREQP from word receiving task! (task%d)\n", tid);
+ return;
+ }
+ if (rcvtyp_gbl(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: BKREQP from non-private receiving task! (task%d)\n", tid);
+ return;
+ }
+ if (rcvtyp_psv(task->ttyp)) {
+ printk(KERN_ERR
+ "mbox: BKREQP from passive receiving task! (task%d)\n", tid);
+ return;
+ }
+
+ ipbp = task->ipbuf_pvt_w;
+ if (sync_with_dsp(&ipbp->s, TID_FREE, 10) < 0) {
+ printk(KERN_ERR "mbox: BKREQP - IPBUF sync failed!\n");
+ return;
+ }
+ pr_debug("mbox: ipbuf_pvt_w->a = 0x%08lx\n",
+ MKLONG(ipbp->ah, ipbp->al));
+ dev = task->dev;
+ spin_lock(&dev->wsz_lock);
+ dev->wsz = ipbp->c*2;
+ spin_unlock(&dev->wsz_lock);
+ wake_up_interruptible(&dev->write_wait_q);
+}
+
+void mbox_tctl(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+ struct dsptask *task = dsptask[tid];
+
+ if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+ printk(KERN_ERR "mbox: TCTL with illegal tid! %d\n", tid);
+ return;
+ }
+
+ if (!waitqueue_active(&task->dev->tctl_wait_q)) {
+ printk(KERN_WARNING "mbox: unexpected TCTL from DSP!\n");
+ return;
+ }
+
+ task->dev->tctl_stat = mb->data;
+ wake_up_interruptible(&task->dev->tctl_wait_q);
+}
+
+void mbox_tcfg(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+ struct dsptask *task = dsptask[tid];
+ u16 *tnm;
+ volatile u16 *buf;
+ int i;
+
+ if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+ printk(KERN_ERR "mbox: TCFG with illegal tid! %d\n", tid);
+ return;
+ }
+ if ((task->state != TASK_ST_CFGREQ) || (cfg_cmd != MBOX_CMD_DSP_TCFG)) {
+ printk(KERN_WARNING "mbox: unexpected TCFG from DSP!\n");
+ return;
+ }
+
+ if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+ printk(KERN_ERR "mbox: TCFG - ipbuf_sys_da read failed!\n");
+ dsp_mem_disable(ipbuf_sys_da);
+ goto out;
+ }
+ if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
+ printk(KERN_ERR "mbox: TCFG - IPBUF sync failed!\n");
+ dsp_mem_disable(ipbuf_sys_da);
+ goto out;
+ }
+
+ /*
+ * read configuration data on system IPBUF
+ */
+ buf = ipbuf_sys_da->d;
+ task->ttyp = buf[0];
+ task->ipbuf_pvt_r = MKVIRT(buf[1], buf[2]);
+ task->ipbuf_pvt_w = MKVIRT(buf[3], buf[4]);
+ task->map_base = MKVIRT(buf[5], buf[6]);
+ task->map_length = MKLONG(buf[7], buf[8]) << 1; /* word -> byte */
+ tnm = MKVIRT(buf[9], buf[10]);
+ release_ipbuf_pvt(ipbuf_sys_da);
+ dsp_mem_disable(ipbuf_sys_da);
+
+ /*
+ * copy task name string
+ */
+ if (dsp_address_validate(tnm, TNM_LEN, "task name buffer") < 0) {
+ task->name[0] = '\0';
+ goto out;
+ }
+
+ for (i = 0; i < TNM_LEN-1; i++) {
+ /* avoiding byte access */
+ u16 tmp = tnm[i];
+ task->name[i] = tmp & 0x00ff;
+ if (!tmp)
+ break;
+ }
+ task->name[TNM_LEN-1] = '\0';
+
+ task->state = TASK_ST_READY;
+out:
+ wake_up_interruptible(&cfg_wait_q);
+}
+
+void mbox_tadd(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+
+ if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBOX_CMD_DSP_TADD)) {
+ printk(KERN_WARNING "mbox: unexpected TADD from DSP!\n");
+ return;
+ }
+ cfg_tid = tid;
+ wake_up_interruptible(&cfg_wait_q);
+}
+
+void mbox_tdel(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+
+ if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBOX_CMD_DSP_TDEL)) {
+ printk(KERN_WARNING "mbox: unexpected TDEL from DSP!\n");
+ return;
+ }
+ cfg_tid = tid;
+ wake_up_interruptible(&cfg_wait_q);
+}
+
+void mbox_err_fatal(u8 tid)
+{
+ struct dsptask *task = dsptask[tid];
+ struct taskdev *dev;
+
+ if ((tid >= TASKDEV_MAX) || (task == NULL)) {
+ printk(KERN_ERR "mbox: FATAL ERR with illegal tid! %d\n", tid);
+ return;
+ }
+
+ /* wake up waiting processes */
+ dev = task->dev;
+ wake_up_interruptible_all(&dev->read_wait_q);
+ wake_up_interruptible_all(&dev->write_wait_q);
+ wake_up_interruptible_all(&dev->tctl_wait_q);
+}
+
+static u16 *dbg_buf;
+static u16 dbg_buf_sz, dbg_line_sz;
+static int dbg_rp;
+
+int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz)
+{
+#ifdef OLD_BINARY_SUPPORT
+ if ((mbox_revision == MBREV_3_0) || (mbox_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 mbox_dbg_old(struct mbcmd *mb);
+#endif
+
+void mbox_dbg(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+ int cnt = mb->data;
+ char s[80], *s_end = &s[79], *p;
+ u16 *src;
+ int i;
+
+#ifdef OLD_BINARY_SUPPORT
+ if ((mbox_revision == MBREV_3_0) || (mbox_revision == MBREV_3_2)) {
+ mbox_dbg_old(mb);
+ return;
+ }
+#endif
+
+ if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
+ (tid != TID_ANON)) {
+ printk(KERN_ERR "mbox: DBG with illegal tid! %d\n", tid);
+ return;
+ }
+ if (dbg_buf == NULL) {
+ printk(KERN_ERR "mbox: 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++) {
+ u16 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';
+ pr_info("%s", s);
+ p = s;
+ continue;
+ }
+ if (p == s_end) {
+ *p = '\0';
+ pr_info("%s\n", s);
+ p = s;
+ continue;
+ }
+ }
+ if (p > s) {
+ *p = '\0';
+ pr_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 mbox_dbg_old(struct mbcmd *mb)
+{
+ u8 tid = mb->cmd_l;
+ char s[80], *s_end = &s[79], *p;
+ u16 *src;
+ volatile u16 *buf;
+ int cnt;
+ int i;
+
+ if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
+ (tid != TID_ANON)) {
+ printk(KERN_ERR "mbox: DBG with illegal tid! %d\n", tid);
+ return;
+ }
+ if (dsp_mem_enable(ipbuf_sys_da) < 0) {
+ printk(KERN_ERR "mbox: DBG - ipbuf_sys_da read failed!\n");
+ return;
+ }
+ if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
+ printk(KERN_ERR "mbox: DBG - IPBUF sync failed!\n");
+ goto out1;
+ }
+ buf = ipbuf_sys_da->d;
+ cnt = buf[0];
+ src = MKVIRT(buf[1], buf[2]);
+ if (dsp_address_validate(src, cnt, "dbg buffer") < 0)
+ goto out2;
+
+ if (dsp_mem_enable(src) < 0)
+ goto out2;
+
+ p = s;
+ for (i = 0; i < cnt; i++) {
+ u16 tmp;
+ /*
+ * Be carefull that ipbuf 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';
+ pr_info("%s", s);
+ p = s;
+ continue;
+ }
+ if (p == s_end) {
+ *p = '\0';
+ pr_info("%s\n", s);
+ p = s;
+ continue;
+ }
+ }
+ if (p > s) {
+ *p = '\0';
+ pr_info("%s\n", s);
+ }
+
+ dsp_mem_disable(src);
+out2:
+ release_ipbuf_pvt(ipbuf_sys_da);
+out1:
+ dsp_mem_disable(ipbuf_sys_da);
+}
+#endif /* OLD_BINARY_SUPPORT */
+
+/*
+ * sysfs files: for each device
+ */
+
+/* devname */
+static ssize_t devname_show(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", to_taskdev(d)->name);
+}
+
+/* devstate */
+static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", devstate_name(to_taskdev(d)->state));
+}
+
+/* proc_list */
+static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct taskdev *dev;
+ struct proc_list *pl;
+ int len = 0;
+
+ dev = to_taskdev(d);
+ spin_lock(&dev->proc_list_lock);
+ list_for_each_entry(pl, &dev->proc_list, list_head) {
+ /* need to lock tasklist_lock before calling
+ * find_task_by_pid_type. */
+ if (find_task_by_pid(pl->pid) != NULL)
+ len += sprintf(buf + len, "%d\n", pl->pid);
+ read_unlock(&tasklist_lock);
+ }
+ spin_unlock(&dev->proc_list_lock);
+
+ return len;
+}
+
+/* taskname */
+static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct taskdev *dev = to_taskdev(d);
+ int len;
+
+ if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+ return -ENODEV;
+
+ len = sprintf(buf, "%s\n", dev->task->name);
+
+ devstate_read_unlock(dev);
+ return len;
+}
+
+/* ttyp */
+static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct taskdev *dev = to_taskdev(d);
+ u16 ttyp;
+ int len = 0;
+
+ if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED))
+ return -ENODEV;
+
+ ttyp = dev->task->ttyp;
+ len += sprintf(buf + len, "0x%04x\n", ttyp);
+ len += sprintf(buf + len, "%s %s send\n",
+ (sndtyp_acv(ttyp)) ? "active" :
+ "passive",
+ (sndtyp_wd(ttyp)) ? "word" :
+ (sndtyp_pvt(ttyp)) ? "private block" :
+ "global block");
+ len += sprintf(buf + len, "%s %s receive\n",
+ (rcvtyp_acv(ttyp)) ? "active" :
+ "passive",
+ (rcvtyp_wd(ttyp)) ? "word" :
+ (rcvtyp_pvt(ttyp)) ? "private block" :
+ "global block");
+
+ devstate_read_unlock(dev);
+ return len;
+}
+
+/* fifosz */
+static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo;
+ return sprintf(buf, "%d\n", fifo->size);
+}
+
+static int fifosz_store(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct taskdev *dev = to_taskdev(d);
+ unsigned long fifosz;
+ int ret;
+
+ fifosz = simple_strtol(buf, NULL, 10);
+ if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex))
+ return -ENODEV;
+ ret = taskdev_set_fifosz(dev, fifosz);
+ taskdev_unlock_and_stateunlock(dev, &dev->read_mutex);
+
+ return (ret < 0) ? ret : strlen(buf);
+}
+
+/* fifocnt */
+static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo;
+ return sprintf(buf, "%d\n", fifo->size);
+}
+
+/* ipblink */
+static inline char *bid_name(u16 bid)
+{
+ static char s[6];
+
+ switch (bid) {
+ case BID_NULL:
+ return "NULL";
+ case BID_PVT:
+ return "PRIVATE";
+ default:
+ sprintf(s, "%d", bid);
+ return s;
+ }
+}
+
+static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->rcvdt.bk;
+ int len;
+
+ spin_lock(&rcvdt->link.lock);
+ len = sprintf(buf, "top %s\ntail %s\n",
+ bid_name(rcvdt->link.top), bid_name(rcvdt->link.tail));
+ spin_unlock(&rcvdt->link.lock);
+
+ return len;
+}
+
+/* wsz */
+static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", to_taskdev(d)->wsz);
+}
+
+/* mmap */
+static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
+ char *buf)
+{
+ struct dsptask *task = to_taskdev(d)->task;
+ return sprintf(buf, "0x%p 0x%x\n", task->map_base, task->map_length);
+}
+
+/*
+ * called from ipbuf_show()
+ */
+int ipbuf_is_held(u8 tid, u16 bid)
+{
+ struct dsptask *task = dsptask[tid];
+ struct ipblink *link;
+ u16 b;
+ int ret = 0;
+
+ if (task == NULL)
+ return 0;
+
+ link = &task->dev->rcvdt.bk.link;
+ spin_lock(&link->lock);
+ ipblink_for_each(b, link) {
+ if (b == bid) { /* found */
+ ret = 1;
+ break;
+ }
+ }
+ spin_unlock(&link->lock);
+
+ return ret;
+}
+
+int __init dsp_taskmod_init(void)
+{
+ int retval;
+
+ memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX);
+ memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX);
+
+ retval = register_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask",
+ &dsp_task_fops);
+ if (retval < 0) {
+ printk(KERN_ERR
+ "omapdsp: failed to register task device: %d\n", retval);
+ return retval;
+ }
+
+ retval = bus_register(&dsptask_bus);
+ if (retval) {
+ printk(KERN_ERR
+ "omapdsp: failed to register DSP task bus: %d\n",
+ retval);
+ unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
+ return -EINVAL;
+ }
+ retval = driver_register(&dsptask_driver);
+ if (retval) {
+ printk(KERN_ERR
+ "omapdsp: failed to register DSP task driver: %d\n",
+ retval);
+ bus_unregister(&dsptask_bus);
+ unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
+ return -EINVAL;
+ }
+ dsp_task_class = class_create(THIS_MODULE, "dsptask");
+ if (IS_ERR(dsp_task_class)) {
+ printk(KERN_ERR "omapdsp: failed to create DSP task class\n");
+ driver_unregister(&dsptask_driver);
+ bus_unregister(&dsptask_bus);
+ unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void dsp_taskmod_exit(void)
+{
+ class_destroy(dsp_task_class);
+ driver_unregister(&dsptask_driver);
+ bus_unregister(&dsptask_bus);
+ unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
+}
diff --git a/drivers/dsp/dspgateway/taskwatch.c b/drivers/dsp/dspgateway/taskwatch.c
new file mode 100644
index 0000000..4297b51
--- /dev/null
+++ b/drivers/dsp/dspgateway/taskwatch.c
@@ -0,0 +1,163 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <asm/arch/dsp.h>
+#include "dsp_mbcmd.h"
+#include "dsp.h"
+
+static DECLARE_WAIT_QUEUE_HEAD(read_wait_q);
+static unsigned int change_cnt;
+
+void dsp_twch_touch(void)
+{
+ change_cnt++;
+ wake_up_interruptible(&read_wait_q);
+}
+
+/*
+ * @count: represents the device counts of the user's interst
+ */
+static ssize_t dsp_twch_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ long taskstat[TASKDEV_MAX];
+ int devcount = count / sizeof(long);
+ int i;
+ DEFINE_WAIT(wait);
+
+ if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
+ printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
+ return -EINVAL;
+ }
+
+ prepare_to_wait(&read_wait_q, &wait, TASK_INTERRUPTIBLE);
+ if (change_cnt == 0) /* last check */
+ schedule();
+ finish_wait(&read_wait_q, &wait);
+
+ /* unconfigured while waiting ;-( */
+ if ((change_cnt == 0) && (dsp_cfgstat_get_stat() != CFGSTAT_READY))
+ return -EINVAL;
+
+ if (devcount > TASKDEV_MAX)
+ devcount = TASKDEV_MAX;
+
+ count = devcount * sizeof(long);
+ change_cnt = 0;
+ for (i = 0; i < devcount; 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))
+ return -EFAULT;
+
+ return count;
+}
+
+static unsigned int dsp_twch_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+
+ poll_wait(file, &read_wait_q, wait);
+ if (change_cnt)
+ mask |= POLLIN | POLLRDNORM;
+
+ return mask;
+}
+
+static int dsp_twch_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int ret;
+
+ switch (cmd) {
+ case TWCH_IOCTL_MKDEV:
+ {
+ char name[TNM_LEN];
+ if (copy_from_user(name, (void __user *)arg, TNM_LEN))
+ return -EFAULT;
+ name[TNM_LEN-1] = '\0';
+ ret = dsp_mkdev(name);
+ break;
+ }
+
+ case TWCH_IOCTL_RMDEV:
+ {
+ char name[TNM_LEN];
+ if (copy_from_user(name, (void __user *)arg, TNM_LEN))
+ return -EFAULT;
+ name[TNM_LEN-1] = '\0';
+ ret = dsp_rmdev(name);
+ break;
+ }
+
+ case TWCH_IOCTL_TADD:
+ {
+ struct omap_dsp_taddinfo ti;
+ if (copy_from_user(&ti, (void __user *)arg, sizeof(ti)))
+ return -EFAULT;
+ ret = dsp_tadd_minor(ti.minor, ti.taskadr);
+ break;
+ }
+
+ case TWCH_IOCTL_TDEL:
+ ret = dsp_tdel_minor(arg);
+ break;
+
+ case TWCH_IOCTL_TKILL:
+ ret = dsp_tkill_minor(arg);
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return ret;
+}
+
+struct file_operations dsp_twch_fops = {
+ .owner = THIS_MODULE,
+ .read = dsp_twch_read,
+ .poll = dsp_twch_poll,
+ .ioctl = dsp_twch_ioctl,
+};
+
+void dsp_twch_start(void)
+{
+ change_cnt = 1; /* first read will not wait */
+}
+
+void dsp_twch_stop(void)
+{
+ wake_up_interruptible(&read_wait_q);
+}
diff --git a/drivers/dsp/dspgateway/uaccess_dsp.S b/drivers/dsp/dspgateway/uaccess_dsp.S
new file mode 100644
index 0000000..bcf4a54
--- /dev/null
+++ b/drivers/dsp/dspgateway/uaccess_dsp.S
@@ -0,0 +1,77 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ .text
+
+/* Prototype: int __copy_to_user_dsp_2b(void *to, const char *from)
+ * Purpose : copy 2 bytes to user memory from kernel(DSP) memory
+ * escaping from unexpected byte swap using __copy_to_user()
+ * in OMAP architecture.
+ * Params : to - user memory
+ * : from - kernel(DSP) memory
+ * Returns : success = 0, failure = 2
+ */
+
+ENTRY(__copy_to_user_dsp_2b)
+ stmfd sp!, {r4, lr}
+ ldrb r3, [r1], #1
+ ldrb r4, [r1], #1
+USER( strbt r4, [r0], #1) @ May fault
+USER( strbt r3, [r0], #1) @ May fault
+ mov r0, #0
+ ldmfd sp!, {r4, pc}
+
+ .section .fixup,"ax"
+ .align 0
+9001: mov r0, #2
+ ldmfd sp!, {r4, pc}
+ .previous
+
+/* Prototype: unsigned long __copy_from_user_dsp_2b(void *to, const void *from);
+ * Purpose : copy 2 bytes from user memory to kernel(DSP) memory
+ * escaping from unexpected byte swap using __copy_to_user()
+ * in OMAP architecture.
+ * Params : to - kernel (DSP) memory
+ * : from - user memory
+ * Returns : success = 0, failure = 2
+ */
+
+ENTRY(__copy_from_user_dsp_2b)
+ stmfd sp!, {r4, lr}
+USER( ldrbt r3, [r1], #1) @ May fault
+USER( ldrbt r4, [r1], #1) @ May fault
+ strb r4, [r0], #1
+ strb r3, [r0], #1
+ mov r0, #0
+ ldmfd sp!, {r4, pc}
+
+ .section .fixup,"ax"
+ .align 0
+9001: mov r3, #0
+ strh r3, [r0], #2
+ mov r0, #2
+ ldmfd sp!, {r4, pc}
+ .previous
diff --git a/drivers/dsp/dspgateway/uaccess_dsp.h b/drivers/dsp/dspgateway/uaccess_dsp.h
new file mode 100644
index 0000000..028814f
--- /dev/null
+++ b/drivers/dsp/dspgateway/uaccess_dsp.h
@@ -0,0 +1,176 @@
+/*
+ * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
+ *
+ * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef _OMAP_DSP_UACCESS_DSP_H
+#define _OMAP_DSP_UACCESS_DSP_H
+
+#include <asm/uaccess.h>
+#include <asm/arch/dsp_common.h>
+#include "dsp.h"
+
+#define HAVE_ASM_COPY_FROM_USER_DSP_2B
+
+#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
+extern unsigned long __copy_from_user_dsp_2b(void *to,
+ const void __user *from);
+extern unsigned long __copy_to_user_dsp_2b(void __user *to,
+ const void *from);
+#endif
+
+#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
+static inline unsigned long copy_from_user_dsp_2b(void *to,
+ const void *from)
+{
+ unsigned short tmp;
+
+ if (__copy_from_user(&tmp, from, 2))
+ return 2;
+ /* expecting compiler to generate "strh" instruction */
+ *((unsigned short *)to) = tmp;
+ return 0;
+}
+#endif
+
+/*
+ * @n must be multiple of 2
+ */
+static inline unsigned long copy_from_user_dsp(void *to, const void *from,
+ unsigned long n)
+{
+ if (access_ok(VERIFY_READ, from, n)) {
+ if ((is_dsp_internal_mem(to)) &&
+ (((unsigned long)to & 2) || (n & 2))) {
+ /*
+ * DARAM/SARAM with odd word alignment
+ */
+ unsigned long n4;
+ unsigned long last_n;
+
+ /* dest not aligned -- copy 2 bytes */
+ if (((unsigned long)to & 2) && (n >= 2)) {
+#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
+ if (__copy_from_user_dsp_2b(to, from))
+#else
+ if (copy_from_user_dsp_2b(to, from))
+#endif
+ return n;
+ to += 2;
+ from += 2;
+ n -= 2;
+ }
+ /* middle 4*n bytes */
+ last_n = n & 2;
+ n4 = n - last_n;
+ if ((n = __copy_from_user(to, from, n4)) != 0)
+ return n + last_n;
+ /* last 2 bytes */
+ if (last_n) {
+ to += n4;
+ from += n4;
+#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
+ if (__copy_from_user_dsp_2b(to, from))
+#else
+ if (copy_from_user_dsp_2b(to, from))
+#endif
+ return 2;
+ n = 0;
+ }
+ } else {
+ /*
+ * DARAM/SARAM with 4-byte alignment or
+ * external memory
+ */
+ n = __copy_from_user(to, from, n);
+ }
+ }
+ else /* security hole - plug it */
+ memzero(to, n);
+ return n;
+}
+
+#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
+static inline unsigned long copy_to_user_dsp_2b(void *to, const void *from)
+{
+ /* expecting compiler to generate "strh" instruction */
+ unsigned short tmp = *(unsigned short *)from;
+
+ return __copy_to_user(to, &tmp, 2);
+}
+#endif
+
+/*
+ * @n must be multiple of 2
+ */
+static inline unsigned long copy_to_user_dsp(void *to, const void *from,
+ unsigned long n)
+{
+ if (access_ok(VERIFY_WRITE, to, n)) {
+ if ((is_dsp_internal_mem(from)) &&
+ (((unsigned long)to & 2) || (n & 2))) {
+ /*
+ * DARAM/SARAM with odd word alignment
+ */
+ unsigned long n4;
+ unsigned long last_n;
+
+ /* dest not aligned -- copy 2 bytes */
+ if (((unsigned long)to & 2) && (n >= 2)) {
+#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
+ if (__copy_to_user_dsp_2b(to, from))
+#else
+ if (copy_to_user_dsp_2b(to, from))
+#endif
+ return n;
+ to += 2;
+ from += 2;
+ n -= 2;
+ }
+ /* middle 4*n bytes */
+ last_n = n & 2;
+ n4 = n - last_n;
+ if ((n = __copy_to_user(to, from, n4)) != 0)
+ return n + last_n;
+ /* last 2 bytes */
+ if (last_n) {
+ to += n4;
+ from += n4;
+#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
+ if (__copy_to_user_dsp_2b(to, from))
+#else
+ if (copy_to_user_dsp_2b(to, from))
+#endif
+ return 2;
+ n = 0;
+ }
+ } else {
+ /*
+ * DARAM/SARAM with 4-byte alignment or
+ * external memory
+ */
+ n = __copy_to_user(to, from, n);
+ }
+ }
+ return n;
+}
+
+#endif /* _OMAP_DSP_UACCESS_DSP_H */
diff --git a/include/asm-arm/arch-omap/mmu.h b/include/asm-arm/arch-omap/mmu.h
index 6c5869c..714ee1d 100644
--- a/include/asm-arm/arch-omap/mmu.h
+++ b/include/asm-arm/arch-omap/mmu.h
@@ -59,6 +59,16 @@ struct omap_mmu_tlb_lock {
struct omap_mmu;
struct omap_mmu_tlb_entry;
+#ifdef CONFIG_ARCH_OMAP1
+extern struct omap_mmu_ops omap1_mmu_ops;
+extern void omap_mmu_itack(struct omap_mmu *mmu);
+#elif defined(CONFIG_ARCH_OMAP2)
+extern struct omap_mmu_ops omap2_mmu_ops;
+static inline void omap_mmu_itack(struct omap_mmu *mmu)
+{
+}
+#endif
+
struct omap_mmu_ops {
int (*startup)(struct omap_mmu *mmu);
void (*shutdown)(struct omap_mmu *mmu);
--
1.5.3.6.GIT
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
2007-11-28 5:18 [PATCH 1/2] DSP: Move code to use only one dsp_common.h Tony Lindgren
2007-11-28 5:20 ` [PATCH 2/2] DSP: Move dspgateway to drivers/dsp/dspgateway Tony Lindgren
@ 2007-11-28 9:54 ` Hiroshi DOYU
2007-11-28 16:57 ` Tony Lindgren
1 sibling, 1 reply; 11+ messages in thread
From: Hiroshi DOYU @ 2007-11-28 9:54 UTC (permalink / raw)
To: tony; +Cc: linux-omap, linux-omap-open-source
Hi Tony,
From: "ext Tony Lindgren" <tony@atomide.com>
Subject: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
Date: Tue, 27 Nov 2007 21:18:12 -0800
> Hi all,
>
> As discussed earlier, here are the patches to move dspgateway
> to under drivers.
>
> Hiroshi san & Toshihiro san, can you take a quick look at these
> two patches and ack?
>
> I've only compile tested on osk and n800. There should not be any
> functional changes. Some inline functions I had to export though.
Thank you for the patch, but it doesn't seem to work. I am
now investigating....
At least, I'd like to make sure that the code itself works fine at
this migration both on N8x0 and OSK.
Hiroshi DOYU
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
2007-11-28 9:54 ` [PATCH 1/2] DSP: Move code to use only one dsp_common.h Hiroshi DOYU
@ 2007-11-28 16:57 ` Tony Lindgren
2007-11-28 23:35 ` Tony Lindgren
0 siblings, 1 reply; 11+ messages in thread
From: Tony Lindgren @ 2007-11-28 16:57 UTC (permalink / raw)
To: Hiroshi DOYU; +Cc: linux-omap, linux-omap-open-source
* Hiroshi DOYU <Hiroshi.DOYU@nokia.com> [071128 01:55]:
> Hi Tony,
>
> From: "ext Tony Lindgren" <tony@atomide.com>
> Subject: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
> Date: Tue, 27 Nov 2007 21:18:12 -0800
>
> > Hi all,
> >
> > As discussed earlier, here are the patches to move dspgateway
> > to under drivers.
> >
> > Hiroshi san & Toshihiro san, can you take a quick look at these
> > two patches and ack?
> >
> > I've only compile tested on osk and n800. There should not be any
> > functional changes. Some inline functions I had to export though.
>
> Thank you for the patch, but it doesn't seem to work. I am
> now investigating....
Oops, does the DSP get initialized?
> At least, I'd like to make sure that the code itself works fine at
> this migration both on N8x0 and OSK.
Yes that would be great :)
Tony
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
2007-11-28 16:57 ` Tony Lindgren
@ 2007-11-28 23:35 ` Tony Lindgren
2007-11-29 17:03 ` Hiroshi DOYU
0 siblings, 1 reply; 11+ messages in thread
From: Tony Lindgren @ 2007-11-28 23:35 UTC (permalink / raw)
To: Hiroshi DOYU; +Cc: linux-omap, linux-omap-open-source
[-- Attachment #1: Type: text/plain, Size: 1060 bytes --]
* Tony Lindgren <tony@atomide.com> [071128 08:59]:
> * Hiroshi DOYU <Hiroshi.DOYU@nokia.com> [071128 01:55]:
> > Hi Tony,
> >
> > From: "ext Tony Lindgren" <tony@atomide.com>
> > Subject: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
> > Date: Tue, 27 Nov 2007 21:18:12 -0800
> >
> > > Hi all,
> > >
> > > As discussed earlier, here are the patches to move dspgateway
> > > to under drivers.
> > >
> > > Hiroshi san & Toshihiro san, can you take a quick look at these
> > > two patches and ack?
> > >
> > > I've only compile tested on osk and n800. There should not be any
> > > functional changes. Some inline functions I had to export though.
> >
> > Thank you for the patch, but it doesn't seem to work. I am
> > now investigating....
>
> Oops, does the DSP get initialized?
>
> > At least, I'd like to make sure that the code itself works fine at
> > this migration both on N8x0 and OSK.
>
> Yes that would be great :)
No idea why it would not work, but here's one more clean-up patch in
order to send the MMU framework upstream.
Tony
[-- Attachment #2: dsp-allocation.patch --]
[-- Type: text/x-diff, Size: 5128 bytes --]
>From 870324f3b330e7df6e5391b1c379c029b6c9f5f3 Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Wed, 28 Nov 2007 15:33:49 -0800
Subject: [PATCH] DSP: Clean up memory allocation return values
Clean up memory allocation return values
Signed-off-by: Tony Lindgren <tony@atomide.com>
diff --git a/arch/arm/mach-omap1/mmu.c b/arch/arm/mach-omap1/mmu.c
index c7cb4ff..2d05708 100644
--- a/arch/arm/mach-omap1/mmu.c
+++ b/arch/arm/mach-omap1/mmu.c
@@ -32,7 +32,6 @@
#include <linux/err.h>
#include "mmu.h"
#include <asm/tlbflush.h>
-#include <asm/arch/dsp.h>
#include <asm/arch/dsp_common.h>
static void *dspvect_page;
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index a17b5ae..4083cf5 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -28,8 +28,8 @@
#include <asm/arch/dma.h>
#include <asm/arch/mux.h>
#include <asm/arch/irqs.h>
-#include <asm/arch/mcbsp.h>
#include <asm/arch/dsp_common.h>
+#include <asm/arch/mcbsp.h>
#ifdef CONFIG_MCBSP_DEBUG
#define DBG(x...) printk(x)
@@ -197,7 +197,14 @@ static int omap_mcbsp_check(unsigned int id)
static void omap_mcbsp_dsp_request(void)
{
if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
- omap_dsp_request_mem();
+ int ret;
+
+ ret = omap_dsp_request_mem();
+ if (ret < 0) {
+ printk(KERN_ERR "Could not get dsp memory: %i\n", ret);
+ return;
+ }
+
clk_enable(mcbsp_dsp_ck);
clk_enable(mcbsp_api_ck);
diff --git a/arch/arm/plat-omap/mmu.c b/arch/arm/plat-omap/mmu.c
index c92afd6..c80d411 100644
--- a/arch/arm/plat-omap/mmu.c
+++ b/arch/arm/plat-omap/mmu.c
@@ -588,9 +588,12 @@ int omap_mmu_load_tlb_entry(struct omap_mmu *mmu,
{
struct omap_mmu_tlb_lock lock;
struct cam_ram_regset *cr;
+ int ret;
clk_enable(mmu->clk);
- omap_dsp_request_mem();
+ ret = omap_dsp_request_mem();
+ if (ret < 0)
+ goto out;
omap_mmu_get_tlb_lock(mmu, &lock);
for (lock.victim = 0; lock.victim < lock.base; lock.victim++) {
@@ -624,6 +627,7 @@ found_victim:
omap_mmu_set_tlb_lock(mmu, &lock);
omap_dsp_release_mem();
+out:
clk_disable(mmu->clk);
return 0;
}
@@ -638,11 +642,13 @@ omap_mmu_cam_va(struct omap_mmu *mmu, struct cam_ram_regset *cr)
int omap_mmu_clear_tlb_entry(struct omap_mmu *mmu, unsigned long vadr)
{
struct omap_mmu_tlb_lock lock;
- int i;
+ int i, ret = 0;
int max_valid = 0;
clk_enable(mmu->clk);
- omap_dsp_request_mem();
+ ret = omap_dsp_request_mem();
+ if (ret < 0)
+ goto out;
omap_mmu_get_tlb_lock(mmu, &lock);
for (i = 0; i < lock.base; i++) {
@@ -666,23 +672,28 @@ int omap_mmu_clear_tlb_entry(struct omap_mmu *mmu, unsigned long vadr)
omap_mmu_set_tlb_lock(mmu, &lock);
omap_dsp_release_mem();
+out:
clk_disable(mmu->clk);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(omap_mmu_clear_tlb_entry);
static void omap_mmu_gflush(struct omap_mmu *mmu)
{
struct omap_mmu_tlb_lock lock;
+ int ret;
clk_enable(mmu->clk);
- omap_dsp_request_mem();
+ ret = omap_dsp_request_mem();
+ if (ret < 0)
+ goto out;
omap_mmu_write_reg(mmu, 0x1, OMAP_MMU_GFLUSH);
lock.base = lock.victim = mmu->nr_exmap_preserved;
omap_mmu_set_tlb_lock(mmu, &lock);
omap_dsp_release_mem();
+out:
clk_disable(mmu->clk);
}
@@ -1073,7 +1084,10 @@ static int omap_mmu_init(struct omap_mmu *mmu)
int ret = 0;
clk_enable(mmu->clk);
- omap_dsp_request_mem();
+ ret = omap_dsp_request_mem();
+ if (ret < 0)
+ goto out;
+
down_write(&mmu->exmap_sem);
ret = request_irq(mmu->irq, omap_mmu_interrupt, IRQF_DISABLED,
@@ -1093,9 +1107,10 @@ static int omap_mmu_init(struct omap_mmu *mmu)
if (unlikely(mmu->ops->startup))
ret = mmu->ops->startup(mmu);
- fail:
+fail:
up_write(&mmu->exmap_sem);
omap_dsp_release_mem();
+out:
clk_disable(mmu->clk);
return ret;
@@ -1309,15 +1324,18 @@ static ssize_t omap_mmu_show(struct device *dev, struct device_attribute *attr,
{
struct omap_mmu *mmu = dev_get_drvdata(dev);
struct omap_mmu_tlb_lock tlb_lock;
- int ret = -EIO;
+ int ret;
clk_enable(mmu->clk);
- omap_dsp_request_mem();
+ ret = omap_dsp_request_mem();
+ if (ret < 0)
+ goto out;
down_read(&mmu->exmap_sem);
omap_mmu_get_tlb_lock(mmu, &tlb_lock);
+ ret = -EIO;
if (likely(mmu->ops->show))
ret = mmu->ops->show(mmu, buf, &tlb_lock);
@@ -1326,6 +1344,7 @@ static ssize_t omap_mmu_show(struct device *dev, struct device_attribute *attr,
up_read(&mmu->exmap_sem);
omap_dsp_release_mem();
+out:
clk_disable(mmu->clk);
return ret;
diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h
index a11deed..c52b6c6 100644
--- a/include/asm-arm/arch-omap/dsp_common.h
+++ b/include/asm-arm/arch-omap/dsp_common.h
@@ -66,8 +66,11 @@ extern void omap_dsp_release_mpui(void);
extern int omap_dsp_request_mem(void);
extern int omap_dsp_release_mem(void);
#elif defined(CONFIG_ARCH_OMAP2)
-#define omap_dsp_request_mem() do { } while (0)
-#define omap_dsp_release_mem() do { } while (0)
+static inline int omap_dsp_request_mem(void)
+{
+ return 0;
+}
+#define omap_dsp_release_mem() do {} while (0)
#endif
#endif /* ASM_ARCH_DSP_COMMON_H */
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
2007-11-28 23:35 ` Tony Lindgren
@ 2007-11-29 17:03 ` Hiroshi DOYU
2007-11-29 17:55 ` Tony Lindgren
0 siblings, 1 reply; 11+ messages in thread
From: Hiroshi DOYU @ 2007-11-29 17:03 UTC (permalink / raw)
To: tony; +Cc: linux-omap, linux-omap-open-source
Hi Tony,
From: "ext Tony Lindgren" <tony@atomide.com>
Subject: Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
Date: Wed, 28 Nov 2007 15:35:24 -0800
> * Tony Lindgren <tony@atomide.com> [071128 08:59]:
> > * Hiroshi DOYU <Hiroshi.DOYU@nokia.com> [071128 01:55]:
> > > Hi Tony,
> > >
> > > From: "ext Tony Lindgren" <tony@atomide.com>
> > > Subject: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
> > > Date: Tue, 27 Nov 2007 21:18:12 -0800
> > >
> > > > Hi all,
> > > >
> > > > As discussed earlier, here are the patches to move dspgateway
> > > > to under drivers.
> > > >
> > > > Hiroshi san & Toshihiro san, can you take a quick look at these
> > > > two patches and ack?
> > > >
> > > > I've only compile tested on osk and n800. There should not be any
> > > > functional changes. Some inline functions I had to export though.
> > >
> > > Thank you for the patch, but it doesn't seem to work. I am
> > > now investigating....
> >
> > Oops, does the DSP get initialized?
> >
> > > At least, I'd like to make sure that the code itself works fine at
> > > this migration both on N8x0 and OSK.
> >
> > Yes that would be great :)
>
> No idea why it would not work, but here's one more clean-up patch in
> order to send the MMU framework upstream.
With OSK5912, I verified that the demo program("demo_console") worked
fine with your 3 patches. Probably something was broken just with
OMAP2. I am checking it bit more.
Hiroshi DOYU
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
2007-11-29 17:03 ` Hiroshi DOYU
@ 2007-11-29 17:55 ` Tony Lindgren
2007-11-30 20:02 ` Tony Lindgren
0 siblings, 1 reply; 11+ messages in thread
From: Tony Lindgren @ 2007-11-29 17:55 UTC (permalink / raw)
To: Hiroshi DOYU; +Cc: linux-omap, linux-omap-open-source
* Hiroshi DOYU <Hiroshi.DOYU@nokia.com> [071129 09:04]:
> Hi Tony,
>
> From: "ext Tony Lindgren" <tony@atomide.com>
> Subject: Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
> Date: Wed, 28 Nov 2007 15:35:24 -0800
>
> > * Tony Lindgren <tony@atomide.com> [071128 08:59]:
> > > * Hiroshi DOYU <Hiroshi.DOYU@nokia.com> [071128 01:55]:
> > > > Hi Tony,
> > > >
> > > > From: "ext Tony Lindgren" <tony@atomide.com>
> > > > Subject: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
> > > > Date: Tue, 27 Nov 2007 21:18:12 -0800
> > > >
> > > > > Hi all,
> > > > >
> > > > > As discussed earlier, here are the patches to move dspgateway
> > > > > to under drivers.
> > > > >
> > > > > Hiroshi san & Toshihiro san, can you take a quick look at these
> > > > > two patches and ack?
> > > > >
> > > > > I've only compile tested on osk and n800. There should not be any
> > > > > functional changes. Some inline functions I had to export though.
> > > >
> > > > Thank you for the patch, but it doesn't seem to work. I am
> > > > now investigating....
> > >
> > > Oops, does the DSP get initialized?
> > >
> > > > At least, I'd like to make sure that the code itself works fine at
> > > > this migration both on N8x0 and OSK.
> > >
> > > Yes that would be great :)
> >
> > No idea why it would not work, but here's one more clean-up patch in
> > order to send the MMU framework upstream.
>
> With OSK5912, I verified that the demo program("demo_console") worked
> fine with your 3 patches. Probably something was broken just with
> OMAP2. I am checking it bit more.
OK, that's good to hear. Let's wait until you're happy before pushing
this.
Tony
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
2007-11-29 17:55 ` Tony Lindgren
@ 2007-11-30 20:02 ` Tony Lindgren
2007-12-03 8:56 ` Hiroshi DOYU
0 siblings, 1 reply; 11+ messages in thread
From: Tony Lindgren @ 2007-11-30 20:02 UTC (permalink / raw)
To: Hiroshi DOYU; +Cc: linux-omap, linux-omap-open-source
Hi,
* Tony Lindgren <tony@atomide.com> [071129 09:58]:
> * Hiroshi DOYU <Hiroshi.DOYU@nokia.com> [071129 09:04]:
> > Hi Tony,
> >
> > From: "ext Tony Lindgren" <tony@atomide.com>
> > Subject: Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
> > Date: Wed, 28 Nov 2007 15:35:24 -0800
> >
> > > * Tony Lindgren <tony@atomide.com> [071128 08:59]:
> > > > * Hiroshi DOYU <Hiroshi.DOYU@nokia.com> [071128 01:55]:
> > > > > Hi Tony,
> > > > >
> > > > > From: "ext Tony Lindgren" <tony@atomide.com>
> > > > > Subject: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
> > > > > Date: Tue, 27 Nov 2007 21:18:12 -0800
> > > > >
> > > > > > Hi all,
> > > > > >
> > > > > > As discussed earlier, here are the patches to move dspgateway
> > > > > > to under drivers.
> > > > > >
> > > > > > Hiroshi san & Toshihiro san, can you take a quick look at these
> > > > > > two patches and ack?
> > > > > >
> > > > > > I've only compile tested on osk and n800. There should not be any
> > > > > > functional changes. Some inline functions I had to export though.
> > > > >
> > > > > Thank you for the patch, but it doesn't seem to work. I am
> > > > > now investigating....
> > > >
> > > > Oops, does the DSP get initialized?
> > > >
> > > > > At least, I'd like to make sure that the code itself works fine at
> > > > > this migration both on N8x0 and OSK.
> > > >
> > > > Yes that would be great :)
> > >
> > > No idea why it would not work, but here's one more clean-up patch in
> > > order to send the MMU framework upstream.
> >
> > With OSK5912, I verified that the demo program("demo_console") worked
> > fine with your 3 patches. Probably something was broken just with
> > OMAP2. I am checking it bit more.
>
> OK, that's good to hear. Let's wait until you're happy before pushing
> this.
I've pushed these patches, Hiroshi is looking into why omap2 dsp is
not currently working while omap1 is. It seems the problem is unrelated
to these patches.
Regards,
Tony
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
2007-11-30 20:02 ` Tony Lindgren
@ 2007-12-03 8:56 ` Hiroshi DOYU
2007-12-03 10:33 ` Trilok Soni
0 siblings, 1 reply; 11+ messages in thread
From: Hiroshi DOYU @ 2007-12-03 8:56 UTC (permalink / raw)
To: tony; +Cc: linux-omap, linux-omap-open-source
From: "ext Tony Lindgren" <tony@atomide.com>
Subject: Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
Date: Fri, 30 Nov 2007 12:02:22 -0800
> > > With OSK5912, I verified that the demo program("demo_console") worked
> > > fine with your 3 patches. Probably something was broken just with
> > > OMAP2. I am checking it bit more.
> >
> > OK, that's good to hear. Let's wait until you're happy before pushing
> > this.
>
> I've pushed these patches, Hiroshi is looking into why omap2 dsp is
> not currently working while omap1 is. It seems the problem is unrelated
> to these patches.
Actually dspgw itself is basically working with omap2 also. Probably
there seems to be some missing update patches from N8x0 for other
drivers, which are supposed to come soon.
Anyway, thank you for you patches.
Hiroshi DOYU
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
2007-12-03 8:56 ` Hiroshi DOYU
@ 2007-12-03 10:33 ` Trilok Soni
2007-12-03 11:03 ` Hiroshi DOYU
0 siblings, 1 reply; 11+ messages in thread
From: Trilok Soni @ 2007-12-03 10:33 UTC (permalink / raw)
To: Hiroshi DOYU; +Cc: linux-omap, linux-omap-open-source
Hi,
On Dec 3, 2007 2:26 PM, Hiroshi DOYU <Hiroshi.DOYU@nokia.com> wrote:
> From: "ext Tony Lindgren" <tony@atomide.com>
> Subject: Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
> Date: Fri, 30 Nov 2007 12:02:22 -0800
>
> > > > With OSK5912, I verified that the demo program("demo_console") worked
> > > > fine with your 3 patches. Probably something was broken just with
> > > > OMAP2. I am checking it bit more.
> > >
> > > OK, that's good to hear. Let's wait until you're happy before pushing
> > > this.
> >
> > I've pushed these patches, Hiroshi is looking into why omap2 dsp is
> > not currently working while omap1 is. It seems the problem is unrelated
> > to these patches.
>
> Actually dspgw itself is basically working with omap2 also. Probably
> there seems to be some missing update patches from N8x0 for other
> drivers, which are supposed to come soon.
>
> Anyway, thank you for you patches.
>
> Hiroshi DOYU
>
Is there any plan to move dspgw code to use "dspfs" instead?
-- --Trilok Soni
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
2007-12-03 10:33 ` Trilok Soni
@ 2007-12-03 11:03 ` Hiroshi DOYU
0 siblings, 0 replies; 11+ messages in thread
From: Hiroshi DOYU @ 2007-12-03 11:03 UTC (permalink / raw)
To: soni.trilok; +Cc: linux-omap, linux-omap-open-source
Hi Trilok,
From: "ext Trilok Soni" <soni.trilok@gmail.com>
Subject: Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
Date: Mon, 3 Dec 2007 16:03:25 +0530
> Hi,
>
> On Dec 3, 2007 2:26 PM, Hiroshi DOYU <Hiroshi.DOYU@nokia.com> wrote:
> > From: "ext Tony Lindgren" <tony@atomide.com>
> > Subject: Re: [PATCH 1/2] DSP: Move code to use only one dsp_common.h
> > Date: Fri, 30 Nov 2007 12:02:22 -0800
> >
> > > > > With OSK5912, I verified that the demo program("demo_console") worked
> > > > > fine with your 3 patches. Probably something was broken just with
> > > > > OMAP2. I am checking it bit more.
> > > >
> > > > OK, that's good to hear. Let's wait until you're happy before pushing
> > > > this.
> > >
> > > I've pushed these patches, Hiroshi is looking into why omap2 dsp is
> > > not currently working while omap1 is. It seems the problem is unrelated
> > > to these patches.
> >
> > Actually dspgw itself is basically working with omap2 also. Probably
> > there seems to be some missing update patches from N8x0 for other
> > drivers, which are supposed to come soon.
> >
> > Anyway, thank you for you patches.
> >
> > Hiroshi DOYU
> >
>
> Is there any plan to move dspgw code to use "dspfs" instead?
No, we don't have any plan, unfortunately.
Hiroshi DOYU
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2007-12-03 11:03 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-28 5:18 [PATCH 1/2] DSP: Move code to use only one dsp_common.h Tony Lindgren
2007-11-28 5:20 ` [PATCH 2/2] DSP: Move dspgateway to drivers/dsp/dspgateway Tony Lindgren
2007-11-28 9:54 ` [PATCH 1/2] DSP: Move code to use only one dsp_common.h Hiroshi DOYU
2007-11-28 16:57 ` Tony Lindgren
2007-11-28 23:35 ` Tony Lindgren
2007-11-29 17:03 ` Hiroshi DOYU
2007-11-29 17:55 ` Tony Lindgren
2007-11-30 20:02 ` Tony Lindgren
2007-12-03 8:56 ` Hiroshi DOYU
2007-12-03 10:33 ` Trilok Soni
2007-12-03 11:03 ` Hiroshi DOYU
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox