thermal: rockchip: add rk3328 support
[firefly-linux-kernel-4.4.55.git] / drivers / cmmb / cmmb_class.c
1 #include <linux/types.h>\r
2 #include <linux/errno.h>\r
3 #include <linux/string.h>\r
4 #include <linux/module.h>\r
5 #include <linux/kernel.h>\r
6 #include <linux/init.h>\r
7 #include <linux/slab.h>\r
8 #include <linux/device.h>\r
9 #include <linux/fs.h>\r
10 #include <linux/cdev.h>\r
11 #include <linux/mutex.h>\r
12 \r
13 #include "cmmb_class.h"\r
14 \r
15 \r
16 #if 1\r
17 #define DBGERR(fmt...)    printk(KERN_DEBUG fmt)\r
18 #else\r
19 #define DBGERR(fmt...)\r
20 #endif\r
21 \r
22 #if 0\r
23 #define DBG(fmt...)    printk(KERN_DEBUG fmt)\r
24 #else\r
25 #define DBG(fmt...)\r
26 #endif\r
27 \r
28 #define MAX_CMMB_ADAPTER    2\r
29 #define MAX_CMMB_MINORS (MAX_CMMB_ADAPTER*4)\r
30 \r
31 \r
32 struct cmmb_adapter CMMB_adapter;\r
33 struct class * cmmb_class;\r
34 \r
35 static struct cdev cmmb_device_cdev;\r
36 \r
37 static int cmmb_device_open(struct inode *inode, struct file *file);\r
38 \r
39 static struct file_operations cmmb_device_fops =\r
40 {\r
41         .owner =        THIS_MODULE,\r
42         .open =         cmmb_device_open\r
43 };\r
44 \r
45 static struct cmmb_device* cmmb_find_device (int minor)\r
46 {\r
47         \r
48     struct cmmb_device *dev;\r
49     DBG("[CMMB HW]:[class]:enter cmmb_find_device\n");\r
50                 \r
51         list_for_each_entry(dev, &CMMB_adapter.device_list, list_head)\r
52         if (dev->type == minor)\r
53         return dev;\r
54         \r
55         return NULL;\r
56 }\r
57 \r
58 static int cmmb_device_open(struct inode *inode, struct file *file)\r
59 {\r
60         struct cmmb_device *cmmbdev;\r
61     \r
62     DBG("[CMMB HW]:[class]:enter cmmb_device_open\n");\r
63     \r
64         cmmbdev = cmmb_find_device (iminor(inode));\r
65     \r
66     DBG("[CMMB HW]:[class]:cmmbdev.type%d\n",cmmbdev->type);\r
67     \r
68         if (cmmbdev && cmmbdev->fops) {\r
69                 int err = 0;\r
70                 const struct file_operations *old_fops;\r
71 \r
72                 file->private_data = cmmbdev;\r
73                 old_fops = file->f_op;\r
74                 file->f_op = fops_get(cmmbdev->fops);\r
75                 if(file->f_op->open)\r
76                         err = file->f_op->open(inode,file);\r
77                 if (err) {\r
78                         fops_put(file->f_op);\r
79                         file->f_op = fops_get(old_fops);\r
80                 }\r
81                 fops_put(old_fops);\r
82                 return err;\r
83         }\r
84         return -ENODEV;\r
85 }\r
86 \r
87 \r
88 static int cmmb_register_adapter(const char *name, struct device *device)\r
89 {\r
90     DBG("[CMMB HW]:[class]:cmmb_register_adapter\n");\r
91 \r
92         memset (&CMMB_adapter, 0, sizeof(struct cmmb_adapter));\r
93     \r
94         INIT_LIST_HEAD (&CMMB_adapter.device_list);\r
95 \r
96         CMMB_adapter.num = 0;\r
97         CMMB_adapter.name = name;\r
98         CMMB_adapter.device = device;\r
99     \r
100         return 0;\r
101 }\r
102 \r
103 \r
104 static int cmmb_unregister_adapter(struct cmmb_adapter *adap)\r
105 {\r
106     DBG("[CMMB HW]:[class]:cmmb_unregister_adapter\n");\r
107     \r
108         memset (&CMMB_adapter, 0, sizeof(struct cmmb_adapter));\r
109 \r
110         return 0;\r
111 }\r
112 \r
113 \r
114 int cmmb_register_device(struct cmmb_adapter *adap, struct cmmb_device **pcmmbdev,\r
115                          struct file_operations *fops, void *priv, int type,char* name)\r
116 {\r
117         struct cmmb_device *cmmbdev;\r
118         struct file_operations *cmmbdevfops;\r
119         struct device *clsdev;\r
120 \r
121     DBG("[CMMB HW]:[class]:cmmb_register_device\n");\r
122     \r
123         *pcmmbdev = cmmbdev = kmalloc(sizeof(struct cmmb_device), GFP_KERNEL);\r
124     if(!pcmmbdev)\r
125     {\r
126        DBGERR("[CMMB HW]:[class]:[err]: cmmb register device cmmbdev malloc fail!!!\n");\r
127        return -ENOMEM;\r
128     }\r
129     \r
130         cmmbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);\r
131 \r
132         if (!cmmbdevfops){\r
133         DBGERR("[CMMB HW]:[class]:[err]: cmmb register device cmmbdevfops malloc fail!!!\n");\r
134                 kfree (cmmbdev);\r
135                 return -ENOMEM;\r
136         }\r
137 \r
138         cmmbdev->type = type;\r
139         cmmbdev->adapter = adap;\r
140         cmmbdev->priv = priv;\r
141         cmmbdev->fops = cmmbdevfops;\r
142     \r
143         init_waitqueue_head (&cmmbdev->wait_queue);\r
144 \r
145         memcpy(cmmbdev->fops, fops, sizeof(struct file_operations));\r
146         cmmbdev->fops->owner = THIS_MODULE;\r
147 \r
148         list_add_tail (&cmmbdev->list_head, &adap->device_list);\r
149 \r
150         clsdev = device_create(cmmb_class, adap->device,MKDEV(CMMB_MAJOR, type),NULL,name);\r
151         if (IS_ERR(clsdev)) {\r
152                 DBGERR("[CMMB HW]:[class]:[err]: creat dev fail!!!\n");\r
153                 return PTR_ERR(clsdev);\r
154         }\r
155     \r
156         return 0;\r
157 }\r
158 EXPORT_SYMBOL(cmmb_register_device);\r
159 \r
160 \r
161 void cmmb_unregister_device(struct cmmb_device *cmmbdev)\r
162 {\r
163         if (!cmmbdev)\r
164                 return;\r
165     \r
166     DBG("[CMMB HW]:[class]:cmmb_unregister_device\n");\r
167 \r
168         device_destroy(cmmb_class, MKDEV(CMMB_MAJOR, cmmbdev->type));\r
169 \r
170         list_del (&cmmbdev->list_head);\r
171         kfree (cmmbdev->fops);\r
172         kfree (cmmbdev);\r
173 }\r
174 EXPORT_SYMBOL(cmmb_unregister_device);\r
175 \r
176 \r
177 ssize_t cmmb_class_show_name(struct class * class, char * buf, size_t count, loff_t off)\r
178 {\r
179 #if defined(CONFIG_IFxxx_CMMB_Chip_Support)\r
180         memcpy(buf,"inno",5);\r
181         return 5;\r
182 #else\r
183         memcpy(buf,"siano",6);\r
184         return 6;\r
185 #endif\r
186         \r
187 }  \r
188 \r
189 static CLASS_ATTR(name, 0660, cmmb_class_show_name, NULL);\r
190 \r
191 static int __init init_cmmbclass(void)\r
192 {\r
193     int retval;\r
194     struct cmmb_adapter* cmmbadapter;\r
195     struct cmmb_device * tunerdev;\r
196     dev_t dev = MKDEV(CMMB_MAJOR, 0);\r
197     \r
198     DBG("[CMMB HW]:[class]: init_cmmbclass\n");\r
199 \r
200         if ((retval = register_chrdev_region(dev, CMMB_MAJOR, "CMMB")) != 0){\r
201                 DBGERR("[CMMB HW]:[class]:[err]: register chrdev fail!!!\n");\r
202                 return retval;\r
203         }\r
204 \r
205         cdev_init(&cmmb_device_cdev, &cmmb_device_fops);\r
206         if ((retval = cdev_add(&cmmb_device_cdev, dev, MAX_CMMB_MINORS)) != 0){\r
207                 DBGERR("[CMMB HW]:[class]:[err]: cedv add fail!!!\n");\r
208                 goto error;\r
209         }\r
210 \r
211         cmmb_class = class_create(THIS_MODULE, "cmmb");\r
212         if (IS_ERR(cmmb_class)) {\r
213         DBGERR("[CMMB HW]:[class]:[err]: class creat fail!!!\n");\r
214                 retval = PTR_ERR(cmmb_class);\r
215                 goto error;\r
216         }\r
217         retval = class_create_file(cmmb_class, &class_attr_name);\r
218         if(retval < 0)\r
219         {\r
220             DBGERR("cmmb_class create attribute failed\n");\r
221         } \r
222          cmmb_register_adapter("cmmb_adapter", NULL);\r
223 \r
224         return 0;\r
225 \r
226 error:\r
227         cdev_del(&cmmb_device_cdev);\r
228         unregister_chrdev_region(dev, MAX_CMMB_MINORS);\r
229         return retval;\r
230 }\r
231 \r
232 \r
233 static void __exit exit_cmmbclass(void)\r
234 {\r
235         DBG("[CMMB HW]:[class]: exit_cmmbclass\n");\r
236 \r
237         cdev_del(&cmmb_device_cdev);\r
238         cmmb_unregister_adapter(&CMMB_adapter);\r
239         unregister_chrdev_region(MKDEV(CMMB_MAJOR, 0), MAX_CMMB_MINORS);\r
240         class_remove_file(cmmb_class, &class_attr_name);\r
241         class_destroy(cmmb_class);\r
242 }\r
243 \r
244 \r
245 subsys_initcall(init_cmmbclass);\r
246 module_exit(exit_cmmbclass);\r
247 \r
248 MODULE_DESCRIPTION("CMMB CORE");\r
249 MODULE_AUTHOR("HT,HZB,HH,LW");\r
250 MODULE_LICENSE("GPL");\r
251 \r