2 * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
4 * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
6 * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 #include <linux/module.h>
26 #include <linux/device.h>
27 #include <linux/init.h>
28 #include <linux/sched.h>
29 #include <linux/delay.h>
30 #include <linux/platform_device.h>
31 #include <linux/clk.h>
32 #include <linux/mutex.h>
33 #include <asm/uaccess.h>
35 #include <asm/ioctls.h>
36 #include <mach/mailbox.h>
38 #include "hardware_dsp.h"
39 #include "dsp_mbcmd.h"
48 #ifdef CONFIG_OMAP_DSP_FBEXPORT
49 static enum fbstat_e {
53 } fbstat = FBSTAT_ENABLED;
56 static enum cfgstat_e cfgstat;
60 static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
62 static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
64 static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
66 static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
67 const char *buf, size_t count);
68 static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
71 #define __ATTR_RW(_name, _mode) { \
72 .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
73 .show = _name##_show, \
74 .store = _name##_store, \
77 static struct device_attribute dev_attr_ifver = __ATTR_RO(ifver);
78 static struct device_attribute dev_attr_cpustat = __ATTR_RO(cpustat);
79 static struct device_attribute dev_attr_icrmask = __ATTR_RW(icrmask, 0644);
80 static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo);
83 * misc interactive mailbox command operations
85 static struct misc_mb_wait_struct {
87 wait_queue_head_t wait_q;
92 .lock = __MUTEX_INITIALIZER(misc_mb_wait.lock),
93 .wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(misc_mb_wait.wait_q),
96 static int __misc_mbcompose_send_and_wait(u8 cmd_h, u8 cmd_l, u16 data,
99 struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data);
102 if (mutex_lock_interruptible(&misc_mb_wait.lock))
105 misc_mb_wait.cmd_h = mb.cmd_h;
106 misc_mb_wait.cmd_l = mb.cmd_l;
107 misc_mb_wait.retvp = retvp;
108 dsp_mbcmd_send_and_wait(&mb, &misc_mb_wait.wait_q);
110 if (misc_mb_wait.cmd_h != 0)
113 mutex_unlock(&misc_mb_wait.lock);
117 #define misc_mbcompose_send_and_wait(cmd_h, cmd_l, data, retvp) \
118 __misc_mbcompose_send_and_wait(MBOX_CMD_DSP_##cmd_h, (cmd_l), \
121 static int misc_mbcmd_response(struct mbcmd *mb, int argc, int match_cmd_l_flag)
126 /* if match_cmd_l_v flag is set, cmd_l needs to be matched as well. */
127 if (!waitqueue_active(&misc_mb_wait.wait_q) ||
128 (misc_mb_wait.cmd_h != mb->cmd_h) ||
129 (match_cmd_l_flag && (misc_mb_wait.cmd_l != mb->cmd_l))) {
130 const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
133 if (ci->cmd_l_type == CMD_L_TYPE_SUBCMD)
134 sprintf(cmdstr, "%s:%s", ci->name, subcmd_name(mb));
136 strcpy(cmdstr, ci->name);
138 "mbox: unexpected command %s received!\n", cmdstr);
143 * if argc == 1, receive data through mbox:data register.
144 * if argc > 1, receive through ipbuf_sys.
147 misc_mb_wait.retvp[0] = mb->data;
149 if (dsp_mem_enable(ipbuf_sys_da) < 0) {
150 printk(KERN_ERR "mbox: %s - ipbuf_sys_da read failed!\n",
151 cmdinfo[mb->cmd_h]->name);
154 if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
155 printk(KERN_ERR "mbox: %s - IPBUF sync failed!\n",
156 cmdinfo[mb->cmd_h]->name);
157 dsp_mem_disable(ipbuf_sys_da);
160 /* need word access. do not use memcpy. */
161 buf = ipbuf_sys_da->d;
162 for (i = 0; i < argc; i++)
163 misc_mb_wait.retvp[i] = buf[i];
164 release_ipbuf_pvt(ipbuf_sys_da);
165 dsp_mem_disable(ipbuf_sys_da);
168 misc_mb_wait.cmd_h = 0;
169 wake_up_interruptible(&misc_mb_wait.wait_q);
173 static int dsp_regread(enum dsp_space_e space, u16 adr, u16 *val)
175 u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMR : REGRW_IOR;
178 ret = misc_mbcompose_send_and_wait(REGRW, cmd_l, adr, val);
179 if ((ret < 0) && (ret != -EINTR))
180 printk(KERN_ERR "omapdsp: register read error!\n");
185 static int dsp_regwrite(enum dsp_space_e space, u16 adr, u16 val)
187 u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMW : REGRW_IOW;
188 struct mb_exarg arg = {
194 mbcompose_send_exarg(REGRW, cmd_l, adr, &arg);
198 static int dsp_getvar(u8 varid, u16 *val)
202 ret = misc_mbcompose_send_and_wait(GETVAR, varid, 0, val);
203 if ((ret < 0) && (ret != -EINTR))
204 printk(KERN_ERR "omapdsp: variable read error!\n");
209 static int dsp_setvar(u8 varid, u16 val)
211 mbcompose_send(SETVAR, varid, val);
216 * dsp_cfg() return value
218 * = 1: failed, but state is clear. (DSPCFG command failed)
219 * < 0: failed. need cleanup.
221 static int dsp_cfg(void)
225 #ifdef CONFIG_ARCH_OMAP1
227 dsp_mem_usecount_clear();
231 * DSPCFG command and dsp_mem_start() must be called
232 * while internal mem is on.
234 dsp_mem_enable((void *)dspmem_base);
243 ret = misc_mbcompose_send_and_wait(DSPCFG, DSPCFG_REQ, 0, NULL);
246 printk(KERN_ERR "omapdsp: configuration error!\n");
251 #if defined(CONFIG_ARCH_OMAP1) && defined(OLD_BINARY_SUPPORT)
253 * MBREV 3.2 or earlier doesn't assume DMA domain is on
254 * when DSPCFG command is sent
256 if ((mbox_revision == MBREV_3_0) ||
257 (mbox_revision == MBREV_3_2)) {
258 if ((ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA)) < 0)
263 if ((ret = dsp_task_config_all(n_stask)) < 0)
267 #ifdef CONFIG_OMAP_DSP_FBEXPORT
268 fbstat = FBSTAT_ENABLED;
272 ret = dsp_setvar(VARID_ICRMASK, dsp_cpustat_get_icrmask());
276 /* create runtime sysfs entries */
277 ret = device_create_file(omap_dsp->dev, &dev_attr_loadinfo);
279 printk(KERN_ERR "device_create_file failed: %d\n", ret);
281 dsp_mem_disable((void *)dspmem_base);
285 static int dsp_uncfg(void)
287 if (dsp_taskmod_busy()) {
288 printk(KERN_WARNING "omapdsp: tasks are busy.\n");
292 /* FIXME: lock task module */
294 /* remove runtime sysfs entries */
295 device_remove_file(omap_dsp->dev, &dev_attr_loadinfo);
302 dsp_task_unconfig_all();
308 static int dsp_suspend(void)
312 ret = misc_mbcompose_send_and_wait(SUSPEND, 0, 0, NULL);
315 printk(KERN_ERR "omapdsp: DSP suspend error!\n");
319 udelay(100); /* wait for DSP-side execution */
323 int dsp_cfgstat_request(enum cfgstat_e st_req)
325 static DEFINE_MUTEX(cfgstat_lock);
326 int ret = 0, ret_override = 0;
328 if (mutex_lock_interruptible(&cfgstat_lock))
334 /* cfgstat takes CLEAN, READY or SUSPEND,
335 while st_req can take SUSPEND in addition. */
338 if (cfgstat == CFGSTAT_CLEAN)
340 if ((ret = dsp_uncfg()) < 0)
345 if (cfgstat != CFGSTAT_CLEAN) {
346 printk(KERN_ERR "omapdsp: DSP is ready already!\n");
352 if (ret > 0) { /* failed, but state is clear. */
355 } else if (ret < 0) { /* failed, need cleanup. */
356 st_req = CFGSTAT_CLEAN;
364 * DSP is not reset within this code, but done in omap_pm_suspend.
365 * so if these functions are called from sysfs,
366 * DSP should be reset / unreset out of these functions.
368 case CFGSTAT_SUSPEND:
372 if (dsp_cpustat_get_stat() == CPUSTAT_RUN) {
374 "omapdsp: illegal operation -- trying "
375 "suspend DSP while it is running but "
377 " Resetting DSP.\n");
378 dsp_cpustat_request(CPUSTAT_RESET);
384 if ((ret = dsp_suspend()) < 0)
388 case CFGSTAT_SUSPEND:
399 if (cfgstat != CFGSTAT_SUSPEND) {
401 "omapdsp: DSP resume request, but DSP is not in "
406 st_req = CFGSTAT_READY;
416 mutex_unlock(&cfgstat_lock);
417 return ret_override ? ret_override : ret;
420 enum cfgstat_e dsp_cfgstat_get_stat(void)
428 static int dsp_poll(void)
432 ret = misc_mbcompose_send_and_wait(POLL, 0, 0, NULL);
433 if ((ret < 0) && (ret != -EINTR))
434 printk(KERN_ERR "omapdsp: poll error!\n");
439 int dsp_set_runlevel(u8 level)
441 if (level == RUNLEVEL_RECOVERY) {
442 if (mbcompose_send_recovery(RUNLEVEL, level, 0) < 0)
445 if ((level < RUNLEVEL_USER) ||
446 (level > RUNLEVEL_SUPER))
448 if (mbcompose_send(RUNLEVEL, level, 0) < 0)
455 #ifdef CONFIG_OMAP_DSP_FBEXPORT
456 static void dsp_fbctl_enable(void)
458 mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_ENABLE);
461 static int dsp_fbctl_disable(void)
465 ret = misc_mbcompose_send_and_wait(KFUNC, KFUNC_FBCTL, FBCTL_DISABLE,
467 if ((ret < 0) && (ret != -EINTR))
468 printk(KERN_ERR "omapdsp: fb disable error!\n");
473 static int dsp_fbstat_request(enum fbstat_e st)
475 static DEFINE_MUTEX(fbstat_lock);
478 if (mutex_lock_interruptible(&fbstat_lock))
488 case FBSTAT_DISABLED:
489 if ((ret = dsp_fbctl_disable()) < 0)
498 mutex_unlock(&fbstat_lock);
501 #endif /* CONFIG_OMAP_DSP_FBEXPORT */
504 * DSP control device file operations
506 static int dsp_ctl_ioctl(struct inode *inode, struct file *file,
507 unsigned int cmd, unsigned long arg)
513 * command level 1: commands which don't need lock
515 case DSPCTL_IOCTL_RUN:
516 dsp_cpustat_request(CPUSTAT_RUN);
519 case DSPCTL_IOCTL_RESET:
520 dsp_cpustat_request(CPUSTAT_RESET);
523 case DSPCTL_IOCTL_SETRSTVECT:
524 ret = dsp_set_rstvect((dsp_long_t)arg);
527 #ifdef CONFIG_ARCH_OMAP1
528 case DSPCTL_IOCTL_CPU_IDLE:
529 dsp_cpustat_request(CPUSTAT_CPU_IDLE);
532 case DSPCTL_IOCTL_GBL_IDLE:
533 dsp_cpustat_request(CPUSTAT_GBL_IDLE);
536 case DSPCTL_IOCTL_MPUI_WORDSWAP_ON:
540 case DSPCTL_IOCTL_MPUI_WORDSWAP_OFF:
544 case DSPCTL_IOCTL_MPUI_BYTESWAP_ON:
548 case DSPCTL_IOCTL_MPUI_BYTESWAP_OFF:
551 #endif /* CONFIG_ARCH_OMAP1 */
553 case DSPCTL_IOCTL_TASKCNT:
554 ret = dsp_task_count();
557 case DSPCTL_IOCTL_MBSEND:
559 struct omap_dsp_mailbox_cmd u_cmd;
561 if (copy_from_user(&u_cmd, (void *)arg, sizeof(u_cmd)))
563 msg = (u_cmd.cmd << 16) | u_cmd.data;
564 ret = dsp_mbcmd_send((struct mbcmd *)&msg);
568 case DSPCTL_IOCTL_SETVAR:
570 struct omap_dsp_varinfo var;
571 if (copy_from_user(&var, (void *)arg, sizeof(var)))
573 ret = dsp_setvar(var.varid, var.val[0]);
577 case DSPCTL_IOCTL_RUNLEVEL:
578 ret = dsp_set_runlevel(arg);
581 #ifdef CONFIG_OMAP_DSP_FBEXPORT
582 case DSPCTL_IOCTL_FBEN:
583 ret = dsp_fbstat_request(FBSTAT_ENABLED);
588 * command level 2: commands which need lock
590 case DSPCTL_IOCTL_DSPCFG:
591 ret = dsp_cfgstat_request(CFGSTAT_READY);
594 case DSPCTL_IOCTL_DSPUNCFG:
595 ret = dsp_cfgstat_request(CFGSTAT_CLEAN);
598 case DSPCTL_IOCTL_POLL:
602 #ifdef CONFIG_OMAP_DSP_FBEXPORT
603 case DSPCTL_IOCTL_FBDIS:
604 ret = dsp_fbstat_request(FBSTAT_DISABLED);
608 case DSPCTL_IOCTL_SUSPEND:
609 if ((ret = dsp_cfgstat_request(CFGSTAT_SUSPEND)) < 0)
611 dsp_cpustat_request(CPUSTAT_RESET);
614 case DSPCTL_IOCTL_RESUME:
615 if ((ret = dsp_cfgstat_request(CFGSTAT_RESUME)) < 0)
617 dsp_cpustat_request(CPUSTAT_RUN);
620 case DSPCTL_IOCTL_REGMEMR:
622 struct omap_dsp_reginfo *u_reg = (void *)arg;
625 if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
627 if ((ret = dsp_regread(SPACE_MEM, adr, &val)) < 0)
629 if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
634 case DSPCTL_IOCTL_REGMEMW:
636 struct omap_dsp_reginfo reg;
638 if (copy_from_user(®, (void *)arg, sizeof(reg)))
640 ret = dsp_regwrite(SPACE_MEM, reg.adr, reg.val);
644 case DSPCTL_IOCTL_REGIOR:
646 struct omap_dsp_reginfo *u_reg = (void *)arg;
649 if (copy_from_user(&adr, &u_reg->adr, sizeof(u16)))
651 if ((ret = dsp_regread(SPACE_IO, adr, &val)) < 0)
653 if (copy_to_user(&u_reg->val, &val, sizeof(u16)))
658 case DSPCTL_IOCTL_REGIOW:
660 struct omap_dsp_reginfo reg;
662 if (copy_from_user(®, (void *)arg, sizeof(reg)))
664 ret = dsp_regwrite(SPACE_IO, reg.adr, reg.val);
668 case DSPCTL_IOCTL_GETVAR:
670 struct omap_dsp_varinfo *u_var = (void *)arg;
672 u16 val[5]; /* maximum */
675 if (copy_from_user(&varid, &u_var->varid, sizeof(u8)))
687 if ((ret = dsp_getvar(varid, val)) < 0)
689 if (copy_to_user(&u_var->val, val, sizeof(u16) * argc))
702 * functions called from mailbox interrupt routine
704 void mbox_suspend(struct mbcmd *mb)
706 misc_mbcmd_response(mb, 0, 0);
709 void mbox_dspcfg(struct mbcmd *mb)
711 u8 last = mb->cmd_l & 0x80;
712 u8 cfgcmd = mb->cmd_l & 0x7f;
713 static dsp_long_t tmp_ipb_adr;
715 if (!waitqueue_active(&misc_mb_wait.wait_q) ||
716 (misc_mb_wait.cmd_h != MBOX_CMD_DSP_DSPCFG)) {
718 "mbox: DSPCFG command received, "
719 "but nobody is waiting for it...\n");
723 /* mailbox protocol check */
724 if (cfgcmd == DSPCFG_PROTREV) {
725 mbox_revision = mb->data;
726 if (mbox_revision == MBPROT_REVISION)
728 #ifdef OLD_BINARY_SUPPORT
729 else if ((mbox_revision == MBREV_3_0) ||
730 (mbox_revision == MBREV_3_2)) {
732 "mbox: ***** old DSP binary *****\n"
733 " Please update your DSP application.\n");
739 "mbox: protocol revision check error!\n"
740 " expected=0x%04x, received=0x%04x\n",
741 MBPROT_REVISION, mb->data);
748 * following commands are accepted only after
749 * revision check has been passed.
751 if (!mbox_revision < 0) {
752 pr_info("mbox: DSPCFG command received, "
753 "but revision check has not been passed.\n");
759 tmp_ipb_adr = (u32)mb->data << 16;
763 tmp_ipb_adr |= mb->data;
771 "mbox: Unknown CFG command: cmd_l=0x%02x, data=0x%04x\n",
772 mb->cmd_l, mb->data);
781 void *ipb_sys_da, *ipb_sys_ad;
782 void *mbseq; /* FIXME: 3.4 obsolete */
784 u16 dbg_buf_sz, dbg_line_sz;
785 struct mem_sync_struct mem_sync, *mem_syncp;
787 ipb_sys_da = dspword_to_virt(tmp_ipb_adr);
788 if (ipbuf_sys_config(ipb_sys_da, DIR_D2A) < 0)
791 if (dsp_mem_enable(ipbuf_sys_da) < 0) {
792 printk(KERN_ERR "mbox: DSPCFG - ipbuf_sys_da read failed!\n");
795 if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) {
796 printk(KERN_ERR "mbox: DSPCFG - IPBUF sync failed!\n");
797 dsp_mem_disable(ipbuf_sys_da);
801 * read configuration data on system IPBUF
802 * we must read with 16bit-access
804 #ifdef OLD_BINARY_SUPPORT
805 if (mbox_revision == MBPROT_REVISION) {
807 buf = ipbuf_sys_da->d;
811 badr = MKVIRT(buf[3], buf[4]);
812 /* ipb_sys_da = MKVIRT(buf[5], buf[6]); */
813 ipb_sys_ad = MKVIRT(buf[7], buf[8]);
814 mbseq = MKVIRT(buf[9], buf[10]);
815 dbg_buf = MKVIRT(buf[11], buf[12]);
816 dbg_buf_sz = buf[13];
817 dbg_line_sz = buf[14];
818 mem_sync.DARAM = MKVIRT(buf[15], buf[16]);
819 mem_sync.SARAM = MKVIRT(buf[17], buf[18]);
820 mem_sync.SDRAM = MKVIRT(buf[19], buf[20]);
821 mem_syncp = &mem_sync;
822 #ifdef OLD_BINARY_SUPPORT
823 } else if (mbox_revision == MBREV_3_2) {
824 buf = ipbuf_sys_da->d;
828 badr = MKVIRT(buf[3], buf[4]);
829 /* ipb_sys_da = MKVIRT(buf[5], buf[6]); */
830 ipb_sys_ad = MKVIRT(buf[7], buf[8]);
831 mbseq = MKVIRT(buf[9], buf[10]);
836 } else if (mbox_revision == MBREV_3_0) {
837 buf = ipbuf_sys_da->d;
841 badr = MKVIRT(buf[3], buf[4]);
842 /* bkeep = buf[5]; */
843 /* ipb_sys_da = MKVIRT(buf[6], buf[7]); */
844 ipb_sys_ad = MKVIRT(buf[8], buf[9]);
845 mbseq = MKVIRT(buf[10], buf[11]);
850 } else { /* should not occur */
851 dsp_mem_disable(ipbuf_sys_da);
854 #endif /* OLD_BINARY_SUPPORT */
856 release_ipbuf_pvt(ipbuf_sys_da);
857 dsp_mem_disable(ipbuf_sys_da);
860 * following configurations need to be done before
861 * waking up the dspcfg initiator process.
863 if (ipbuf_sys_config(ipb_sys_ad, DIR_A2D) < 0)
865 if (ipbuf_config(bln, bsz, badr) < 0)
867 if (dsp_mbox_config(mbseq) < 0)
869 if (dsp_dbg_config(dbg_buf, dbg_buf_sz, dbg_line_sz) < 0)
871 if (dsp_mem_sync_config(mem_syncp) < 0)
874 misc_mb_wait.cmd_h = 0;
875 wake_up_interruptible(&misc_mb_wait.wait_q);
882 wake_up_interruptible(&misc_mb_wait.wait_q);
886 void mbox_poll(struct mbcmd *mb)
888 misc_mbcmd_response(mb, 0, 0);
891 void mbox_regrw(struct mbcmd *mb)
895 misc_mbcmd_response(mb, 1, 0);
899 "mbox: Illegal REGRW command: "
900 "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
905 void mbox_getvar(struct mbcmd *mb)
909 misc_mbcmd_response(mb, 1, 1);
912 misc_mbcmd_response(mb, 5, 1);
916 "mbox: Illegal GETVAR command: "
917 "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data);
922 void mbox_fbctl_disable(struct mbcmd *mb)
924 misc_mbcmd_response(mb, 0, 0);
927 struct file_operations dsp_ctl_fops = {
928 .owner = THIS_MODULE,
929 .ioctl = dsp_ctl_ioctl,
937 static ssize_t ifver_show(struct device *dev, struct device_attribute *attr,
943 * I/F VERSION descriptions:
945 * 3.2: sysfs / udev support
946 * KMEM_RESERVE / KMEM_RELEASE ioctls for mem device
947 * 3.3: added following ioctls
948 * DSPCTL_IOCTL_GBL_IDLE
949 * DSPCTL_IOCTL_CPU_IDLE (instead of DSPCTL_IOCTL_IDLE)
954 * print all supporting I/F VERSIONs, like followings.
956 * len += sprintf(buf, "3.2\n");
957 * len += sprintf(buf, "3.3\n");
959 len += sprintf(buf + len, "3.2\n");
960 len += sprintf(buf + len, "3.3\n");
966 static char *cpustat_name[CPUSTAT_MAX] = {
967 [CPUSTAT_RESET] = "reset",
968 #ifdef CONFIG_ARCH_OMAP1
969 [CPUSTAT_GBL_IDLE] = "gbl_idle",
970 [CPUSTAT_CPU_IDLE] = "cpu_idle",
972 [CPUSTAT_RUN] = "run",
975 static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr,
978 return sprintf(buf, "%s\n", cpustat_name[dsp_cpustat_get_stat()]);
982 static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr,
985 return sprintf(buf, "0x%04x\n", dsp_cpustat_get_icrmask());
988 static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr,
989 const char *buf, size_t count)
994 mask = simple_strtol(buf, NULL, 16);
995 dsp_cpustat_set_icrmask(mask);
997 if (dsp_cfgstat_get_stat() == CFGSTAT_READY) {
998 ret = dsp_setvar(VARID_ICRMASK, mask);
1007 static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr,
1014 if ((ret = dsp_getvar(VARID_LOADINFO, val)) < 0)
1018 * load info value range is 0(free) - 10000(busy):
1019 * if CPU load is not measured on DSP, it sets 0xffff at val[0].
1022 if (val[0] == 0xffff) {
1024 "currently DSP load info is not available.\n");
1030 " 10ms average = %3d.%02d%%\n"
1031 " 1sec average = %3d.%02d%% busiest 10ms = %3d.%02d%%\n"
1032 " 1min average = %3d.%02d%% busiest 1s = %3d.%02d%%\n",
1033 val[0]/100, val[0]%100,
1034 val[1]/100, val[1]%100, val[2]/100, val[2]%100,
1035 val[3]/100, val[3]%100, val[4]/100, val[4]%100);
1040 int __init dsp_ctl_init(void)
1044 ret = device_create_file(omap_dsp->dev, &dev_attr_ifver);
1047 ret = device_create_file(omap_dsp->dev, &dev_attr_cpustat);
1049 goto fail_create_cpustat;
1050 ret = device_create_file(omap_dsp->dev, &dev_attr_icrmask);
1052 goto fail_create_icrmask;
1056 fail_create_icrmask:
1057 device_remove_file(omap_dsp->dev, &dev_attr_cpustat);
1058 fail_create_cpustat:
1059 device_remove_file(omap_dsp->dev, &dev_attr_ifver);
1064 void dsp_ctl_exit(void)
1066 device_remove_file(omap_dsp->dev, &dev_attr_ifver);
1067 device_remove_file(omap_dsp->dev, &dev_attr_cpustat);
1068 device_remove_file(omap_dsp->dev, &dev_attr_icrmask);