]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/dsp/dspgateway/dsp_ctl_core.c
25954bba9c8c6ad52fa6fb514dd6d987c13e6ad7
[linux-2.6-omap-h63xx.git] / drivers / dsp / dspgateway / dsp_ctl_core.c
1 /*
2  * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
3  *
4  * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
5  *
6  * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
7  *
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.
11  *
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.
16  *
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
20  * 02110-1301 USA
21  *
22  */
23
24 #include <linux/major.h>
25 #include <linux/fs.h>
26 #include <linux/device.h>
27 #include <linux/init.h>
28 #include <asm/io.h>
29 #include "dsp.h"
30
31 #define CTL_MINOR       0
32 #define MEM_MINOR       1
33 #define TWCH_MINOR      2
34 #define ERR_MINOR       3
35
36 static struct class *dsp_ctl_class;
37 extern struct file_operations dsp_ctl_fops,
38                               dsp_mem_fops,
39                               dsp_twch_fops,
40                               dsp_err_fops;
41
42 static int dsp_ctl_core_open(struct inode *inode, struct file *file)
43 {
44         static DEFINE_MUTEX(open_lock);
45         int ret = 0;
46
47         if (mutex_lock_interruptible(&open_lock))
48                 return -EINTR;
49         if (omap_dsp->initialized == 0) {
50                 ret = dsp_late_init();
51                 if (ret != 0) {
52                         mutex_unlock(&open_lock);
53                         return ret;
54                 }
55                 omap_dsp->initialized = 1;
56         }
57         mutex_unlock(&open_lock);
58
59         switch (iminor(inode)) {
60         case CTL_MINOR:
61                 file->f_op = &dsp_ctl_fops;
62                 break;
63         case MEM_MINOR:
64                 file->f_op = &dsp_mem_fops;
65                 break;
66         case TWCH_MINOR:
67                 file->f_op = &dsp_twch_fops;
68                 break;
69         case ERR_MINOR:
70                 file->f_op = &dsp_err_fops;
71                 break;
72         default:
73                 return -ENXIO;
74         }
75         if (file->f_op && file->f_op->open)
76                 return file->f_op->open(inode, file);
77         return 0;
78 }
79
80 static struct file_operations dsp_ctl_core_fops = {
81         .owner = THIS_MODULE,
82         .open  = dsp_ctl_core_open,
83 };
84
85 static const struct dev_list {
86         unsigned int    minor;
87         char            *devname;
88         umode_t         mode;
89 } dev_list[] = {
90         {CTL_MINOR,  "dspctl",  S_IRUSR | S_IWUSR},
91         {MEM_MINOR,  "dspmem",  S_IRUSR | S_IWUSR | S_IRGRP},
92         {TWCH_MINOR, "dsptwch", S_IRUSR | S_IWUSR | S_IRGRP},
93         {ERR_MINOR,  "dsperr",  S_IRUSR | S_IRGRP},
94 };
95
96 int __init dsp_ctl_core_init(void)
97 {
98         int retval;
99         int i;
100
101         retval = register_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl",
102                                  &dsp_ctl_core_fops);
103         if (retval < 0) {
104                 printk(KERN_ERR
105                        "omapdsp: failed to register dspctl device: %d\n",
106                        retval);
107                 return retval;
108         }
109
110         dsp_ctl_class = class_create(THIS_MODULE, "dspctl");
111         for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
112                 device_create(dsp_ctl_class, NULL,
113                               MKDEV(OMAP_DSP_CTL_MAJOR, dev_list[i].minor),
114                               NULL, dev_list[i].devname);
115         }
116
117         return 0;
118 }
119
120 void dsp_ctl_core_exit(void)
121 {
122         int i;
123
124         for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
125                 device_destroy(dsp_ctl_class,
126                                 MKDEV(OMAP_DSP_CTL_MAJOR,
127                                         dev_list[i].minor));
128         }
129         class_destroy(dsp_ctl_class);
130
131         unregister_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl");
132 }