--- /dev/null
+#include "cmmb_memory.h"\r
+#include "cmmb_class.h"\r
+#include <linux/errno.h>\r
+#include <linux/workqueue.h>\r
+#include <asm/atomic.h>\r
+\r
+#if 1\r
+#define DBGERR(x...) printk(KERN_INFO x)\r
+#else\r
+#define DBGERR(x...)\r
+#endif\r
+\r
+#if 0\r
+#define DBG(x...) printk(KERN_INFO x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+struct cmmb_memory CMMB_memo;\r
+static struct cmmb_device* cmmbmemo;\r
+\r
+\r
+static int cmmbmemo_release(struct inode *inode, struct file *file)\r
+{\r
+ struct cmmb_memory *cmmb_memo = (struct cmmb_memory*)file->private_data;\r
+ \r
+ DBG("[CMMB HW]:[memory]: enter cmmb av memory release\n");\r
+ \r
+ mutex_lock(&cmmb_memo->mutex);\r
+ \r
+ cmmb_memo->usr--;\r
+ \r
+ if(cmmb_memo->usr == 0){\r
+ kfree(cmmb_memo->video_buf);\r
+ kfree(cmmb_memo->audio_buf);\r
+ kfree(cmmb_memo->data_buf);\r
+ mutex_unlock(&cmmb_memo->mutex);\r
+ DBG("[CMMB HW]:[memory]: enter cmmb av memory release free buffer\n");\r
+ } else{\r
+ mutex_unlock(&cmmb_memo->mutex);\r
+ } \r
+ return 0;\r
+}\r
+\r
+//hzb@20100416,ÔÚ´ò¿ªÉ豸µÄʱºòÉêÇë¿Õ¼ä\r
+static int cmmbmemo_open(struct inode * inode, struct file * file)\r
+{\r
+ struct cmmb_memory *cmmbmemo = &CMMB_memo;\r
+ int ret = 0;\r
+ \r
+ DBG("[CMMB HW]:[memory]: enter cmmb memo open\n");\r
+\r
+ if (mutex_lock_interruptible(&cmmbmemo->mutex))\r
+ return -ERESTARTSYS;\r
+ \r
+ cmmbmemo->usr++;\r
+ \r
+ if (cmmbmemo->usr == 1)\r
+ {\r
+ DBG("[CMMB HW]:[memory]:cmmb video buffer malloc\n");\r
+ \r
+ cmmbmemo->video_buf = NULL;\r
+ cmmbmemo->audio_buf = NULL;\r
+ cmmbmemo->data_buf = NULL;\r
+\r
+ cmmbmemo->video_buf = kmalloc(CMMB_VIDEO_BUFFER_SIZE+1, GFP_KERNEL);\r
+\r
+ if (cmmbmemo->video_buf == NULL){\r
+ ret = - ENOMEM;\r
+ DBGERR("[CMMB HW]:[memory]:[err]: cmmb video buffer malloc fail!!!\n");\r
+ goto kmalloc_fail;\r
+ }\r
+\r
+ cmmbmemo->audio_buf = kmalloc(CMMB_AUDIO_BUFFER_SIZE+1, GFP_KERNEL);\r
+\r
+ if (cmmbmemo->audio_buf == NULL){\r
+ ret = - ENOMEM;\r
+ DBGERR("[CMMB HW]:[memory]:[err]: cmmb audio buffer malloc fail!!!\n");\r
+ goto kmalloc_fail;\r
+ }\r
+\r
+ cmmbmemo->data_buf = kmalloc(1, GFP_KERNEL);\r
+\r
+ if (cmmbmemo->data_buf == NULL){\r
+ ret = - ENOMEM;\r
+ DBGERR("[CMMB HW]:[memory]:[err]: cmmb data buffer malloc fail!!!\n");\r
+ goto kmalloc_fail;\r
+ }\r
+\r
+ //hzb@20100415,init av ring buffers,cmmb need three ring buffers to store the demuxed data\r
+ cmmb_ringbuffer_init(&cmmbmemo->buffer_Video, cmmbmemo->video_buf, CMMB_VIDEO_BUFFER_SIZE); //init video ring buffer\r
+ cmmb_ringbuffer_init(&cmmbmemo->buffer_Audio, cmmbmemo->audio_buf, CMMB_AUDIO_BUFFER_SIZE); //init audio ring buffer\r
+ cmmb_ringbuffer_init(&cmmbmemo->buffer_Data, cmmbmemo->data_buf, 1); //init data ring buffer\r
+\r
+ cmmbmemo->w_datatype = CMMB_NULL_TYPE;\r
+ cmmbmemo->r_datatype = CMMB_NULL_TYPE;\r
+ }\r
+ file->private_data = cmmbmemo; //hzb@20100415,store the cmmbmemo struct in the file private data \r
+ mutex_unlock(&cmmbmemo->mutex); \r
+ return ret;\r
+ \r
+kmalloc_fail:\r
+ kfree(cmmbmemo->video_buf);\r
+ kfree(cmmbmemo->audio_buf);\r
+ kfree(cmmbmemo->data_buf);\r
+ mutex_unlock(&cmmbmemo->mutex); \r
+ return ret; \r
+}\r
+
+\r
+static ssize_t cmmbmemo_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)\r
+{\r
+ struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;\r
+ ssize_t avail_V, avail_A, avail_D;\r
+ ssize_t ret;\r
+ \r
+ DBG("[CMMB HW]:[memory]:enter cmmb memory read\n");\r
+ \r
+ if (cmmbmemo->r_datatype == CMMB_VIDEO_TYPE){\r
+#if 0 \r
+ DECLARE_WAITQUEUE(wait, current);\r
+ for(;;){\r
+ avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);\r
+ \r
+ if (avail_V < count){ \r
+ add_wait_queue(&cmmbmemo->buffer_Video.queue, &wait);\r
+ __set_current_state(TASK_INTERRUPTIBLE);\r
+ schedule();\r
+ remove_wait_queue(&cmmbmemo->buffer_Video.queue, &wait);\r
+ if (signal_pending(current)){\r
+ ret = -ERESTARTSYS;\r
+ goto out2;\r
+ }\r
+ }\r
+ }\r
+#else\r
+#if 0\r
+ avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);\r
+ while (avail_V < count){\r
+ DBG("[CMMB HW]:[memory]:cmmb memory read video data sleep!!\n");\r
+ spin_lock(cmmbmemo->buffer_Video.lock);\r
+ cmmbmemo->buffer_Video.condition = 0;\r
+ spin_unlock(cmmbmemo->buffer_Video.lock);\r
+ if (wait_event_interruptible(cmmbmemo->buffer_Video.queue, cmmbmemo->buffer_Video.condition))\r
+ return -ERESTARTSYS;\r
+ \r
+ avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);\r
+ DBG("[CMMB HW]:[memory]:cmmb memory read video data awake\n");\r
+ }\r
+#endif \r
+ avail_V = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);\r
+ if (avail_V < count) \r
+ return 0; \r
+#endif \r
+ ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Video, buf, count, 1);
+ \r
+ DBG("[CMMB HW]:[memory]:cmmb memory video read ret = 0x%x\n",ret);\r
+ }else if (cmmbmemo->r_datatype == CMMB_AUDIO_TYPE){\r
+#if 0\r
+ DECLARE_WAITQUEUE(wait, current);\r
+ for(;;){\r
+ avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);\r
+ if (avail_A < count){\r
+ add_wait_queue(&cmmbmemo->buffer_Audio.queue, &wait);\r
+ __set_current_state(TASK_INTERRUPTIBLE);\r
+ schedule();\r
+ remove_wait_queue(&cmmbmemo->buffer_Audio.queue, &wait);\r
+ if (signal_pending(current)){\r
+ ret = -ERESTARTSYS;\r
+ goto out2;\r
+ }\r
+ }\r
+ }\r
+#else\r
+#if 0\r
+ avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);\r
+ while (avail_A < count){\r
+ DBG("[CMMB HW]:[memory]:cmmb memory read audio data sleep!!\n");\r
+ spin_lock(cmmbmemo->buffer_Audio.lock);\r
+ cmmbmemo->buffer_Audio.condition = 0;\r
+ spin_unlock(cmmbmemo->buffer_Audio.lock);\r
+ if (wait_event_interruptible(cmmbmemo->buffer_Audio.queue, cmmbmemo->buffer_Audio.condition))\r
+ return -ERESTARTSYS;\r
+ \r
+ avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);\r
+ DBG("[CMMB HW]:[memory]:cmmb memory read audio data awake\n");\r
+ }\r
+#endif\r
+ avail_A = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio); \r
+ if (avail_A < count) \r
+ return 0; \r
+#endif\r
+ ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Audio, buf, count, 1);\r
+ }else if(cmmbmemo->r_datatype == CMMB_DATA_TYPE){\r
+ #if 0 \r
+ DECLARE_WAITQUEUE(wait, current);\r
+ for(;;){\r
+ avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);\r
+ if (avail_D < count){\r
+ add_wait_queue(&cmmbmemo->buffer_Data.queue, &wait);\r
+ __set_current_state(TASK_INTERRUPTIBLE);\r
+ schedule();\r
+ remove_wait_queue(&cmmbmemo->buffer_Data.queue, &wait);\r
+ if (signal_pending(current)){\r
+ ret = -ERESTARTSYS;\r
+ goto out2;\r
+ }\r
+ }\r
+ }\r
+#else\r
+#if 0\r
+ avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);\r
+ while (avail_D < count){\r
+ DBG("[CMMB HW]:[memory]:cmmb memory read data sleep!!\n");\r
+ spin_lock(cmmbmemo->buffer_Data.lock);\r
+ cmmbmemo->buffer_Data.condition = 0;\r
+ spin_unlock(cmmbmemo->buffer_Data.lock);\r
+ if (wait_event_interruptible(cmmbmemo->buffer_Data.queue, cmmbmemo->buffer_Data.condition))\r
+ return -ERESTARTSYS;\r
+ \r
+ avail_D= cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);\r
+ DBG("[CMMB HW]:[memory]:cmmb memory read data awake\n");\r
+ }\r
+#endif\r
+ avail_D = cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data); \r
+ if (avail_D < count) \r
+ return 0; \r
+#endif\r
+ ret = cmmb_ringbuffer_read(&cmmbmemo->buffer_Data, buf, count, 1);\r
+ }\r
+ \r
+out2:\r
+ cmmbmemo->r_datatype = CMMB_NULL_TYPE;\r
+ return ret;;\r
+}\r
+\r
+\r
+\r
+static ssize_t cmmbmemo_write(struct file *file, char __user *buf, size_t count,loff_t *ppos)\r
+{\r
+ struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;\r
+ ssize_t free_V, free_A, free_D;\r
+ ssize_t ret;\r
+ static int loop = 0;\r
+ \r
+ DBG("[CMMB HW]:[memory]:enter cmmbdemux_write\n");\r
+ \r
+ if (cmmbmemo->w_datatype == CMMB_VIDEO_TYPE){\r
+ \r
+ free_V = cmmb_ringbuffer_free(&cmmbmemo->buffer_Video);\r
+ if (free_V >= count){\r
+ ret = cmmb_ringbuffer_write(&cmmbmemo->buffer_Video, buf, count);\r
+ }
+ //cmmbmemo->w_datatype = CMMB_NULL_TYPE;\r
+ spin_lock(cmmbmemo->buffer_Video.lock);\r
+ cmmbmemo->buffer_Video.condition = 1;\r
+ spin_unlock(cmmbmemo->buffer_Video.lock);\r
+ wake_up_interruptible(&cmmbmemo->buffer_Video.queue);\r
+ }else if (cmmbmemo->w_datatype == CMMB_AUDIO_TYPE){\r
+ free_A = cmmb_ringbuffer_free(&cmmbmemo->buffer_Audio);\r
+ if (free_A >= count){\r
+ ret = cmmb_ringbuffer_write(&cmmbmemo->buffer_Audio, buf, count);\r
+ }\r
+ //cmmbmemo->w_datatype = CMMB_NULL_TYPE;\r
+ spin_lock(cmmbmemo->buffer_Audio.lock);\r
+ cmmbmemo->buffer_Audio.condition = 1;\r
+ spin_unlock(cmmbmemo->buffer_Audio.lock);\r
+ wake_up_interruptible(&cmmbmemo->buffer_Audio.queue);\r
+ }else if(cmmbmemo->w_datatype == CMMB_DATA_TYPE){\r
+ free_D = cmmb_ringbuffer_free(&cmmbmemo->buffer_Data);\r
+ if (free_D >= count){\r
+ ret = cmmb_ringbuffer_write(&cmmbmemo->buffer_Data, buf, count);\r
+ }\r
+ //cmmbmemo->w_datatype = CMMB_NULL_TYPE;\r
+ spin_lock(cmmbmemo->buffer_Data.lock);\r
+ cmmbmemo->buffer_Data.condition = 1;\r
+ spin_unlock(cmmbmemo->buffer_Data.lock);\r
+ wake_up_interruptible(&cmmbmemo->buffer_Data.queue);\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+int cmmbmemo_valueinit(struct file *file)\r
+{\r
+ struct cmmb_memory *cmmbmemo = file->private_data;\r
+ int ret = 0;\r
+\r
+ DBG("[CMMB HW]:[memory]: enter cmmb memo open\n");\r
+\r
+ cmmbmemo->video_buf = NULL;\r
+ cmmbmemo->audio_buf = NULL;\r
+ cmmbmemo->data_buf = NULL;\r
+\r
+ cmmbmemo->video_buf = kzalloc(CMMB_VIDEO_BUFFER_SIZE+1, GFP_KERNEL);\r
+\r
+ if (cmmbmemo->video_buf == NULL){\r
+ ret = - ENOMEM;\r
+ DBGERR("[CMMB HW]:[memory]:[err]: cmmb video buffer malloc fail!!!\n");\r
+ goto kmalloc_fail;\r
+ }\r
+\r
+ cmmbmemo->audio_buf = kzalloc(CMMB_AUDIO_BUFFER_SIZE+1, GFP_KERNEL);\r
+\r
+ if (cmmbmemo->audio_buf == NULL){\r
+ ret = - ENOMEM;\r
+ DBGERR("[CMMB HW]:[memory]:[err]: cmmb audio buffer malloc fail!!!\n");\r
+ goto kmalloc_fail;\r
+ }\r
+\r
+ cmmbmemo->data_buf = kzalloc(1, GFP_KERNEL);\r
+\r
+ if (cmmbmemo->data_buf == NULL){\r
+ ret = - ENOMEM;\r
+ DBGERR("[CMMB HW]:[memory]:[err]: cmmb data buffer malloc fail!!!\n");\r
+ goto kmalloc_fail;\r
+ }\r
+\r
+ //hzb@20100415,init av ring buffers,cmmb need three ring buffers to store the demuxed data\r
+ cmmb_ringbuffer_init(&cmmbmemo->buffer_Video, cmmbmemo->video_buf, CMMB_VIDEO_BUFFER_SIZE); //init video ring buffer\r
+ cmmb_ringbuffer_init(&cmmbmemo->buffer_Audio, cmmbmemo->audio_buf, CMMB_AUDIO_BUFFER_SIZE); //init audio ring buffer\r
+ cmmb_ringbuffer_init(&cmmbmemo->buffer_Data, cmmbmemo->data_buf, 1); //init data ring buffer\r
+\r
+ cmmbmemo->w_datatype = CMMB_NULL_TYPE;\r
+ cmmbmemo->r_datatype = CMMB_NULL_TYPE;\r
+\r
+ return ret;\r
+\r
+kmalloc_fail:\r
+ kfree(cmmbmemo->video_buf);\r
+ kfree(cmmbmemo->audio_buf);\r
+ kfree(cmmbmemo->data_buf);\r
+ return ret; \r
+}\r
+\r
+static long cmmbmemo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\r
+{\r
+ struct cmmb_memory *cmmbmemo = (struct cmmb_memory*)file->private_data;\r
+ long ret = 0;\r
+ \r
+ DBG("[CMMB HW]:[memory]:enter cmmbdemux_ioctl\n");\r
+\r
+ switch (cmd){\r
+ case CMMB_MEMO_WRITE:{\r
+ cmmbmemo->w_datatype = arg;\r
+ }\r
+ break;\r
+ \r
+ case CMMB_MEMO_READ:{\r
+ cmmbmemo->r_datatype = arg;\r
+ }\r
+ break;\r
+\r
+ case CMMB_MEMO_FLUSH_ONE:{\r
+ if (arg == CMMB_VIDEO_TYPE){\r
+ cmmb_ringbuffer_flush(&cmmbmemo->buffer_Video);\r
+ }else if (arg == CMMB_AUDIO_TYPE){\r
+ cmmb_ringbuffer_flush(&cmmbmemo->buffer_Audio);\r
+ }else if (arg == CMMB_DATA_TYPE){\r
+ cmmb_ringbuffer_flush(&cmmbmemo->buffer_Data);\r
+ }else{\r
+ ret = - EINVAL;\r
+ }\r
+ }\r
+ break;\r
+ \r
+ case CMMB_MEMO_FLUSH_ALL:{\r
+ cmmb_ringbuffer_flush(&cmmbmemo->buffer_Video);\r
+ cmmb_ringbuffer_flush(&cmmbmemo->buffer_Audio);\r
+ cmmb_ringbuffer_flush(&cmmbmemo->buffer_Data);\r
+ }\r
+ break;\r
+ \r
+ case CMMB_MEMO_INIT:{\r
+ return cmmbmemo_valueinit(file);\r
+ }\r
+ break;\r
+\r
+ case CMMB_SET_VIDEO_TYPE:{\r
+ cmmbmemo->videotype = arg;\r
+ }\r
+ break;\r
+ \r
+ case CMMB_SET_AUDIO_TYPE:{\r
+ cmmbmemo->audiotype = arg;\r
+ }\r
+ break;\r
+ \r
+ case CMMB_SET_AUDIO_SAMPLE:{\r
+ cmmbmemo->audiosample = arg;\r
+ }\r
+ break;\r
+\r
+ case CMMB_GET_VIDEO_TYPE:{\r
+ return cmmbmemo->videotype;\r
+ }\r
+ break;\r
+ \r
+ case CMMB_GET_AUDIO_TYPE:{\r
+ return cmmbmemo->videotype;\r
+ }\r
+ break;\r
+ \r
+ case CMMB_GET_AUDIO_SAMPLE:{\r
+ return cmmbmemo->audiosample;\r
+ }\r
+ break;\r
+\r
+ case CMMB_GET_BUFF_FREE:{\r
+ if (arg == CMMB_VIDEO_TYPE){\r
+ ret = (long)cmmb_ringbuffer_free(&cmmbmemo->buffer_Video);\r
+ }else if (arg == CMMB_AUDIO_TYPE){\r
+ ret = (long)cmmb_ringbuffer_free(&cmmbmemo->buffer_Audio);\r
+ }else if (arg == CMMB_DATA_TYPE){\r
+ ret = (long)cmmb_ringbuffer_free(&cmmbmemo->buffer_Data);\r
+ }else{\r
+ ret = - EINVAL;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CMMB_GET_BUFF_AVAIL:{\r
+ if (arg == CMMB_VIDEO_TYPE){\r
+ ret = (long)cmmb_ringbuffer_avail(&cmmbmemo->buffer_Video);\r
+ }else if (arg == CMMB_AUDIO_TYPE){\r
+ ret = (long)cmmb_ringbuffer_avail(&cmmbmemo->buffer_Audio);\r
+ }else if (arg == CMMB_DATA_TYPE){\r
+ ret = (long)cmmb_ringbuffer_avail(&cmmbmemo->buffer_Data);\r
+ }else{\r
+ ret = - EINVAL;\r
+ }\r
+ }\r
+ break;\r
+ \r
+ default:\r
+ ;\r
+ break;\r
+ }\r
+ return ret;\r
+}\r
+\r
+static unsigned int cmmbmemo_poll(struct file *file, struct poll_table_struct *wait)\r
+{\r
+ struct cmmb_demux *cmmbmemo = (struct cmmb_memory*)file->private_data;\r
+ unsigned int mask = 0;\r
+\r
+ DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__); \r
+ \r
+ //2todo memo poll, now doing nothing\r
+ \r
+ return mask;\r
+}\r
+\r
+\r
+static int cmmbmemo_mmap(struct file *file, struct vm_area_struct *vma)\r
+{\r
+ //2 todo memo mmmap, now doing nothing\r
+ DBG("[CMMB HW]:[memory]:enter cmmbdemux_ioctl\n");\r
+ return 0;\r
+}\r
+\r
+\r
+struct file_operations cmmbmemeo_fops = \r
+{\r
+ .open = cmmbmemo_open,\r
+ .release = cmmbmemo_release, \r
+ .read = cmmbmemo_read,\r
+ .write = cmmbmemo_write,\r
+ .mmap = cmmbmemo_mmap,\r
+ .poll = cmmbmemo_poll,\r
+ .unlocked_ioctl = cmmbmemo_ioctl,\r
+};\r
+\r
+static int __init cmmbmemo_init(void)\r
+{\r
+ int res;\r
+ \r
+ DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__); \r
+ res =cmmb_register_device(&CMMB_adapter,&cmmbmemo, &cmmbmemeo_fops, NULL, CMMB_DEVICE_MEMO,"cmmb_memo");\r
+ mutex_init(&CMMB_memo.mutex);\r
+ CMMB_memo.usr = 0;\r
+ return res;\r
+}\r
+\r
+static void __exit cmmbmemo_exit(void)\r
+{\r
+ DBG("[CMMB HW]:[memory]:%s [%d]\n",__FUNCTION__,__LINE__); \r
+ cmmb_unregister_device(cmmbmemo);\r
+ //mutex_destroy(mutex);\r
+}\r
+\r
+module_init(cmmbmemo_init);\r
+module_exit(cmmbmemo_exit);\r
+\r
+MODULE_DESCRIPTION("CMMB demodulator general driver");\r
+MODULE_AUTHOR("HT,HZB,HH,LW");\r
+MODULE_LICENSE("GPL");\r
+\r