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>
10 #define DBGERR(x...) printk(KERN_INFO x)
\r
12 #define DBGERR(x...)
\r
16 #define DBG(x...) printk(KERN_INFO x)
\r
21 struct cmmb_memory CMMB_memo;
\r
22 static struct cmmb_device* cmmbmemo;
\r
25 static int cmmbmemo_release(struct inode *inode, struct file *file)
\r
27 struct cmmb_memory *cmmb_memo = (struct cmmb_memory*)file->private_data;
\r
29 DBG("[CMMB HW]:[memory]: enter cmmb av memory release\n");
\r
31 mutex_lock(&cmmb_memo->mutex);
\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
42 mutex_unlock(&cmmb_memo->mutex);
\r
47 //hzb@20100416,ÔÚ´ò¿ªÉ豸µÄʱºòÉêÇë¿Õ¼ä
\r
48 static int cmmbmemo_open(struct inode * inode, struct file * file)
\r
50 struct cmmb_memory *cmmbmemo = &CMMB_memo;
\r
53 DBG("[CMMB HW]:[memory]: enter cmmb memo open\n");
\r
55 if (mutex_lock_interruptible(&cmmbmemo->mutex))
\r
56 return -ERESTARTSYS;
\r
60 if (cmmbmemo->usr == 1)
\r
62 DBG("[CMMB HW]:[memory]:cmmb video buffer malloc\n");
\r
64 cmmbmemo->video_buf = NULL;
\r
65 cmmbmemo->audio_buf = NULL;
\r
66 cmmbmemo->data_buf = NULL;
\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
71 if (cmmbmemo->video_buf == NULL){
\r
73 DBGERR("[CMMB HW]:[memory]:[err]: cmmb video buffer malloc fail!!!\n");
\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
81 if (cmmbmemo->audio_buf == NULL){
\r
83 DBGERR("[CMMB HW]:[memory]:[err]: cmmb audio buffer malloc fail!!!\n");
\r
87 cmmbmemo->data_buf = vmalloc(1);
\r
89 if (cmmbmemo->data_buf == NULL){
\r
91 DBGERR("[CMMB HW]:[memory]:[err]: cmmb data buffer malloc fail!!!\n");
\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
100 cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
101 cmmbmemo->r_datatype = CMMB_NULL_TYPE;
\r
103 file->private_data = cmmbmemo; //hzb@20100415,store the cmmbmemo struct in the file private data
\r
104 mutex_unlock(&cmmbmemo->mutex);
\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
116 static ssize_t cmmbmemo_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)
\r
118 struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
119 ssize_t avail_V, avail_A, avail_D;
\r
122 DBG("[CMMB HW]:[memory]:enter cmmb memory read\n");
\r
124 if (cmmbmemo->r_datatype == CMMB_VIDEO_TYPE){
\r
126 DECLARE_WAITQUEUE(wait, current);
\r
128 avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
130 if (avail_V < count){
\r
131 add_wait_queue(&cmmbmemo->buffer_Video.queue, &wait);
\r
132 __set_current_state(TASK_INTERRUPTIBLE);
\r
134 remove_wait_queue(&cmmbmemo->buffer_Video.queue, &wait);
\r
135 if (signal_pending(current)){
\r
136 ret = -ERESTARTSYS;
\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
152 avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
153 DBG("[CMMB HW]:[memory]:cmmb memory read video data awake\n");
\r
156 avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
157 if (avail_V < count)
\r
160 ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Video, buf, count, 1);
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
165 DECLARE_WAITQUEUE(wait, current);
\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
172 remove_wait_queue(&cmmbmemo->buffer_Audio.queue, &wait);
\r
173 if (signal_pending(current)){
\r
174 ret = -ERESTARTSYS;
\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
190 avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);
\r
191 DBG("[CMMB HW]:[memory]:cmmb memory read audio data awake\n");
\r
194 avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);
\r
195 if (avail_A < count)
\r
198 ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Audio, buf, count, 1);
\r
199 }else if(cmmbmemo->r_datatype == CMMB_DATA_TYPE){
\r
201 DECLARE_WAITQUEUE(wait, current);
\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
208 remove_wait_queue(&cmmbmemo->buffer_Data.queue, &wait);
\r
209 if (signal_pending(current)){
\r
210 ret = -ERESTARTSYS;
\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
226 avail_D= cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);
\r
227 DBG("[CMMB HW]:[memory]:cmmb memory read data awake\n");
\r
230 avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);
\r
231 if (avail_D < count)
\r
234 ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Data, buf, count, 1);
\r
238 cmmbmemo->r_datatype = CMMB_NULL_TYPE;
\r
244 static ssize_t cmmbmemo_write(struct file *file, char __user *buf, size_t count,loff_t *ppos)
\r
246 struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
247 ssize_t free_V, free_A, free_D;
\r
249 static int loop = 0;
\r
251 DBG("[CMMB HW]:[memory]:enter cmmbdemux_write\n");
\r
253 if (cmmbmemo->w_datatype == CMMB_VIDEO_TYPE){
\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
259 //cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\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
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
271 //cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
273 spin_lock(cmmbmemo->buffer_Audio.lock);
\r
274 cmmbmemo->buffer_Audio.condition = 1;
\r
275 spin_unlock(cmmbmemo->buffer_Audio.lock);
\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
283 //cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
285 spin_lock(cmmbmemo->buffer_Data.lock);
\r
286 cmmbmemo->buffer_Data.condition = 1;
\r
287 spin_unlock(cmmbmemo->buffer_Data.lock);
\r
289 //wake_up_interruptible(&cmmbmemo->buffer_Data.queue);
\r
296 int cmmbmemo_valueinit(struct file *file)
\r
298 struct cmmb_memory *cmmbmemo = file->private_data;
\r
301 DBG("[CMMB HW]:[memory]: enter cmmb memo open\n");
\r
303 cmmbmemo->video_buf = NULL;
\r
304 cmmbmemo->audio_buf = NULL;
\r
305 cmmbmemo->data_buf = NULL;
\r
307 cmmbmemo->video_buf = kzalloc(CMMB_VIDEO_BUFFER_SIZE+1, GFP_KERNEL);
\r
309 if (cmmbmemo->video_buf == NULL){
\r
311 DBGERR("[CMMB HW]:[memory]:[err]: cmmb video buffer malloc fail!!!\n");
\r
315 cmmbmemo->audio_buf = kzalloc(CMMB_AUDIO_BUFFER_SIZE+1, GFP_KERNEL);
\r
317 if (cmmbmemo->audio_buf == NULL){
\r
319 DBGERR("[CMMB HW]:[memory]:[err]: cmmb audio buffer malloc fail!!!\n");
\r
323 cmmbmemo->data_buf = kzalloc(1, GFP_KERNEL);
\r
325 if (cmmbmemo->data_buf == NULL){
\r
327 DBGERR("[CMMB HW]:[memory]:[err]: cmmb data buffer malloc fail!!!\n");
\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
336 cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
337 cmmbmemo->r_datatype = CMMB_NULL_TYPE;
\r
342 kfree(cmmbmemo->video_buf);
\r
343 kfree(cmmbmemo->audio_buf);
\r
344 kfree(cmmbmemo->data_buf);
\r
348 static long cmmbmemo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
\r
350 struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
353 DBG("[CMMB HW]:[memory]:enter cmmbdemux_ioctl\n");
\r
356 case CMMB_MEMO_WRITE:{
\r
357 cmmbmemo->w_datatype = arg;
\r
361 case CMMB_MEMO_READ:{
\r
362 cmmbmemo->r_datatype = arg;
\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
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
386 case CMMB_MEMO_INIT:{
\r
387 return cmmbmemo_valueinit(file);
\r
391 case CMMB_SET_VIDEO_TYPE:{
\r
392 cmmbmemo->videotype = arg;
\r
396 case CMMB_SET_AUDIO_TYPE:{
\r
397 cmmbmemo->audiotype = arg;
\r
401 case CMMB_SET_AUDIO_SAMPLE:{
\r
402 cmmbmemo->audiosample = arg;
\r
406 case CMMB_GET_VIDEO_TYPE:{
\r
407 return cmmbmemo->videotype;
\r
411 case CMMB_GET_AUDIO_TYPE:{
\r
412 return cmmbmemo->audiotype;
\r
416 case CMMB_GET_AUDIO_SAMPLE:{
\r
417 return cmmbmemo->audiosample;
\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
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
454 static unsigned int cmmbmemo_poll(struct file *file, struct poll_table_struct *wait)
\r
456 struct cmmb_demux *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
457 unsigned int mask = 0;
\r
459 DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__);
\r
461 //2todo memo poll, now doing nothing
\r
467 static int cmmbmemo_mmap(struct file *file, struct vm_area_struct *vma)
\r
469 //2 todo memo mmmap, now doing nothing
\r
470 DBG("[CMMB HW]:[memory]:enter cmmbdemux_ioctl\n");
\r
475 struct file_operations cmmbmemeo_fops =
\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
486 static int __init cmmbmemo_init(void)
\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
497 static void __exit cmmbmemo_exit(void)
\r
499 DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__);
\r
500 cmmb_unregister_device(cmmbmemo);
\r
501 //mutex_destroy(mutex);
\r
504 module_init(cmmbmemo_init);
\r
505 module_exit(cmmbmemo_exit);
\r
507 MODULE_DESCRIPTION("CMMB demodulator general driver");
\r
508 MODULE_AUTHOR("HT,HZB,HH,LW");
\r
509 MODULE_LICENSE("GPL");
\r