thermal: rockchip: add rk3328 support
[firefly-linux-kernel-4.4.55.git] / drivers / cmmb / cmmb_memory.c
1 #include "cmmb_memory.h"\r
2 #include "cmmb_class.h"\r
3 #include <linux/errno.h>\r
4 #include <linux/workqueue.h>\r
5 #include <asm/atomic.h>\r
6 #include <linux/vmalloc.h> \r
7 #include <linux/slab.h>
8
9 #if 1\r
10 #define DBGERR(x...)    printk(KERN_INFO x)\r
11 #else\r
12 #define DBGERR(x...)\r
13 #endif\r
14 \r
15 #if 0\r
16 #define DBG(x...)       printk(KERN_INFO x)\r
17 #else\r
18 #define DBG(x...)\r
19 #endif\r
20 \r
21 struct cmmb_memory CMMB_memo;\r
22 static struct cmmb_device* cmmbmemo;\r
23 \r
24 \r
25 static int cmmbmemo_release(struct inode *inode, struct file *file)\r
26 {\r
27     struct cmmb_memory *cmmb_memo = (struct cmmb_memory*)file->private_data;\r
28     \r
29     DBG("[CMMB HW]:[memory]: enter cmmb av memory release\n");\r
30     \r
31     mutex_lock(&cmmb_memo->mutex);\r
32     \r
33         cmmb_memo->usr--;\r
34     \r
35         if(cmmb_memo->usr == 0){\r
36         vfree(cmmb_memo->video_buf);\r
37         vfree(cmmb_memo->audio_buf);\r
38         vfree(cmmb_memo->data_buf);\r
39                 mutex_unlock(&cmmb_memo->mutex);\r
40         DBG("[CMMB HW]:[memory]: enter cmmb av memory release free buffer\n");\r
41         } else{\r
42                 mutex_unlock(&cmmb_memo->mutex);\r
43         }    \r
44     return 0;\r
45 }\r
46 \r
47 //hzb@20100416,ÔÚ´ò¿ªÉ豸µÄʱºòÉêÇë¿Õ¼ä\r
48 static int cmmbmemo_open(struct inode * inode, struct file * file)\r
49 {\r
50     struct cmmb_memory *cmmbmemo = &CMMB_memo;\r
51     int ret = 0;\r
52     \r
53     DBG("[CMMB HW]:[memory]: enter cmmb memo open\n");\r
54 \r
55     if (mutex_lock_interruptible(&cmmbmemo->mutex))\r
56         return -ERESTARTSYS;\r
57     \r
58     cmmbmemo->usr++;\r
59     \r
60     if (cmmbmemo->usr == 1)\r
61     {\r
62         DBG("[CMMB HW]:[memory]:cmmb video buffer malloc\n");\r
63         \r
64         cmmbmemo->video_buf = NULL;\r
65         cmmbmemo->audio_buf = NULL;\r
66         cmmbmemo->data_buf  = NULL;\r
67 \r
68         //cmmbmemo->video_buf = vmalloc(CMMB_VIDEO_BUFFER_SIZE+1, GFP_KERNEL);\r
69         cmmbmemo->video_buf   = vmalloc(CMMB_VIDEO_BUFFER_SIZE+1);\r
70 \r
71         if (cmmbmemo->video_buf == NULL){\r
72             ret = - ENOMEM;\r
73             DBGERR("[CMMB HW]:[memory]:[err]: cmmb video buffer malloc fail!!!\n");\r
74             goto kmalloc_fail;\r
75         }\r
76 \r
77         //cmmbmemo->audio_buf = vmalloc(CMMB_AUDIO_BUFFER_SIZE+1, GFP_KERNEL);\r
78         cmmbmemo->audio_buf = vmalloc(CMMB_AUDIO_BUFFER_SIZE+1);\r
79         \r
80         \r
81         if (cmmbmemo->audio_buf == NULL){\r
82             ret = - ENOMEM;\r
83             DBGERR("[CMMB HW]:[memory]:[err]: cmmb audio buffer malloc fail!!!\n");\r
84             goto kmalloc_fail;\r
85         }\r
86 \r
87         cmmbmemo->data_buf = vmalloc(1);\r
88 \r
89         if (cmmbmemo->data_buf == NULL){\r
90             ret = - ENOMEM;\r
91             DBGERR("[CMMB HW]:[memory]:[err]: cmmb data buffer malloc fail!!!\n");\r
92             goto kmalloc_fail;\r
93         }\r
94 \r
95         //hzb@20100415,init av ring buffers,cmmb need three ring buffers to store the demuxed data\r
96         cmmb_ringbuffer_init(&cmmbmemo->buffer_Video, cmmbmemo->video_buf, CMMB_VIDEO_BUFFER_SIZE);  //init video ring buffer\r
97         cmmb_ringbuffer_init(&cmmbmemo->buffer_Audio, cmmbmemo->audio_buf, CMMB_AUDIO_BUFFER_SIZE);  //init audio ring buffer\r
98         cmmb_ringbuffer_init(&cmmbmemo->buffer_Data,  cmmbmemo->data_buf,  1);   //init data ring buffer\r
99 \r
100         cmmbmemo->w_datatype = CMMB_NULL_TYPE;\r
101         cmmbmemo->r_datatype = CMMB_NULL_TYPE;\r
102     }\r
103     file->private_data = cmmbmemo;  //hzb@20100415,store the cmmbmemo struct in the file private data \r
104     mutex_unlock(&cmmbmemo->mutex);    \r
105     return ret;\r
106         \r
107 kmalloc_fail:\r
108     vfree(cmmbmemo->video_buf);\r
109     vfree(cmmbmemo->audio_buf);\r
110     vfree(cmmbmemo->data_buf);\r
111     mutex_unlock(&cmmbmemo->mutex);    \r
112     return ret;        \r
113 }\r
114
115 \r
116 static ssize_t cmmbmemo_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)\r
117 {\r
118     struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;\r
119     ssize_t avail_V, avail_A, avail_D;\r
120     ssize_t ret;\r
121     \r
122     DBG("[CMMB HW]:[memory]:enter cmmb memory read\n");\r
123     \r
124     if (cmmbmemo->r_datatype == CMMB_VIDEO_TYPE){\r
125 #if 0         \r
126         DECLARE_WAITQUEUE(wait, current);\r
127         for(;;){\r
128             avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);\r
129              \r
130             if (avail_V < count){          \r
131                 add_wait_queue(&cmmbmemo->buffer_Video.queue, &wait);\r
132                 __set_current_state(TASK_INTERRUPTIBLE);\r
133                 schedule();\r
134                 remove_wait_queue(&cmmbmemo->buffer_Video.queue, &wait);\r
135                 if (signal_pending(current)){\r
136                    ret = -ERESTARTSYS;\r
137                    goto out2;\r
138                 }\r
139             }\r
140         }\r
141 #else\r
142 #if 0\r
143         avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);\r
144         while (avail_V < count){\r
145             DBG("[CMMB HW]:[memory]:cmmb memory read video data sleep!!\n");\r
146             spin_lock(cmmbmemo->buffer_Video.lock);\r
147             cmmbmemo->buffer_Video.condition = 0;\r
148             spin_unlock(cmmbmemo->buffer_Video.lock);\r
149             if (wait_event_interruptible(cmmbmemo->buffer_Video.queue, cmmbmemo->buffer_Video.condition))\r
150                 return -ERESTARTSYS;\r
151             \r
152             avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);\r
153             DBG("[CMMB HW]:[memory]:cmmb memory read video data awake\n");\r
154         }\r
155 #endif \r
156             avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);\r
157             if (avail_V < count)  \r
158                 return 0;     \r
159 #endif          \r
160         ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Video, buf, count, 1);   
161      \r
162         DBG("[CMMB HW]:[memory]:cmmb memory video read ret = 0x%x\n",ret);\r
163     }else if (cmmbmemo->r_datatype == CMMB_AUDIO_TYPE){\r
164 #if 0\r
165         DECLARE_WAITQUEUE(wait, current);\r
166         for(;;){\r
167             avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);\r
168             if (avail_A < count){\r
169                 add_wait_queue(&cmmbmemo->buffer_Audio.queue, &wait);\r
170                 __set_current_state(TASK_INTERRUPTIBLE);\r
171                 schedule();\r
172                 remove_wait_queue(&cmmbmemo->buffer_Audio.queue, &wait);\r
173                 if (signal_pending(current)){\r
174                     ret = -ERESTARTSYS;\r
175                     goto out2;\r
176                 }\r
177             }\r
178         }\r
179 #else\r
180 #if 0\r
181         avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);\r
182         while (avail_A < count){\r
183             DBG("[CMMB HW]:[memory]:cmmb memory read audio data sleep!!\n");\r
184             spin_lock(cmmbmemo->buffer_Audio.lock);\r
185             cmmbmemo->buffer_Audio.condition = 0;\r
186             spin_unlock(cmmbmemo->buffer_Audio.lock);\r
187             if (wait_event_interruptible(cmmbmemo->buffer_Audio.queue, cmmbmemo->buffer_Audio.condition))\r
188                 return -ERESTARTSYS;\r
189             \r
190             avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);\r
191             DBG("[CMMB HW]:[memory]:cmmb memory read audio data awake\n");\r
192         }\r
193 #endif\r
194                 avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);  \r
195                 if (avail_A < count)  \r
196                         return 0;    \r
197 #endif\r
198         ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Audio, buf, count, 1);\r
199     }else if(cmmbmemo->r_datatype == CMMB_DATA_TYPE){\r
200  #if 0   \r
201         DECLARE_WAITQUEUE(wait, current);\r
202         for(;;){\r
203            avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);\r
204            if (avail_D < count){\r
205                add_wait_queue(&cmmbmemo->buffer_Data.queue, &wait);\r
206                __set_current_state(TASK_INTERRUPTIBLE);\r
207                schedule();\r
208                remove_wait_queue(&cmmbmemo->buffer_Data.queue, &wait);\r
209                if (signal_pending(current)){\r
210                    ret = -ERESTARTSYS;\r
211                    goto out2;\r
212                }\r
213            }\r
214         }\r
215 #else\r
216 #if 0\r
217         avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);\r
218         while (avail_D < count){\r
219         DBG("[CMMB HW]:[memory]:cmmb memory read data sleep!!\n");\r
220         spin_lock(cmmbmemo->buffer_Data.lock);\r
221         cmmbmemo->buffer_Data.condition = 0;\r
222         spin_unlock(cmmbmemo->buffer_Data.lock);\r
223         if (wait_event_interruptible(cmmbmemo->buffer_Data.queue, cmmbmemo->buffer_Data.condition))\r
224             return -ERESTARTSYS;\r
225         \r
226         avail_D= cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);\r
227         DBG("[CMMB HW]:[memory]:cmmb memory read data awake\n");\r
228         }\r
229 #endif\r
230                 avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);  \r
231                 if (avail_D < count)  \r
232                         return 0;               \r
233 #endif\r
234         ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Data, buf, count, 1);\r
235     }\r
236     \r
237 out2:\r
238     cmmbmemo->r_datatype = CMMB_NULL_TYPE;\r
239     return ret;;\r
240 }\r
241 \r
242 \r
243 \r
244 static ssize_t cmmbmemo_write(struct file *file, char __user *buf, size_t count,loff_t *ppos)\r
245 {\r
246     struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;\r
247     ssize_t free_V, free_A, free_D;\r
248     ssize_t ret;\r
249     static int loop = 0;\r
250     \r
251     DBG("[CMMB HW]:[memory]:enter cmmbdemux_write\n");\r
252     \r
253     if (cmmbmemo->w_datatype == CMMB_VIDEO_TYPE){\r
254         \r
255         free_V = cmmb_ringbuffer_free(&cmmbmemo->buffer_Video);\r
256         if (free_V >= count){\r
257            ret = cmmb_ringbuffer_write(&cmmbmemo->buffer_Video, buf, count);\r
258         }
259         //cmmbmemo->w_datatype = CMMB_NULL_TYPE;\r
260 #if 0\r
261         spin_lock(cmmbmemo->buffer_Video.lock);\r
262         cmmbmemo->buffer_Video.condition = 1;\r
263         spin_unlock(cmmbmemo->buffer_Video.lock);\r
264         wake_up_interruptible(&cmmbmemo->buffer_Video.queue);\r
265 #endif\r
266     }else if (cmmbmemo->w_datatype == CMMB_AUDIO_TYPE){\r
267         free_A = cmmb_ringbuffer_free(&cmmbmemo->buffer_Audio);\r
268         if (free_A >= count){\r
269            ret = cmmb_ringbuffer_write(&cmmbmemo->buffer_Audio, buf, count);\r
270         }\r
271         //cmmbmemo->w_datatype = CMMB_NULL_TYPE;\r
272 #if 0\r
273         spin_lock(cmmbmemo->buffer_Audio.lock);\r
274         cmmbmemo->buffer_Audio.condition = 1;\r
275         spin_unlock(cmmbmemo->buffer_Audio.lock);\r
276 #endif\r
277         //wake_up_interruptible(&cmmbmemo->buffer_Audio.queue);\r
278     }else if(cmmbmemo->w_datatype == CMMB_DATA_TYPE){\r
279         free_D = cmmb_ringbuffer_free(&cmmbmemo->buffer_Data);\r
280         if (free_D >= count){\r
281            ret = cmmb_ringbuffer_write(&cmmbmemo->buffer_Data, buf, count);\r
282         }\r
283         //cmmbmemo->w_datatype = CMMB_NULL_TYPE;\r
284 #if 0\r
285         spin_lock(cmmbmemo->buffer_Data.lock);\r
286         cmmbmemo->buffer_Data.condition = 1;\r
287         spin_unlock(cmmbmemo->buffer_Data.lock);\r
288 #endif\r
289         //wake_up_interruptible(&cmmbmemo->buffer_Data.queue);\r
290     }\r
291 \r
292     return ret;\r
293 }\r
294 \r
295 \r
296 int cmmbmemo_valueinit(struct file *file)\r
297 {\r
298     struct cmmb_memory *cmmbmemo = file->private_data;\r
299     int ret = 0;\r
300 \r
301     DBG("[CMMB HW]:[memory]: enter cmmb memo open\n");\r
302 \r
303     cmmbmemo->video_buf = NULL;\r
304     cmmbmemo->audio_buf = NULL;\r
305     cmmbmemo->data_buf  = NULL;\r
306 \r
307     cmmbmemo->video_buf = kzalloc(CMMB_VIDEO_BUFFER_SIZE+1, GFP_KERNEL);\r
308 \r
309     if (cmmbmemo->video_buf == NULL){\r
310         ret = - ENOMEM;\r
311         DBGERR("[CMMB HW]:[memory]:[err]: cmmb video buffer malloc fail!!!\n");\r
312         goto kmalloc_fail;\r
313     }\r
314 \r
315     cmmbmemo->audio_buf = kzalloc(CMMB_AUDIO_BUFFER_SIZE+1, GFP_KERNEL);\r
316 \r
317     if (cmmbmemo->audio_buf == NULL){\r
318         ret = - ENOMEM;\r
319         DBGERR("[CMMB HW]:[memory]:[err]: cmmb audio buffer malloc fail!!!\n");\r
320         goto kmalloc_fail;\r
321     }\r
322 \r
323     cmmbmemo->data_buf = kzalloc(1, GFP_KERNEL);\r
324 \r
325     if (cmmbmemo->data_buf == NULL){\r
326         ret = - ENOMEM;\r
327         DBGERR("[CMMB HW]:[memory]:[err]: cmmb data buffer malloc fail!!!\n");\r
328         goto kmalloc_fail;\r
329     }\r
330 \r
331     //hzb@20100415,init av ring buffers,cmmb need three ring buffers to store the demuxed data\r
332     cmmb_ringbuffer_init(&cmmbmemo->buffer_Video, cmmbmemo->video_buf, CMMB_VIDEO_BUFFER_SIZE);  //init video ring buffer\r
333     cmmb_ringbuffer_init(&cmmbmemo->buffer_Audio, cmmbmemo->audio_buf, CMMB_AUDIO_BUFFER_SIZE);  //init audio ring buffer\r
334     cmmb_ringbuffer_init(&cmmbmemo->buffer_Data,  cmmbmemo->data_buf,  1);   //init data ring buffer\r
335 \r
336     cmmbmemo->w_datatype = CMMB_NULL_TYPE;\r
337     cmmbmemo->r_datatype = CMMB_NULL_TYPE;\r
338 \r
339     return ret;\r
340 \r
341 kmalloc_fail:\r
342     kfree(cmmbmemo->video_buf);\r
343     kfree(cmmbmemo->audio_buf);\r
344     kfree(cmmbmemo->data_buf);\r
345     return ret;   \r
346 }\r
347 \r
348 static long cmmbmemo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\r
349 {\r
350     struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;\r
351     long ret = 0;\r
352     \r
353     DBG("[CMMB HW]:[memory]:enter cmmbdemux_ioctl\n");\r
354 \r
355     switch (cmd){\r
356             case CMMB_MEMO_WRITE:{\r
357             cmmbmemo->w_datatype = arg;\r
358         }\r
359         break;\r
360         \r
361         case CMMB_MEMO_READ:{\r
362             cmmbmemo->r_datatype = arg;\r
363         }\r
364         break;\r
365 \r
366         case CMMB_MEMO_FLUSH_ONE:{\r
367             if (arg == CMMB_VIDEO_TYPE){\r
368                 cmmb_ringbuffer_flush(&cmmbmemo->buffer_Video);\r
369             }else if (arg == CMMB_AUDIO_TYPE){\r
370                 cmmb_ringbuffer_flush(&cmmbmemo->buffer_Audio);\r
371             }else if (arg == CMMB_DATA_TYPE){\r
372                 cmmb_ringbuffer_flush(&cmmbmemo->buffer_Data);\r
373             }else{\r
374                 ret = - EINVAL;\r
375             }\r
376         }\r
377         break;\r
378        \r
379         case CMMB_MEMO_FLUSH_ALL:{\r
380             cmmb_ringbuffer_flush(&cmmbmemo->buffer_Video);\r
381             cmmb_ringbuffer_flush(&cmmbmemo->buffer_Audio);\r
382             cmmb_ringbuffer_flush(&cmmbmemo->buffer_Data);\r
383         }\r
384         break;\r
385         \r
386         case CMMB_MEMO_INIT:{\r
387             return cmmbmemo_valueinit(file);\r
388         }\r
389         break;\r
390 \r
391         case CMMB_SET_VIDEO_TYPE:{\r
392             cmmbmemo->videotype = arg;\r
393         }\r
394         break;\r
395         \r
396         case CMMB_SET_AUDIO_TYPE:{\r
397             cmmbmemo->audiotype = arg;\r
398         }\r
399         break;\r
400         \r
401         case CMMB_SET_AUDIO_SAMPLE:{\r
402             cmmbmemo->audiosample = arg;\r
403         }\r
404         break;\r
405 \r
406         case CMMB_GET_VIDEO_TYPE:{\r
407             return cmmbmemo->videotype;\r
408         }\r
409         break;\r
410         \r
411         case CMMB_GET_AUDIO_TYPE:{\r
412             return cmmbmemo->audiotype;\r
413         }\r
414         break;\r
415         \r
416         case CMMB_GET_AUDIO_SAMPLE:{\r
417             return cmmbmemo->audiosample;\r
418         }\r
419         break;\r
420 \r
421         case CMMB_GET_BUFF_FREE:{\r
422             if (arg == CMMB_VIDEO_TYPE){\r
423                 ret = (long)cmmb_ringbuffer_free(&cmmbmemo->buffer_Video);\r
424             }else if (arg == CMMB_AUDIO_TYPE){\r
425                 ret = (long)cmmb_ringbuffer_free(&cmmbmemo->buffer_Audio);\r
426             }else if (arg == CMMB_DATA_TYPE){\r
427                 ret = (long)cmmb_ringbuffer_free(&cmmbmemo->buffer_Data);\r
428             }else{\r
429                 ret = - EINVAL;\r
430             }\r
431         }\r
432         break;\r
433 \r
434         case CMMB_GET_BUFF_AVAIL:{\r
435             if (arg == CMMB_VIDEO_TYPE){\r
436                 ret = (long)cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);\r
437             }else if (arg == CMMB_AUDIO_TYPE){\r
438                 ret = (long)cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);\r
439             }else if (arg == CMMB_DATA_TYPE){\r
440                 ret = (long)cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);\r
441             }else{\r
442                 ret = - EINVAL;\r
443             }\r
444         }\r
445         break;\r
446         \r
447         default:\r
448             ;\r
449         break;\r
450     }\r
451     return ret;\r
452 }\r
453 \r
454 static unsigned int cmmbmemo_poll(struct file *file, struct poll_table_struct *wait)\r
455 {\r
456     struct cmmb_demux *cmmbmemo = (struct cmmb_memory*)file->private_data;\r
457     unsigned int mask = 0;\r
458 \r
459     DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__);  \r
460     \r
461     //2todo memo poll, now doing nothing\r
462   \r
463     return mask;\r
464 }\r
465 \r
466 \r
467 static int cmmbmemo_mmap(struct file *file, struct vm_area_struct *vma)\r
468 {\r
469     //2 todo memo mmmap, now doing nothing\r
470     DBG("[CMMB HW]:[memory]:enter cmmbdemux_ioctl\n");\r
471     return 0;\r
472 }\r
473 \r
474 \r
475 struct file_operations cmmbmemeo_fops = \r
476 {\r
477     .open  = cmmbmemo_open,\r
478     .release = cmmbmemo_release,    \r
479     .read  = cmmbmemo_read,\r
480     .write = cmmbmemo_write,\r
481     .mmap  = cmmbmemo_mmap,\r
482     .poll  = cmmbmemo_poll,\r
483     .unlocked_ioctl = cmmbmemo_ioctl,\r
484 };\r
485 \r
486 static int __init cmmbmemo_init(void)\r
487 {\r
488     int res;\r
489     \r
490     DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__);  \r
491         res =cmmb_register_device(&CMMB_adapter,&cmmbmemo, &cmmbmemeo_fops, NULL, CMMB_DEVICE_MEMO,"cmmb_memo");\r
492     mutex_init(&CMMB_memo.mutex);\r
493     CMMB_memo.usr = 0;\r
494     return res;\r
495 }\r
496 \r
497 static void __exit cmmbmemo_exit(void)\r
498 {\r
499     DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__);  \r
500     cmmb_unregister_device(cmmbmemo);\r
501     //mutex_destroy(mutex);\r
502 }\r
503 \r
504 module_init(cmmbmemo_init);\r
505 module_exit(cmmbmemo_exit);\r
506 \r
507 MODULE_DESCRIPTION("CMMB demodulator general driver");\r
508 MODULE_AUTHOR("HT,HZB,HH,LW");\r
509 MODULE_LICENSE("GPL");\r
510 \r