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