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
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 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
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 = kmalloc(CMMB_VIDEO_BUFFER_SIZE+1, GFP_KERNEL);
\r
68 if (cmmbmemo->video_buf == NULL){
\r
70 DBGERR("[CMMB HW]:[memory]:[err]: cmmb video buffer malloc fail!!!\n");
\r
74 cmmbmemo->audio_buf = kmalloc(CMMB_AUDIO_BUFFER_SIZE+1, GFP_KERNEL);
\r
76 if (cmmbmemo->audio_buf == NULL){
\r
78 DBGERR("[CMMB HW]:[memory]:[err]: cmmb audio buffer malloc fail!!!\n");
\r
82 cmmbmemo->data_buf = kmalloc(1, GFP_KERNEL);
\r
84 if (cmmbmemo->data_buf == NULL){
\r
86 DBGERR("[CMMB HW]:[memory]:[err]: cmmb data buffer malloc fail!!!\n");
\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
95 cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
96 cmmbmemo->r_datatype = CMMB_NULL_TYPE;
\r
98 file->private_data = cmmbmemo; //hzb@20100415,store the cmmbmemo struct in the file private data
\r
99 mutex_unlock(&cmmbmemo->mutex);
\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
111 static ssize_t cmmbmemo_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)
\r
113 struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
114 ssize_t avail_V, avail_A, avail_D;
\r
117 DBG("[CMMB HW]:[memory]:enter cmmb memory read\n");
\r
119 if (cmmbmemo->r_datatype == CMMB_VIDEO_TYPE){
\r
121 DECLARE_WAITQUEUE(wait, current);
\r
123 avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
125 if (avail_V < count){
\r
126 add_wait_queue(&cmmbmemo->buffer_Video.queue, &wait);
\r
127 __set_current_state(TASK_INTERRUPTIBLE);
\r
129 remove_wait_queue(&cmmbmemo->buffer_Video.queue, &wait);
\r
130 if (signal_pending(current)){
\r
131 ret = -ERESTARTSYS;
\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
147 avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
148 DBG("[CMMB HW]:[memory]:cmmb memory read video data awake\n");
\r
151 avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);
\r
152 if (avail_V < count)
\r
155 ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Video, buf, count, 1);
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
160 DECLARE_WAITQUEUE(wait, current);
\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
167 remove_wait_queue(&cmmbmemo->buffer_Audio.queue, &wait);
\r
168 if (signal_pending(current)){
\r
169 ret = -ERESTARTSYS;
\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
185 avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);
\r
186 DBG("[CMMB HW]:[memory]:cmmb memory read audio data awake\n");
\r
189 avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);
\r
190 if (avail_A < count)
\r
193 ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Audio, buf, count, 1);
\r
194 }else if(cmmbmemo->r_datatype == CMMB_DATA_TYPE){
\r
196 DECLARE_WAITQUEUE(wait, current);
\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
203 remove_wait_queue(&cmmbmemo->buffer_Data.queue, &wait);
\r
204 if (signal_pending(current)){
\r
205 ret = -ERESTARTSYS;
\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
221 avail_D= cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);
\r
222 DBG("[CMMB HW]:[memory]:cmmb memory read data awake\n");
\r
225 avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);
\r
226 if (avail_D < count)
\r
229 ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Data, buf, count, 1);
\r
233 cmmbmemo->r_datatype = CMMB_NULL_TYPE;
\r
239 static ssize_t cmmbmemo_write(struct file *file, char __user *buf, size_t count,loff_t *ppos)
\r
241 struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
242 ssize_t free_V, free_A, free_D;
\r
244 static int loop = 0;
\r
246 DBG("[CMMB HW]:[memory]:enter cmmbdemux_write\n");
\r
248 if (cmmbmemo->w_datatype == CMMB_VIDEO_TYPE){
\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
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
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
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
285 int cmmbmemo_valueinit(struct file *file)
\r
287 struct cmmb_memory *cmmbmemo = file->private_data;
\r
290 DBG("[CMMB HW]:[memory]: enter cmmb memo open\n");
\r
292 cmmbmemo->video_buf = NULL;
\r
293 cmmbmemo->audio_buf = NULL;
\r
294 cmmbmemo->data_buf = NULL;
\r
296 cmmbmemo->video_buf = kzalloc(CMMB_VIDEO_BUFFER_SIZE+1, GFP_KERNEL);
\r
298 if (cmmbmemo->video_buf == NULL){
\r
300 DBGERR("[CMMB HW]:[memory]:[err]: cmmb video buffer malloc fail!!!\n");
\r
304 cmmbmemo->audio_buf = kzalloc(CMMB_AUDIO_BUFFER_SIZE+1, GFP_KERNEL);
\r
306 if (cmmbmemo->audio_buf == NULL){
\r
308 DBGERR("[CMMB HW]:[memory]:[err]: cmmb audio buffer malloc fail!!!\n");
\r
312 cmmbmemo->data_buf = kzalloc(1, GFP_KERNEL);
\r
314 if (cmmbmemo->data_buf == NULL){
\r
316 DBGERR("[CMMB HW]:[memory]:[err]: cmmb data buffer malloc fail!!!\n");
\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
325 cmmbmemo->w_datatype = CMMB_NULL_TYPE;
\r
326 cmmbmemo->r_datatype = CMMB_NULL_TYPE;
\r
331 kfree(cmmbmemo->video_buf);
\r
332 kfree(cmmbmemo->audio_buf);
\r
333 kfree(cmmbmemo->data_buf);
\r
337 static long cmmbmemo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
\r
339 struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
342 DBG("[CMMB HW]:[memory]:enter cmmbdemux_ioctl\n");
\r
345 case CMMB_MEMO_WRITE:{
\r
346 cmmbmemo->w_datatype = arg;
\r
350 case CMMB_MEMO_READ:{
\r
351 cmmbmemo->r_datatype = arg;
\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
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
375 case CMMB_MEMO_INIT:{
\r
376 return cmmbmemo_valueinit(file);
\r
380 case CMMB_SET_VIDEO_TYPE:{
\r
381 cmmbmemo->videotype = arg;
\r
385 case CMMB_SET_AUDIO_TYPE:{
\r
386 cmmbmemo->audiotype = arg;
\r
390 case CMMB_SET_AUDIO_SAMPLE:{
\r
391 cmmbmemo->audiosample = arg;
\r
395 case CMMB_GET_VIDEO_TYPE:{
\r
396 return cmmbmemo->videotype;
\r
400 case CMMB_GET_AUDIO_TYPE:{
\r
401 return cmmbmemo->audiotype;
\r
405 case CMMB_GET_AUDIO_SAMPLE:{
\r
406 return cmmbmemo->audiosample;
\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
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
443 static unsigned int cmmbmemo_poll(struct file *file, struct poll_table_struct *wait)
\r
445 struct cmmb_demux *cmmbmemo = (struct cmmb_memory*)file->private_data;
\r
446 unsigned int mask = 0;
\r
448 DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__);
\r
450 //2todo memo poll, now doing nothing
\r
456 static int cmmbmemo_mmap(struct file *file, struct vm_area_struct *vma)
\r
458 //2 todo memo mmmap, now doing nothing
\r
459 DBG("[CMMB HW]:[memory]:enter cmmbdemux_ioctl\n");
\r
464 struct file_operations cmmbmemeo_fops =
\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
475 static int __init cmmbmemo_init(void)
\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
486 static void __exit cmmbmemo_exit(void)
\r
488 DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__);
\r
489 cmmb_unregister_device(cmmbmemo);
\r
490 //mutex_destroy(mutex);
\r
493 module_init(cmmbmemo_init);
\r
494 module_exit(cmmbmemo_exit);
\r
496 MODULE_DESCRIPTION("CMMB demodulator general driver");
\r
497 MODULE_AUTHOR("HT,HZB,HH,LW");
\r
498 MODULE_LICENSE("GPL");
\r