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
8 #define DBGERR(x...) printk(KERN_INFO x)
\r
10 #define DBGERR(x...)
\r
14 #define DBG(x...) printk(KERN_INFO x)
\r
19 struct cmmb_memory CMMB_memo;
\r
20 static struct cmmb_device* cmmbmemo;
\r
23 static int cmmbmemo_release(struct inode *inode, struct file *file)
\r
25 struct cmmb_memory *cmmb_memo = (struct cmmb_memory*)file->private_data;
\r
27 DBG("[CMMB HW]:[memory]: enter cmmb av memory release\n");
\r
29 mutex_lock(&cmmb_memo->mutex);
\r
33 if(cmmb_memo->usr == 0){
\r
34 vfree(cmmb_memo->video_buf);
\r
35 vfree(cmmb_memo->audio_buf);
\r
36 vfree(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
40 mutex_unlock(&cmmb_memo->mutex);
\r
45 //hzb@20100416,ÔÚ´ò¿ªÉ豸µÄʱºòÉêÇë¿Õ¼ä
\r
46 static int cmmbmemo_open(struct inode * inode, struct file * file)
\r
48 struct cmmb_memory *cmmbmemo = &CMMB_memo;
\r
51 DBG("[CMMB HW]:[memory]: enter cmmb memo open\n");
\r
53 if (mutex_lock_interruptible(&cmmbmemo->mutex))
\r
54 return -ERESTARTSYS;
\r
58 if (cmmbmemo->usr == 1)
\r
60 DBG("[CMMB HW]:[memory]:cmmb video buffer malloc\n");
\r
62 cmmbmemo->video_buf = NULL;
\r
63 cmmbmemo->audio_buf = NULL;
\r
64 cmmbmemo->data_buf = NULL;
\r
66 //cmmbmemo->video_buf = vmalloc(CMMB_VIDEO_BUFFER_SIZE+1, GFP_KERNEL);
\r
67 cmmbmemo->video_buf = vmalloc(CMMB_VIDEO_BUFFER_SIZE+1);
\r
69 if (cmmbmemo->video_buf == NULL){
\r
71 DBGERR("[CMMB HW]:[memory]:[err]: cmmb video buffer malloc fail!!!\n");
\r
75 //cmmbmemo->audio_buf = vmalloc(CMMB_AUDIO_BUFFER_SIZE+1, GFP_KERNEL);
\r
76 cmmbmemo->audio_buf = vmalloc(CMMB_AUDIO_BUFFER_SIZE+1);
\r
79 if (cmmbmemo->audio_buf == NULL){
\r
81 DBGERR("[CMMB HW]:[memory]:[err]: cmmb audio buffer malloc fail!!!\n");
\r
85 cmmbmemo->data_buf = vmalloc(1);
\r
87 if (cmmbmemo->data_buf == NULL){
\r
89 DBGERR("[CMMB HW]:[memory]:[err]: cmmb data buffer malloc fail!!!\n");
\r
93 //hzb@20100415,init av ring buffers,cmmb need three ring buffers to store the demuxed data
\r
94 cmmb_ringbuffer_init(&cmmbmemo->buffer_Video, cmmbmemo->video_buf, CMMB_VIDEO_BUFFER_SIZE); //init video ring buffer
\r
95 cmmb_ringbuffer_init(&cmmbmemo->buffer_Audio, cmmbmemo->audio_buf, CMMB_AUDIO_BUFFER_SIZE); //init audio ring buffer
\r
96 cmmb_ringbuffer_init(&cmmbmemo->buffer_Data, cmmbmemo->data_buf, 1); //init data ring buffer
\r
98 cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
99 cmmbmemo->r_datatype = CMMB_NULL_TYPE;
\r
101 file->private_data = cmmbmemo; //hzb@20100415,store the cmmbmemo struct in the file private data
\r
102 mutex_unlock(&cmmbmemo->mutex);
\r
106 vfree(cmmbmemo->video_buf);
\r
107 vfree(cmmbmemo->audio_buf);
\r
108 vfree(cmmbmemo->data_buf);
\r
109 mutex_unlock(&cmmbmemo->mutex);
\r
114 static ssize_t cmmbmemo_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)
\r
116 struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
117 ssize_t avail_V, avail_A, avail_D;
\r
120 DBG("[CMMB HW]:[memory]:enter cmmb memory read\n");
\r
122 if (cmmbmemo->r_datatype == CMMB_VIDEO_TYPE){
\r
124 DECLARE_WAITQUEUE(wait, current);
\r
126 avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
128 if (avail_V < count){
\r
129 add_wait_queue(&cmmbmemo->buffer_Video.queue, &wait);
\r
130 __set_current_state(TASK_INTERRUPTIBLE);
\r
132 remove_wait_queue(&cmmbmemo->buffer_Video.queue, &wait);
\r
133 if (signal_pending(current)){
\r
134 ret = -ERESTARTSYS;
\r
141 avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
142 while (avail_V < count){
\r
143 DBG("[CMMB HW]:[memory]:cmmb memory read video data sleep!!\n");
\r
144 spin_lock(cmmbmemo->buffer_Video.lock);
\r
145 cmmbmemo->buffer_Video.condition = 0;
\r
146 spin_unlock(cmmbmemo->buffer_Video.lock);
\r
147 if (wait_event_interruptible(cmmbmemo->buffer_Video.queue, cmmbmemo->buffer_Video.condition))
\r
148 return -ERESTARTSYS;
\r
150 avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
151 DBG("[CMMB HW]:[memory]:cmmb memory read video data awake\n");
\r
154 avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
155 if (avail_V < count)
\r
158 ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Video, buf, count, 1);
160 DBG("[CMMB HW]:[memory]:cmmb memory video read ret = 0x%x\n",ret);
\r
161 }else if (cmmbmemo->r_datatype == CMMB_AUDIO_TYPE){
\r
163 DECLARE_WAITQUEUE(wait, current);
\r
165 avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);
\r
166 if (avail_A < count){
\r
167 add_wait_queue(&cmmbmemo->buffer_Audio.queue, &wait);
\r
168 __set_current_state(TASK_INTERRUPTIBLE);
\r
170 remove_wait_queue(&cmmbmemo->buffer_Audio.queue, &wait);
\r
171 if (signal_pending(current)){
\r
172 ret = -ERESTARTSYS;
\r
179 avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);
\r
180 while (avail_A < count){
\r
181 DBG("[CMMB HW]:[memory]:cmmb memory read audio data sleep!!\n");
\r
182 spin_lock(cmmbmemo->buffer_Audio.lock);
\r
183 cmmbmemo->buffer_Audio.condition = 0;
\r
184 spin_unlock(cmmbmemo->buffer_Audio.lock);
\r
185 if (wait_event_interruptible(cmmbmemo->buffer_Audio.queue, cmmbmemo->buffer_Audio.condition))
\r
186 return -ERESTARTSYS;
\r
188 avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);
\r
189 DBG("[CMMB HW]:[memory]:cmmb memory read audio data awake\n");
\r
192 avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);
\r
193 if (avail_A < count)
\r
196 ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Audio, buf, count, 1);
\r
197 }else if(cmmbmemo->r_datatype == CMMB_DATA_TYPE){
\r
199 DECLARE_WAITQUEUE(wait, current);
\r
201 avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);
\r
202 if (avail_D < count){
\r
203 add_wait_queue(&cmmbmemo->buffer_Data.queue, &wait);
\r
204 __set_current_state(TASK_INTERRUPTIBLE);
\r
206 remove_wait_queue(&cmmbmemo->buffer_Data.queue, &wait);
\r
207 if (signal_pending(current)){
\r
208 ret = -ERESTARTSYS;
\r
215 avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);
\r
216 while (avail_D < count){
\r
217 DBG("[CMMB HW]:[memory]:cmmb memory read data sleep!!\n");
\r
218 spin_lock(cmmbmemo->buffer_Data.lock);
\r
219 cmmbmemo->buffer_Data.condition = 0;
\r
220 spin_unlock(cmmbmemo->buffer_Data.lock);
\r
221 if (wait_event_interruptible(cmmbmemo->buffer_Data.queue, cmmbmemo->buffer_Data.condition))
\r
222 return -ERESTARTSYS;
\r
224 avail_D= cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);
\r
225 DBG("[CMMB HW]:[memory]:cmmb memory read data awake\n");
\r
228 avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);
\r
229 if (avail_D < count)
\r
232 ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Data, buf, count, 1);
\r
236 cmmbmemo->r_datatype = CMMB_NULL_TYPE;
\r
242 static ssize_t cmmbmemo_write(struct file *file, char __user *buf, size_t count,loff_t *ppos)
\r
244 struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
245 ssize_t free_V, free_A, free_D;
\r
247 static int loop = 0;
\r
249 DBG("[CMMB HW]:[memory]:enter cmmbdemux_write\n");
\r
251 if (cmmbmemo->w_datatype == CMMB_VIDEO_TYPE){
\r
253 free_V = cmmb_ringbuffer_free(&cmmbmemo->buffer_Video);
\r
254 if (free_V >= count){
\r
255 ret = cmmb_ringbuffer_write(&cmmbmemo->buffer_Video, buf, count);
\r
257 //cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
259 spin_lock(cmmbmemo->buffer_Video.lock);
\r
260 cmmbmemo->buffer_Video.condition = 1;
\r
261 spin_unlock(cmmbmemo->buffer_Video.lock);
\r
262 wake_up_interruptible(&cmmbmemo->buffer_Video.queue);
\r
264 }else if (cmmbmemo->w_datatype == CMMB_AUDIO_TYPE){
\r
265 free_A = cmmb_ringbuffer_free(&cmmbmemo->buffer_Audio);
\r
266 if (free_A >= count){
\r
267 ret = cmmb_ringbuffer_write(&cmmbmemo->buffer_Audio, buf, count);
\r
269 //cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
271 spin_lock(cmmbmemo->buffer_Audio.lock);
\r
272 cmmbmemo->buffer_Audio.condition = 1;
\r
273 spin_unlock(cmmbmemo->buffer_Audio.lock);
\r
275 //wake_up_interruptible(&cmmbmemo->buffer_Audio.queue);
\r
276 }else if(cmmbmemo->w_datatype == CMMB_DATA_TYPE){
\r
277 free_D = cmmb_ringbuffer_free(&cmmbmemo->buffer_Data);
\r
278 if (free_D >= count){
\r
279 ret = cmmb_ringbuffer_write(&cmmbmemo->buffer_Data, buf, count);
\r
281 //cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
283 spin_lock(cmmbmemo->buffer_Data.lock);
\r
284 cmmbmemo->buffer_Data.condition = 1;
\r
285 spin_unlock(cmmbmemo->buffer_Data.lock);
\r
287 //wake_up_interruptible(&cmmbmemo->buffer_Data.queue);
\r
294 int cmmbmemo_valueinit(struct file *file)
\r
296 struct cmmb_memory *cmmbmemo = file->private_data;
\r
299 DBG("[CMMB HW]:[memory]: enter cmmb memo open\n");
\r
301 cmmbmemo->video_buf = NULL;
\r
302 cmmbmemo->audio_buf = NULL;
\r
303 cmmbmemo->data_buf = NULL;
\r
305 cmmbmemo->video_buf = kzalloc(CMMB_VIDEO_BUFFER_SIZE+1, GFP_KERNEL);
\r
307 if (cmmbmemo->video_buf == NULL){
\r
309 DBGERR("[CMMB HW]:[memory]:[err]: cmmb video buffer malloc fail!!!\n");
\r
313 cmmbmemo->audio_buf = kzalloc(CMMB_AUDIO_BUFFER_SIZE+1, GFP_KERNEL);
\r
315 if (cmmbmemo->audio_buf == NULL){
\r
317 DBGERR("[CMMB HW]:[memory]:[err]: cmmb audio buffer malloc fail!!!\n");
\r
321 cmmbmemo->data_buf = kzalloc(1, GFP_KERNEL);
\r
323 if (cmmbmemo->data_buf == NULL){
\r
325 DBGERR("[CMMB HW]:[memory]:[err]: cmmb data buffer malloc fail!!!\n");
\r
329 //hzb@20100415,init av ring buffers,cmmb need three ring buffers to store the demuxed data
\r
330 cmmb_ringbuffer_init(&cmmbmemo->buffer_Video, cmmbmemo->video_buf, CMMB_VIDEO_BUFFER_SIZE); //init video ring buffer
\r
331 cmmb_ringbuffer_init(&cmmbmemo->buffer_Audio, cmmbmemo->audio_buf, CMMB_AUDIO_BUFFER_SIZE); //init audio ring buffer
\r
332 cmmb_ringbuffer_init(&cmmbmemo->buffer_Data, cmmbmemo->data_buf, 1); //init data ring buffer
\r
334 cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
335 cmmbmemo->r_datatype = CMMB_NULL_TYPE;
\r
340 kfree(cmmbmemo->video_buf);
\r
341 kfree(cmmbmemo->audio_buf);
\r
342 kfree(cmmbmemo->data_buf);
\r
346 static long cmmbmemo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
\r
348 struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
351 DBG("[CMMB HW]:[memory]:enter cmmbdemux_ioctl\n");
\r
354 case CMMB_MEMO_WRITE:{
\r
355 cmmbmemo->w_datatype = arg;
\r
359 case CMMB_MEMO_READ:{
\r
360 cmmbmemo->r_datatype = arg;
\r
364 case CMMB_MEMO_FLUSH_ONE:{
\r
365 if (arg == CMMB_VIDEO_TYPE){
\r
366 cmmb_ringbuffer_flush(&cmmbmemo->buffer_Video);
\r
367 }else if (arg == CMMB_AUDIO_TYPE){
\r
368 cmmb_ringbuffer_flush(&cmmbmemo->buffer_Audio);
\r
369 }else if (arg == CMMB_DATA_TYPE){
\r
370 cmmb_ringbuffer_flush(&cmmbmemo->buffer_Data);
\r
377 case CMMB_MEMO_FLUSH_ALL:{
\r
378 cmmb_ringbuffer_flush(&cmmbmemo->buffer_Video);
\r
379 cmmb_ringbuffer_flush(&cmmbmemo->buffer_Audio);
\r
380 cmmb_ringbuffer_flush(&cmmbmemo->buffer_Data);
\r
384 case CMMB_MEMO_INIT:{
\r
385 return cmmbmemo_valueinit(file);
\r
389 case CMMB_SET_VIDEO_TYPE:{
\r
390 cmmbmemo->videotype = arg;
\r
394 case CMMB_SET_AUDIO_TYPE:{
\r
395 cmmbmemo->audiotype = arg;
\r
399 case CMMB_SET_AUDIO_SAMPLE:{
\r
400 cmmbmemo->audiosample = arg;
\r
404 case CMMB_GET_VIDEO_TYPE:{
\r
405 return cmmbmemo->videotype;
\r
409 case CMMB_GET_AUDIO_TYPE:{
\r
410 return cmmbmemo->audiotype;
\r
414 case CMMB_GET_AUDIO_SAMPLE:{
\r
415 return cmmbmemo->audiosample;
\r
419 case CMMB_GET_BUFF_FREE:{
\r
420 if (arg == CMMB_VIDEO_TYPE){
\r
421 ret = (long)cmmb_ringbuffer_free(&cmmbmemo->buffer_Video);
\r
422 }else if (arg == CMMB_AUDIO_TYPE){
\r
423 ret = (long)cmmb_ringbuffer_free(&cmmbmemo->buffer_Audio);
\r
424 }else if (arg == CMMB_DATA_TYPE){
\r
425 ret = (long)cmmb_ringbuffer_free(&cmmbmemo->buffer_Data);
\r
432 case CMMB_GET_BUFF_AVAIL:{
\r
433 if (arg == CMMB_VIDEO_TYPE){
\r
434 ret = (long)cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
435 }else if (arg == CMMB_AUDIO_TYPE){
\r
436 ret = (long)cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);
\r
437 }else if (arg == CMMB_DATA_TYPE){
\r
438 ret = (long)cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);
\r
452 static unsigned int cmmbmemo_poll(struct file *file, struct poll_table_struct *wait)
\r
454 struct cmmb_demux *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
455 unsigned int mask = 0;
\r
457 DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__);
\r
459 //2todo memo poll, now doing nothing
\r
465 static int cmmbmemo_mmap(struct file *file, struct vm_area_struct *vma)
\r
467 //2 todo memo mmmap, now doing nothing
\r
468 DBG("[CMMB HW]:[memory]:enter cmmbdemux_ioctl\n");
\r
473 struct file_operations cmmbmemeo_fops =
\r
475 .open = cmmbmemo_open,
\r
476 .release = cmmbmemo_release,
\r
477 .read = cmmbmemo_read,
\r
478 .write = cmmbmemo_write,
\r
479 .mmap = cmmbmemo_mmap,
\r
480 .poll = cmmbmemo_poll,
\r
481 .unlocked_ioctl = cmmbmemo_ioctl,
\r
484 static int __init cmmbmemo_init(void)
\r
488 DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__);
\r
489 res =cmmb_register_device(&CMMB_adapter,&cmmbmemo, &cmmbmemeo_fops, NULL, CMMB_DEVICE_MEMO,"cmmb_memo");
\r
490 mutex_init(&CMMB_memo.mutex);
\r
495 static void __exit cmmbmemo_exit(void)
\r
497 DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__);
\r
498 cmmb_unregister_device(cmmbmemo);
\r
499 //mutex_destroy(mutex);
\r
502 module_init(cmmbmemo_init);
\r
503 module_exit(cmmbmemo_exit);
\r
505 MODULE_DESCRIPTION("CMMB demodulator general driver");
\r
506 MODULE_AUTHOR("HT,HZB,HH,LW");
\r
507 MODULE_LICENSE("GPL");
\r