]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/dsp/dsp_ctl_core.c
ARM: OMAP: DSPGW: Deferred dsp initializtion
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / dsp / 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 "dsp.h"
29
30 #define CTL_MINOR       0
31 #define MEM_MINOR       1
32 #define TWCH_MINOR      2
33 #define ERR_MINOR       3
34
35 static struct class *dsp_ctl_class;
36 extern struct file_operations dsp_ctl_fops,
37                               dsp_mem_fops,
38                               dsp_twch_fops,
39                               dsp_err_fops;
40
41 static int dsp_ctl_core_open(struct inode *inode, struct file *file)
42 {
43         static DEFINE_MUTEX(open_lock);
44         int ret = 0;
45
46         mutex_lock_interruptible(&open_lock);
47         if (omap_dsp->initialized == 0) {
48                 ret = dsp_late_init();
49                 if (ret != 0) {
50                         mutex_unlock(&open_lock);
51                         return ret;
52                 }
53                 omap_dsp->initialized = 1;
54         }
55         mutex_unlock(&open_lock);
56
57         switch (iminor(inode)) {
58         case CTL_MINOR:
59                 file->f_op = &dsp_ctl_fops;
60                 break;
61         case MEM_MINOR:
62                 file->f_op = &dsp_mem_fops;
63                 break;
64         case TWCH_MINOR:
65                 file->f_op = &dsp_twch_fops;
66                 break;
67         case ERR_MINOR:
68                 file->f_op = &dsp_err_fops;
69                 break;
70         default:
71                 return -ENXIO;
72         }
73         if (file->f_op && file->f_op->open)
74                 return file->f_op->open(inode, file);
75         return 0;
76 }
77
78 static struct file_operations dsp_ctl_core_fops = {
79         .owner = THIS_MODULE,
80         .open  = dsp_ctl_core_open,
81 };
82
83 static const struct dev_list {
84         unsigned int    minor;
85         char            *devname;
86         umode_t         mode;
87 } dev_list[] = {
88         {CTL_MINOR,  "dspctl",  S_IRUSR | S_IWUSR},
89         {MEM_MINOR,  "dspmem",  S_IRUSR | S_IWUSR | S_IRGRP},
90         {TWCH_MINOR, "dsptwch", S_IRUSR | S_IWUSR | S_IRGRP},
91         {ERR_MINOR,  "dsperr",  S_IRUSR | S_IRGRP},
92 };
93
94 int __init dsp_ctl_core_init(void)
95 {
96         int retval;
97         int i;
98
99         retval = register_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl",
100                                  &dsp_ctl_core_fops);
101         if (retval < 0) {
102                 printk(KERN_ERR
103                        "omapdsp: failed to register dspctl device: %d\n",
104                        retval);
105                 return retval;
106         }
107
108         dsp_ctl_class = class_create(THIS_MODULE, "dspctl");
109         for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
110                 class_device_create(dsp_ctl_class, NULL,
111                                     MKDEV(OMAP_DSP_CTL_MAJOR,
112                                           dev_list[i].minor),
113                                     NULL, dev_list[i].devname);
114         }
115
116         return 0;
117 }
118
119 void dsp_ctl_core_exit(void)
120 {
121         int i;
122
123         for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
124                 class_device_destroy(dsp_ctl_class,
125                                      MKDEV(OMAP_DSP_CTL_MAJOR,
126                                            dev_list[i].minor));
127         }
128         class_destroy(dsp_ctl_class);
129
130         unregister_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl");
131 }