--- /dev/null
+/* drivers/video/wimo.c\r
+ *\r
+ * Copyright (C) 2010 ROCKCHIP, Inc.\r
+ * author: chenhengming chm@rock-chips.com\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/debugfs.h>
+#include <linux/mempolicy.h>
+#include <linux/sched.h>\r
+#include <asm/io.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/cacheflush.h>\r
+#include <linux/fb.h>\r
+#include <plat/ipp.h>\r
+#include "linux/wimo.h"\r
+#include<linux/rk_fb.h>\r
+#define WIMO_MIN_ALLOC PAGE_SIZE\r
+#define WIMO_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))\r
+\r
+#define WIMO_DEBUG 0\r
+#define WIMO_DEBUG_MSGS 0\r
+\r
+#if WIMO_DEBUG_MSGS\r
+#define DLOG(fmt,args...) \\r
+ do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \\r
+ ##args); } \\r
+ while (0)\r
+#else\r
+#define DLOG(x...) do {} while (0)\r
+#endif\r
+#define WIMO_WRITE_FILE
+\r
+struct win_set {
+ volatile u32 y_offset;
+ volatile u32 c_offset;
+};
+
+struct win0_par {
+ u32 refcount;
+ u32 pseudo_pal[16];
+ u32 y_offset;
+ u32 c_offset;
+ u32 xpos; //size in panel
+ u32 ypos;
+ u32 xsize; //start point in panel
+ u32 ysize;
+ u32 format;
+
+ wait_queue_head_t wait;
+ struct win_set mirror;
+ struct win_set displ;
+ struct win_set done;
+
+ u8 par_seted;
+ u8 addr_seted;
+};
+\r
+\r
+/**\r
+ * struct for global wimo info\r
+ */\r
+struct enc_buff_info{\r
+ u32 bitperpixel;\r
+ u32 mode;\r
+ u32 xaff;\r
+ u32 yaff;\r
+ u32 xpos;\r
+ u32 ypos;\r
+ u32 xsize;\r
+ u32 ysize;\r
+ u32 src_y;\r
+ u32 src_uv;\r
+ u32 dst_width;\r
+ u32 dst_height;\r
+ u32 dst_vir_w;\r
+ u32 dst_vir_h;\r
+ u32 y_offset;\r
+ u32 c_offset;\r
+ u32 src_width;\r
+ u32 src_height;\r
+ long long Frame_Time;
+ unsigned char* ui_buffer;
+ unsigned char* ui_buffer_map;
+ int rotation_flag;\r
+
+
+};
+struct wimo_video_info{\r
+ u32 bitperpixel;\r
+ u32 mode;\r
+ u32 xaff;\r
+ u32 yaff;\r
+ u32 xpos;\r
+ u32 ypos;\r
+ u32 xsize;\r
+ u32 ysize;\r
+ u32 src_y;\r
+ u32 src_uv;\r
+ u32 dst_width;\r
+ u32 dst_height;\r
+ u32 rot_dst_width;\r
+ u32 rot_dst_height;\r
+ u32 src_width;\r
+ u32 src_height;\r
+ u32 set_flag;\r
+ int Last_rotation_flag;\r
+ int rotation_flag;\r
+ long long Last_Frame_Time;
+ struct timeval Wimo_RGB_time;
+ struct timeval Wimo_YUV_time;
+ struct timeval Wimo_Cur_time;
+ struct enc_buff_info enc_buff[4];
+ u32 buffer_num;\r
+ u32 avail_index;\r
+ u32 work_index;\r
+ volatile u32 avail_frame;\r
+ int test_sign;
+ u32 frame_num;\r
+\r
+};\r
+struct wimo_audio_info{\r
+ volatile u32 buffer_size;\r
+ volatile u32 head_offset;\r
+ volatile u32 tail_offset;\r
+ volatile u32 data_len;\r
+ u32 nSamplePerFrame;\r
+ u32 nChannel;\r
+ u32 nBytePerSample;\r
+ u32 nBytePerFrame;\r
+ unsigned char* Out_Buffer;\r
+ struct timeval *time_stamp;\r
+ unsigned char *audio_data;\r
+\r
+};\r
+struct wimo_audio_param{\r
+ u32 buffer_size;\r
+ u32 nSamplePerFrame;\r
+ u32 nChannel;\r
+ u32 nBytePerSample;\r
+ u32 nBytePerFrame;\r
+ u32 Reserverd[7];\r
+};\r
+int rgb_time;\r
+int yuv_time;\r
+struct wimo_info{\r
+ struct wimo_video_info video_info;\r
+ struct wimo_audio_info audio_info;\r
+ struct rw_semaphore rw_sem;\r
+ struct miscdevice dev;\r
+ int video_start_sign;\r
+ int audio_start_sign;\r
+ int start_sign;\r
+ int volumn_open_sign;\r
+ int rotation_flag;\r
+};\r
+struct mutex video_lock;\r
+struct mutex audio_lock;\r
+struct mutex wimo_lock;\r
+//int wimo_prepare_para(struct fb_info *info);\r
+//int wimo_prepare_buff(struct fb_info *info);\r
+//int wimo_prepare(struct fb_info *info);\r
+
+\r
+static int wimo_count = 0;\r
+static struct wimo_info wimo;\r
+#define wdm_rwsem (wimo.rw_sem)\r
+extern int (*audio_data_to_wimo)(void* data,int size,int channel);\r
+extern int (*video_data_to_wimo)(struct fb_info *info,u32 yuv_phy[2]);\r
+\r
+unsigned long temp_vv;\r
+static int frame_num = 0;\r
+static int Is_Wimo_Loaded()\r
+{\r
+ int ret = -1;\r
+ if(wimo_count > 0)\r
+ ret = 0;\r
+ return ret;\r
+}\r
+static int wimo_start(void)\r
+{\r
+ int ret = 0;\r
+ wimo.start_sign = 1;\r
+ \r
+ return ret;\r
+}\r
+static int wimo_stop(void)\r
+{\r
+ int ret = 0;\r
+ \r
+ wimo.start_sign = 0;\r
+ return ret;\r
+}\r
+static int wimo_set_rotation(int rotation_flag)\r
+{\r
+ int ret = 0;\r
+ \r
+ wimo.rotation_flag = rotation_flag;\r
+ return ret;\r
+}\r
+struct file* wimo_filp;\r
+mm_segment_t old_fs;\r
+struct file* wimo_filp_output;\r
+mm_segment_t old_fs_output;\r
+static int wimo_audio_open(unsigned long *temp)\r
+{\r
+ int ret = 0;\r
+ struct wimo_audio_info *audio_info = &wimo.audio_info;\r
+ struct timeval timeFirst;\r
+ do_gettimeofday(&timeFirst); \r
+ if(wimo.start_sign == 0)\r
+ {\r
+ printk("Apk didn't start when audio start \n");\r
+ return -1;\r
+ }\r
+ memset(audio_info, 0, sizeof(struct wimo_audio_info));\r
+ wimo.audio_start_sign = 1; \r
+ audio_info->Out_Buffer = NULL;\r
+\r
+ audio_info->buffer_size = 50;\r
+ audio_info->nSamplePerFrame = 1024;\r
+ audio_info->nBytePerSample = 2;\r
+ audio_info->nChannel = 2;\r
+ audio_info->nBytePerFrame = 4096;\r
+ \r
+ \r
+ audio_info->head_offset = 0;\r
+ audio_info->tail_offset = 0;\r
+ audio_info->data_len = 0;\r
+ \r
+ audio_info->audio_data = (unsigned char*)kmalloc(audio_info->buffer_size * audio_info->nBytePerFrame,GFP_KERNEL);\r
+ audio_info->time_stamp = (struct timeval*)kmalloc(audio_info->buffer_size * sizeof(struct timeval),GFP_KERNEL);\r
+ memset(audio_info->audio_data, 0,audio_info->buffer_size * audio_info->nBytePerFrame);\r
+ printk("audio_info->buffer_size * audio_info->nBytePerFrame timestamp %d audio_info->Out_Buffer %x time %lld %x %x\n",\r
+ audio_info->buffer_size * audio_info->nBytePerFrame,audio_info->time_stamp,audio_info->Out_Buffer,(int64_t)timeFirst.tv_sec*1000000ll + timeFirst.tv_usec\r
+ ,__pa(audio_info->audio_data),__pa(audio_info->time_stamp));\r
+ #ifdef WIMO_WRITE_FILE\r
+ wimo_filp = NULL;\r
+ wimo_filp = filp_open("/data/test/input_cmp.pcm",O_CREAT|O_TRUNC|O_RDWR,0);\r
+ if (wimo_filp)\r
+ {\r
+ old_fs = get_fs();\r
+ set_fs(get_ds());\r
+ }\r
+ wimo_filp_output = NULL;\r
+ wimo_filp_output = filp_open("/data/test/output_cmp.pcm",O_CREAT|O_TRUNC|O_RDWR,0);\r
+ if (wimo_filp_output)\r
+ {\r
+ old_fs_output = get_fs();\r
+ set_fs(get_ds());\r
+ }\r
+ #endif\r
+ return ret;\r
+}\r
+static int wimo_audio_close(void)\r
+{\r
+ int ret = 0;\r
+ struct wimo_audio_info *audio_info = &wimo.audio_info;\r
+ #ifdef WIMO_WRITE_FILE\r
+ set_fs(old_fs);\r
+ filp_close(wimo_filp,NULL);\r
+\r
+ set_fs(old_fs_output);\r
+ filp_close(wimo_filp_output,NULL);\r
+\r
+ #endif\r
+ printk("wimo_audio_close\n");\r
+ kfree((void *)audio_info->time_stamp);\r
+ kfree((void *)audio_info->audio_data);\r
+ \r
+ audio_info->Out_Buffer = NULL;\r
+ wimo.audio_start_sign = 0;\r
+ return ret;\r
+}\r
+static void wimo_audio_set_para(struct wimo_audio_param *param)\r
+{\r
+ struct wimo_audio_info *audio_info = &wimo.audio_info;\r
+ audio_info->buffer_size = param->buffer_size;\r
+ audio_info->nSamplePerFrame = param->nSamplePerFrame;\r
+ audio_info->nChannel = param->nChannel;\r
+ audio_info->nBytePerSample = param->nBytePerSample;\r
+ audio_info->nBytePerFrame = param->nBytePerFrame;\r
+ DLOG("param %d %d %d %d %d audio_info %d %d %d %d %d",\r
+ param->buffer_size,param->nSamplePerFrame,param->nChannel,param->nBytePerSample,param->nBytePerFrame,\r
+ audio_info->buffer_size,audio_info->nSamplePerFrame,audio_info->nChannel,audio_info->nBytePerSample,audio_info->nBytePerFrame);\r
+ return;\r
+}\r
+\r
+static void wimo_audio_set_vol(u32 temp_data)\r
+{\r
+ wimo.volumn_open_sign = temp_data;\r
+ return;\r
+}\r
+static int wimo_audio_find_frame()\r
+{\r
+ struct wimo_audio_info *audio_info = &wimo.audio_info;\r
+ int ret = 0;\r
+ if(audio_info->data_len >= 1)\r
+ {\r
+ audio_info->Out_Buffer = (void*)(&audio_info->audio_data[audio_info->head_offset * audio_info->nBytePerFrame]);\r
+ //wimo_filp_output->f_op->write(wimo_filp_output, audio_info->Out_Buffer, audio_info->nBytePerFrame, &wimo_filp_output->f_pos);\r
+ audio_info->data_len --;\r
+ audio_info->head_offset ++;\r
+ audio_info->head_offset %= audio_info->buffer_size;\r
+ }\r
+ else\r
+ {\r
+ ret = -1;\r
+ }\r
+ \r
+ return ret;\r
+}\r
+static int wimo_audio_prepare(void* data,int size,int channel)\r
+{\r
+ int ret = 0;\r
+ mutex_lock(&audio_lock);\r
+ \r
+ if(wimo.audio_start_sign && wimo.start_sign)\r
+ {\r
+ struct timeval timeFirst;\r
+ unsigned long* temp = (unsigned long*)data;\r
+ struct wimo_audio_info *audio_info = &wimo.audio_info;\r
+ unsigned char* buf = data;\r
+ do_gettimeofday(&timeFirst); \r
+ memcpy((void*)(&audio_info->audio_data[audio_info->tail_offset * audio_info->nBytePerFrame]), (void*)data,size);\r
+ memcpy((void*)(&audio_info->time_stamp[audio_info->tail_offset]),(void*)(&timeFirst),sizeof(struct timeval));\r
+ audio_info->tail_offset ++;\r
+ audio_info->tail_offset %= audio_info->buffer_size;\r
+ wimo_filp->f_op->write(wimo_filp, data, size, &wimo_filp->f_pos);\r
+ if(audio_info->data_len + 1 < audio_info->buffer_size)\r
+ {\r
+ audio_info->data_len ++;\r
+ }\r
+ else\r
+ {\r
+ audio_info->head_offset=audio_info->tail_offset;\r
+ audio_info->data_len = audio_info->buffer_size;\r
+ }\r
+// if(wimo.volumn_open_sign==0)\r
+// {\r
+// memset((void*)data,0,size);\r
+//\r
+// }\r
+ } \r
+ else\r
+ {\r
+ //DLOG("wimo_video not open\n");\r
+ ret = AUDIO_ENCODER_CLOSED;\r
+ }\r
+ if(wimo.start_sign && wimo.volumn_open_sign == 0)\r
+ memset((void*)data,0,size);\r
+ \r
+ mutex_unlock(&audio_lock);\r
+ return ret;\r
+}\r
+/*\r
+ wimo_video can be opened once at a time.\r
+ Other user must wait for last open closed.\r
+*/\r
+static int wimo_video_open(unsigned long *temp)\r
+{
+ struct wimo_video_info *video_info = &wimo.video_info;\r
+ int i;\r
+ int ret =0 ;\r
+ printk("wimo_video_open\n");\r
+ if(wimo.start_sign == 0)\r
+ {\r
+ printk("Apk didn't start when video start ");\r
+ return -1;\r
+ }\r
+ if(wimo.video_start_sign == 1)\r
+ {\r
+ printk("last wimo_video still opened ,something wrong\n");\r
+ \r
+ }\r
+ memset(&wimo.video_info,0,sizeof(struct wimo_video_info));\r
+ if(wimo.rotation_flag < 0 )\r
+ DLOG("wimo_set_buff rotation_flag < 0,maybe something wrong\n");\r
+ \r
+ video_info->Last_rotation_flag = -1;\r
+ video_info->rotation_flag = wimo.rotation_flag;\r
+ for(i = 0; i < temp[3]; i++)\r
+ {
+ video_info->enc_buff[i].ui_buffer= (unsigned char*)temp[i+4];\r
+ video_info->enc_buff[i].ui_buffer_map= ioremap(temp[i+4],temp[2]);\r
+ if(video_info->enc_buff[i].ui_buffer_map == NULL)\r
+ {
+ printk("can't map a buffer for ui\n");
+ return -EFAULT;
+ }
+ }\r
+ video_info->buffer_num = temp[3];\r
+ video_info->dst_width = (temp[0] + 15) & 0xfff0;\r
+ video_info->dst_height = (temp[1] + 15) & 0xfff0;\r
+ video_info->xsize = video_info->dst_width;\r
+ video_info->ysize = video_info->dst_height;\r
+ wimo.video_start_sign = 1; \r
+ printk("video_info->dst_width %d video_info->dst_height %d num %d %x ui_buffer %x %x size %d map %x %x\n",\r
+ video_info->dst_width,video_info->dst_height,video_info->buffer_num,(long)&wimo.video_info.buffer_num,\r
+ video_info->enc_buff[0].ui_buffer,video_info->enc_buff[1].ui_buffer,temp[2],video_info->enc_buff[0].ui_buffer_map\r
+ ,video_info->enc_buff[1].ui_buffer_map);\r
+ rgb_time = yuv_time = 0;\r
+ return ret;\r
+}\r
+/*\r
+close wimo_video .\r
+release resources.\r
+\r
+*/\r
+static int wimo_video_close(struct wimo_video_info *video_info)\r
+{
+ int i ;\r
+ int ret = 0;\r
+ if(video_info->buffer_num && wimo.video_start_sign && wimo.start_sign)\r
+ printk("something is okay with wimo video in close");\r
+
+ else
+ printk("somethint wrong with wimo video in close");\r
+ wimo.video_start_sign = 0;\r
+ DLOG("video_info->dst_width %d video_info->dst_height %d ui_buffer %x %x ui_buffer_map %x %x\n",\r
+ video_info->dst_width,video_info->dst_height,video_info->enc_buff[0].ui_buffer,video_info->enc_buff[1].ui_buffer,\r
+ video_info->enc_buff[0].ui_buffer_map,video_info->enc_buff[1].ui_buffer_map);\r
+ \r
+ for(i = 0; i < 4; i++)
+ {
+ DLOG("closebuf ui_buffer %x ui_buffer_map %x ui_buffer_map addr %x wimo_info.buffer_num %d i %d\n",\r
+ (unsigned int)video_info->enc_buff[i].ui_buffer,(unsigned int)video_info->enc_buff[i].ui_buffer_map,(unsigned long)(&video_info->enc_buff[i].ui_buffer_map),video_info->buffer_num,i);\r
+ if(video_info->enc_buff[i].ui_buffer_map!=0)\r
+ {
+ iounmap(video_info->enc_buff[i].ui_buffer_map);\r
+ video_info->enc_buff[i].ui_buffer_map = 0;\r
+ video_info->enc_buff[i].ui_buffer = 0;\r
+ }
+ }\r
+ return ret;\r
+}
+
+/*\r
+get video frame \r
+it return -1 when no frame is availiable\r
+*/\r
+static int wimo_video_find_frame(unsigned long* temp_data,struct wimo_video_info *video_info)\r
+{
+
+ int ret = 0;\r
+ do_gettimeofday(&video_info->Wimo_Cur_time);\r
+ DLOG("wimo_find_frame video_info %x video_info->buffer_num %d avail_index %d avail_frame %d work_index %d testIgn %d time %lld curtime %lld last_time %lld %lld %lld yuv rgb time %lld %lld yuv_time %d\n",\r
+ (unsigned long)video_info,video_info->buffer_num, video_info->avail_index,video_info->avail_frame,video_info->work_index,video_info->test_sign,video_info->enc_buff[video_info->avail_index].Frame_Time,\r
+ (long long)video_info->Wimo_Cur_time.tv_sec * 1000000ll + video_info->Wimo_Cur_time.tv_usec,video_info->Last_Frame_Time,video_info->enc_buff[video_info->avail_index].Frame_Time,\r
+ video_info->enc_buff[1-video_info->avail_index].Frame_Time,(long long)video_info->Wimo_YUV_time.tv_sec * 1000000ll + video_info->Wimo_YUV_time.tv_usec\r
+ ,(long long)video_info->Wimo_RGB_time.tv_sec * 1000000ll + video_info->Wimo_RGB_time.tv_usec,yuv_time);\r
+ if(video_info->avail_frame)\r
+ {
+ if(video_info->Last_Frame_Time > video_info->enc_buff[video_info->avail_index].Frame_Time)\r
+ {
+
+ DLOG("wimo_find_frame error avail_index %d avail_frame %d work_index %d testIgn %d time %lld curtime %lld last_time %lld %lld %lld yuv rgb time %lld %lld yuv_time %d\n",\r
+ video_info->avail_index,video_info->avail_frame,video_info->work_index,video_info->test_sign,video_info->enc_buff[video_info->avail_index].Frame_Time,\r
+ (long long)video_info->Wimo_Cur_time.tv_sec * 1000000ll + video_info->Wimo_Cur_time.tv_usec,video_info->Last_Frame_Time,video_info->enc_buff[video_info->avail_index].Frame_Time,\r
+ video_info->enc_buff[1-video_info->avail_index].Frame_Time,(long long)video_info->Wimo_YUV_time.tv_sec * 1000000ll + video_info->Wimo_YUV_time.tv_usec\r
+ ,(long long)video_info->Wimo_RGB_time.tv_sec * 1000000ll + video_info->Wimo_RGB_time.tv_usec,yuv_time);\r
+ video_info->test_sign = 2;\r
+ }
+ video_info->Last_Frame_Time = video_info->enc_buff[video_info->avail_index].Frame_Time;\r
+
+ }
+ else
+ {
+ if(((long long)video_info->Wimo_Cur_time.tv_sec * 1000000ll + video_info->Wimo_Cur_time.tv_usec > video_info->Last_Frame_Time + 1000000ll || video_info->frame_num < 30) && video_info->frame_num!=0)\r
+ {
+
+ DLOG("wimo_find_frame wait second avail_index %d avail_frame %d work_index %d testIgn %d time %lld curtime %lld last_time %lld %lld %lld yuv rgb time %lld %lld yuv_time %d\n",\r
+ video_info->avail_index,video_info->avail_frame,video_info->work_index,\r
+ video_info->test_sign,video_info->enc_buff[video_info->avail_index].Frame_Time,\r
+ (long long)video_info->Wimo_Cur_time.tv_sec * 1000000ll + video_info->Wimo_Cur_time.tv_usec,video_info->Last_Frame_Time,video_info->enc_buff[video_info->avail_index].Frame_Time,\r
+ video_info->enc_buff[1- video_info->avail_index].Frame_Time,(long long)video_info->Wimo_YUV_time.tv_sec * 1000000ll + video_info->Wimo_YUV_time.tv_usec\r
+ ,(long long)video_info->Wimo_RGB_time.tv_sec * 1000000ll + video_info->Wimo_RGB_time.tv_usec,yuv_time);\r
+ video_info->test_sign = 3;\r
+ video_info->Last_Frame_Time =(long long)video_info->Wimo_Cur_time.tv_sec * 1000000ll + video_info->Wimo_Cur_time.tv_usec;\r
+ if(video_info->mode == 0 )\r
+ {
+ video_info->Wimo_RGB_time.tv_sec = video_info->Wimo_Cur_time.tv_sec;\r
+ video_info->Wimo_RGB_time.tv_usec = video_info->Wimo_Cur_time.tv_usec;\r
+ }
+ \r
+ video_info->avail_index--;\r
+ video_info->avail_index %= video_info->buffer_num;\r
+ video_info->avail_frame++;\r
+ \r
+ }
+ else
+ {
+ video_info->test_sign = 4;\r
+ DLOG ("no avail frame \n");\r
+ return -1;
+ }
+
+ }
+ temp_data[0] = (video_info->enc_buff[video_info->avail_index].bitperpixel << 16);\r
+ temp_data[0] |= video_info->enc_buff[video_info->avail_index].mode;\r
+
+ temp_data[1] = video_info->avail_index ;\r
+ memcpy(&temp_data[2],&video_info->enc_buff[video_info->avail_index].Frame_Time,8);\r
+ temp_data[4] = video_info->enc_buff[video_info->avail_index].rotation_flag| (yuv_time<<16);\r
+ temp_data[5] = video_info->Wimo_Cur_time.tv_sec;\r
+ temp_data[6] = video_info->Wimo_Cur_time.tv_usec;\r
+\r
+ video_info->avail_index++;\r
+ video_info->avail_index %= video_info->buffer_num;\r
+ video_info->avail_frame--;\r
+ video_info->frame_num++;\r
+ yuv_time = rgb_time = 0;
+ \r
+ return ret;\r
+}
+\r
+#if 1
+ int wimo_prepare_para(struct fb_info *info,struct wimo_video_info *video_info,struct enc_buff_info *enc_buff)\r
+{
+
+ //struct rk29fb_inf *inf = dev_get_drvdata(info->device);\r
+ struct rk_fb_inf *inf = dev_get_drvdata(info->device);
+ struct fb_var_screeninfo *var = &info->var;\r
+ int ret = 0;\r
+ struct layer_par *par = NULL; \r
+ struct fb_fix_screeninfo * fix = &info->fix;\r
+ struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver *)info->par; \r
+ int layer_id = 0; \r
+ layer_id = get_fb_layer_id(fix); \r
+ if (layer_id < 0) \r
+ { \r
+ return -ENODEV; \r
+ } \r
+ else \r
+ { \r
+ par = dev_drv->layer_par[layer_id]; \r
+ }\r
+ video_info->mode = inf->video_mode;\r
+ video_info->src_width = var->xres_virtual;\r
+ video_info->src_height = var->yres_virtual/2;\r
+ if(inf->video_mode == 0 )
+ {\r
+ \r
+\r
+ if(par->format == 1)
+ {
+ enc_buff->bitperpixel = 16;
+ enc_buff->rotation_flag = video_info->rotation_flag;\r
+ }
+ else
+ {
+ enc_buff->bitperpixel =32;// wimo_info.bitperpixel_fb1;
+ enc_buff->rotation_flag = video_info->rotation_flag + 8;\r
+ }
+ enc_buff->dst_width = video_info->dst_width;\r
+ enc_buff->dst_height = video_info->dst_height;\r
+
+
+
+ enc_buff->src_width = video_info->src_width;\r
+ enc_buff->src_height = video_info->src_height;\r
+
+
+ enc_buff->dst_vir_w = video_info->dst_width;\r
+ enc_buff->dst_vir_h = video_info->dst_height;\r
+ enc_buff->y_offset = enc_buff->c_offset = 0;
+ enc_buff->mode = 0;
+
+ enc_buff->src_y = info->fix.smem_start + par->y_offset;//info->screen_base + par->y_offset;//info_buffer[8];
+ enc_buff->src_uv = info->fix.smem_start + par->y_offset + video_info->src_width * video_info->src_height;//dst_width*dst_height;//+ par->y_offset + dst_width*dst_height;//info_buffer[9];\r
+ enc_buff->Frame_Time = (long long)video_info->Wimo_RGB_time.tv_sec * 1000000ll + video_info->Wimo_RGB_time.tv_usec;\r
+
+ if(0)//rotation_sign == IPP_ROT_90 || rotation_sign == IPP_ROT_270)
+ {
+ if(enc_buff->dst_vir_w > enc_buff->dst_vir_h)
+ {
+ enc_buff->dst_height = enc_buff->dst_vir_h;
+ enc_buff->dst_width = ((enc_buff->dst_vir_h * enc_buff->dst_vir_h) / enc_buff->dst_vir_w) & 0xfffc;
+ if(par->format == 1)
+ enc_buff->c_offset = enc_buff->y_offset = ((enc_buff->dst_vir_w - enc_buff->dst_width ) ) & 0xfffc;
+
+ else
+ enc_buff->c_offset = enc_buff->y_offset = ((enc_buff->dst_vir_w - enc_buff->dst_width ) *2) & 0xfffc;
+
+ }
+ else
+ {
+ enc_buff->dst_width = enc_buff->dst_vir_w;
+ enc_buff->dst_height = ((enc_buff->dst_vir_w * enc_buff->dst_vir_w) / enc_buff->dst_vir_h) ;
+ enc_buff->y_offset = (enc_buff->dst_vir_h - enc_buff->dst_height ) * enc_buff->dst_vir_w * 2;
+ enc_buff->c_offset = (enc_buff->dst_vir_h - enc_buff->dst_height ) * enc_buff->dst_vir_w ; ;
+ }
+ }
+ // printk("width height %d %d vir_w %d vir_h %d y_offset %d c_offset %d rotation_sign %d\n",enc_buff->dst_width,enc_buff->dst_height,enc_buff->dst_vir_w,enc_buff->dst_vir_h,enc_buff->y_offset,
+ // enc_buff->c_offset,rotation_sign);
+ // printk("mode 0 enc_buff.src0.w %d %d enc_buff %x enc_buff->mode %d bit %d format %d\n",enc_buff->src_width,enc_buff->src_height,(unsigned long)enc_buff
+ // ,enc_buff->mode,enc_buff->bitperpixel,par->format);
+
+ }
+ DLOG(" test %d %d %d %d %d %d %x %x\n",enc_buff->dst_vir_w,enc_buff->dst_width,enc_buff->dst_vir_h,enc_buff->dst_height\r
+ ,video_info->Last_rotation_flag , enc_buff->rotation_flag,\r
+ video_info->enc_buff[0].ui_buffer_map,video_info->enc_buff[1].ui_buffer_map);\r
+ if((enc_buff->dst_vir_w != enc_buff->dst_width || enc_buff->dst_vir_h != enc_buff->dst_height ) && video_info->Last_rotation_flag != enc_buff->rotation_flag)//wimo_info.Last_rotation_flag != enc_buff->rotation_sign)\r
+ {
+ int i;
+ if(enc_buff->rotation_flag & 0x8)\r
+ {
+ for(i = 0; i < video_info->buffer_num; i++)\r
+ {
+ memset(video_info->enc_buff[i].ui_buffer_map,0,enc_buff->dst_vir_w * enc_buff->dst_vir_h * 4);//dst_width*dst_height);\r
+ }
+ }
+ else if((enc_buff->rotation_flag & 0x8 )== 0)\r
+ {
+ for(i = 0; i < video_info->buffer_num; i++)\r
+ {
+ memset(video_info->enc_buff[i].ui_buffer_map,0,enc_buff->dst_vir_w * enc_buff->dst_vir_h * 2);//dst_width*dst_height);\r
+ }
+ }
+ // memset(ui_buffer_map,0,enc_buff->dst_vir_w * enc_buff->dst_vir_h * 4);//dst_width*dst_height);
+ //memset(ui_buffer_map + enc_buff->dst_height * enc_buff->dst_width, 0x80,enc_buff->dst_height * enc_buff->dst_width / 2);//dst_width*dst_height,0x80,dst_width*dst_height/2);
+ // printk("rotation change wimo_info.Last_rotation_flag %d enc_buff->rotation_sign %d\n",wimo_info.Last_rotation_flag,enc_buff->rotation_sign);
+ }
+ video_info->Last_rotation_flag = enc_buff->rotation_flag;\r
+
+ return ret;\r
+}
+ int wimo_prepare_buff(struct enc_buff_info *enc_buff)\r
+{
+
+ struct rk29_ipp_req overlay_req;
+ struct rk29_ipp_req overlay_req_1;
+ int err = 0;\r
+ \r
+ memset(&overlay_req, 0 , sizeof(overlay_req));
+ memset(&overlay_req_1, 0 , sizeof(overlay_req_1));
+ //printk("inf->video_mode %d\n",inf->video_mode);
+ if(enc_buff->mode == 0 )
+ {
+ \r
+ overlay_req.src0.YrgbMst = enc_buff->src_y;//info->fix.smem_start + par->y_offset;//info->screen_base + par->y_offset;//info_buffer[8];
+ overlay_req.src0.CbrMst = enc_buff->src_uv;//info->fix.smem_start + par->y_offset + enc_buff->src_width * enc_buff->src_height;//dst_width*dst_height;//+ par->y_offset + dst_width*dst_height;//info_buffer[9];
+ overlay_req.src0.w = enc_buff->src_width ;//dst_width;//info_buffer[2];
+ overlay_req.src0.h = enc_buff->src_height ;//dst_height;//info_buffer[3];
+ overlay_req.src0.fmt = (enc_buff->bitperpixel == 16) ? 1 : 0;//3;
+ overlay_req.dst0.YrgbMst = (unsigned long)(enc_buff->ui_buffer + enc_buff->y_offset);//overlay_buffer + info_buffer[4] + info_buffer[5] * dst_width;\r
+ overlay_req.dst0.CbrMst = (unsigned long)(enc_buff->ui_buffer + enc_buff->dst_vir_w * enc_buff->dst_height + enc_buff->c_offset);//dst_width*dst_height;//(unsigned char*) overlay_buffer + dst_width*dst_height +info_buffer[4] + ( info_buffer[5] * dst_width) / 2;// info_buffer[6] * info_buffer[7];\r
+
+ overlay_req.dst0.w = enc_buff->dst_width ;//dst_width;//info_buffer[6];
+ overlay_req.dst0.h = enc_buff->dst_height ;//dst_height;//info_buffer[7];
+ overlay_req.dst0.fmt = (enc_buff->bitperpixel== 16) ? 1 : 0;//3;3;
+ overlay_req.deinterlace_enable = 0;
+ overlay_req.timeout = 1000000;
+ overlay_req.src_vir_w = enc_buff->src_width ;//dst_width;//info_buffer[2];
+ overlay_req.dst_vir_w = enc_buff->dst_vir_w ;//dst_width;
+
+
+ //printk("mode 0 overlay_req.src0.w %d %d enc_buff %x\n",overlay_req.src0.w,overlay_req.src0.h,(unsigned long)enc_buff);
+ overlay_req.flag = enc_buff->rotation_flag & 0x7;\r
+ err = ipp_blit_sync(&overlay_req);\r
+ if(err)
+ goto WIMO_IPP_ERROR;
+ //printk("mode 0err %d w h fmt time out %d %d %d %d",err,overlay_req.src0.w,overlay_req.src0.h,overlay_req.src0.fmt,overlay_req.timeout);
+ // printk("overlay_req.dst0.w %d overlay_req.dst0.h %d overlay_req.src0.w %d overlay_req.src0.h %d\n",overlay_req.dst0.w,overlay_req.dst0.h,overlay_req.src0.w,overlay_req.src0.h);
+
+
+
+
+
+ }
+ else
+ {
+
+ \r
+ if(enc_buff->xaff * 3 < enc_buff->xsize || enc_buff->yaff * 3 < enc_buff->ysize)// 3time or bigger scale up\r
+ {
+ unsigned long mid_width, mid_height;
+ struct rk29_ipp_req overlay_req_1;
+ if(enc_buff->xaff * 3 < enc_buff->xsize)
+ mid_width = enc_buff->xaff * 3;
+ else
+ mid_width = enc_buff->xsize;
+
+ if(enc_buff->yaff * 3 < enc_buff->ysize)
+ mid_height = enc_buff->yaff * 3;
+ else
+ mid_height = enc_buff->ysize;
+ overlay_req.src0.YrgbMst = enc_buff->src_y;//info_buffer[8];
+ overlay_req.src0.CbrMst = enc_buff->src_uv;//info_buffer[9];
+ overlay_req.src0.w = enc_buff->xaff;// info_buffer[2];
+ overlay_req.src0.h = enc_buff->yaff;// info_buffer[3];
+ overlay_req.src0.fmt = 3;
+ overlay_req.dst0.YrgbMst = (unsigned long)(enc_buff->ui_buffer + 2048000) ;//info_buffer[4] + info_buffer[5] * dst_width; //С³ß´çƬԴÐèÒª2´Î·Å´ó£¬ËùÒÔ½«bufferµÄºó°ë¶ÎÓÃÓÚ»º´æ\r
+ overlay_req.dst0.CbrMst = (unsigned long)( (unsigned char*) enc_buff->ui_buffer + mid_height * mid_width + 2048000);\r
+
+ overlay_req.dst0.w = mid_width;//info_buffer[6];
+ overlay_req.dst0.h = mid_height;//info_buffer[7];
+ overlay_req.dst0.fmt = 3;
+ overlay_req.timeout = 100000;
+ overlay_req.src_vir_w = enc_buff->xaff;//info_buffer[2];
+ overlay_req.dst_vir_w = mid_width;//dst_width;
+ overlay_req.flag = IPP_ROT_0;
+\r
+\r
+\r
+\r
+ overlay_req_1.src0.YrgbMst = (unsigned long)(enc_buff->ui_buffer + 2048000);\r
+ overlay_req_1.src0.CbrMst = (unsigned long)((unsigned char*) enc_buff->ui_buffer + mid_height * mid_width + 2048000);\r
+ overlay_req_1.src0.w = mid_width;
+ overlay_req_1.src0.h = mid_height;// info_buffer[3];
+ overlay_req_1.src0.fmt = 3;
+ overlay_req_1.dst0.YrgbMst = (unsigned long)(enc_buff->ui_buffer + ((enc_buff->xpos + 1)&0xfffe) + enc_buff->ypos * enc_buff->dst_width);//info_buffer[4] + info_buffer[5] * dst_width;\r
+ overlay_req_1.dst0.CbrMst = (unsigned long)((unsigned char*) enc_buff->ui_buffer + enc_buff->dst_width * enc_buff->dst_height + \r
+ ((enc_buff->xpos + 1)&0xfffe) + ( enc_buff->ypos / 2)* enc_buff->dst_width) ;\r
+
+ overlay_req_1.dst0.w = enc_buff->xsize;//info_buffer[6];
+ overlay_req_1.dst0.h = enc_buff->ysize;//info_buffer[7];
+ overlay_req_1.dst0.fmt = 3;
+ overlay_req_1.timeout = 100000;
+ overlay_req_1.src_vir_w = mid_width;//info_buffer[2];
+ overlay_req_1.dst_vir_w = enc_buff->dst_vir_w;//dst_width;
+ overlay_req_1.flag = IPP_ROT_0;
+
+
+ err = ipp_blit_sync(&overlay_req);
+ if(err)
+ goto WIMO_IPP_ERROR;
+ dmac_flush_range(enc_buff->ui_buffer_map,enc_buff->ui_buffer_map + enc_buff->dst_height * enc_buff->dst_width * 3/2);//dst_width*dst_height*3/2);\r
+ err = ipp_blit_sync(&overlay_req_1);
+ if(err)
+ goto WIMO_IPP_ERROR;
+ // printk("err1 %d w h fmt time out %d %d %d %d workindex %d encbuff %x xaff %d yaff %d xsize %d ysize %d",
+ // err,overlay_req.src0.w,overlay_req.src0.h,overlay_req.src0.fmt,overlay_req.timeout,wimo_info.work_index,(unsigned long)enc_buff
+ // ,enc_buff->xaff,enc_buff->yaff,enc_buff->xsize,enc_buff->ysize);
+ }
+ else
+ {
+ overlay_req.src0.YrgbMst = enc_buff->src_y;//info_buffer[8];
+ overlay_req.src0.CbrMst = enc_buff->src_uv;//info_buffer[9];
+ overlay_req.src0.w = enc_buff->xaff;// info_buffer[2];
+ overlay_req.src0.h = enc_buff->yaff;// info_buffer[3];
+ overlay_req.src0.fmt = 3;
+ overlay_req.dst0.YrgbMst = (unsigned long)(enc_buff->ui_buffer + ((enc_buff->xpos + 1)&0xfffe) + enc_buff->ypos * enc_buff->dst_width);//info_buffer[4] + info_buffer[5] * dst_width;\r
+ overlay_req.dst0.CbrMst = (unsigned long)((unsigned char*) enc_buff->ui_buffer + ((enc_buff->xpos + 1)&0xfffe) + \r
+ ( enc_buff->ypos / 2)* enc_buff->dst_width + enc_buff->dst_width * enc_buff->dst_height);\r
+
+ overlay_req.dst0.w = enc_buff->xsize;//wimo_info.xsize;//wimo_info.xaff;// wimo_info.xsize;//info_buffer[6];
+ overlay_req.dst0.h = (enc_buff->ysize + 1) & 0xfffe;//(wimo_info.ysize + 1) & 0xfffe;//wimo_info.yaff;//(wimo_info.ysize + 1) & 0xfffe;//info_buffer[7];
+ overlay_req.dst0.fmt = 3;
+ overlay_req.timeout = 100000;
+ overlay_req.src_vir_w = (enc_buff->xaff + 15) & 0xfff0;//enc_buff->xaff;//info_buffer[2];
+ overlay_req.dst_vir_w = enc_buff->dst_vir_w;//wimo_info.dst_width;//wimo_info.yaff;//wimo_info.dst_width;//dst_width;
+ overlay_req.flag = IPP_ROT_0;
+
+
+ dmac_flush_range(enc_buff->ui_buffer_map,enc_buff->ui_buffer_map + enc_buff->dst_height *enc_buff->dst_width * 3/2);//dst_width*dst_height*3/2);\r
+ err = ipp_blit_sync(&overlay_req);
+ //printk("mode 1 overlay_req.src0.w %d %d overlay_req.dst0.w %d %d overlay_req.src_vir_w %d %d overlay_req.src0.YrgbMst %x %x overlay_req.dst0.YrgbMst %x %x ui_buffer %x pixel%x %x %x %x\n",
+ // overlay_req.src0.w,overlay_req.src0.h,overlay_req.dst0.w,overlay_req.dst0.h,overlay_req.src_vir_w ,overlay_req.dst_vir_w,overlay_req.src0.YrgbMst,overlay_req.src0.CbrMst,
+ // overlay_req.dst0.YrgbMst,overlay_req.dst0.CbrMst,ui_buffer,ui_buffer_map[0],ui_buffer_map[1],ui_buffer_map[1024],ui_buffer_map[1025]);
+ if(err)
+ goto WIMO_IPP_ERROR;
+
+ //printk("err %d w h fmt time out %d %d %d %d",err,overlay_req.src0.w,overlay_req.src0.h,overlay_req.src0.fmt,overlay_req.timeout);
+ }
+ }
+
+ \r
+
+ return 0;
+WIMO_IPP_ERROR:
+ \r
+ return -1;
+}
+\r
+int wimo_video_prepare(struct fb_info *info,u32 yuv_phy[2])\r
+{\r
+ int ret = 0;\r
+ static int comin_time = 0;\r
+ if(wimo_count < 1)\r
+ return WIMO_COUNT_ZERO;\r
+ mutex_lock(&video_lock);\r
+ DLOG("before wimo prepare para wimo_count %d wimo.video_start_sign %d %d %d %x %x\n"\r
+ ,wimo_count,wimo.video_start_sign,wimo.start_sign,wimo.video_info.avail_frame,wimo.video_info.buffer_num,(long)&wimo.video_info.buffer_num);\r
+ if(wimo.video_start_sign && wimo.start_sign)\r
+ {\r
+ struct wimo_video_info *video_info = &wimo.video_info;\r
+ struct enc_buff_info *enc_buff = &video_info->enc_buff[video_info->work_index]; \r
+ //struct rk29fb_inf *inf = dev_get_drvdata(info->device);\r
+ struct rk_fb_inf *inf = dev_get_drvdata(info->device);
+ int ret;\r
+ if(comin_time == 1)\r
+ {\r
+ printk("ENCODER_BUFFER_FULL wimo.video_info.avail_frame %d wimo.video_info.buffer_num %d\n",wimo.video_info.avail_frame,wimo.video_info.buffer_num);\r
+ // ret = ENCODER_BUFFER_FULL;\r
+ // goto buffer_full;\r
+ }\r
+ comin_time++;\r
+ if((wimo.video_info.avail_frame>=wimo.video_info.buffer_num-1) )\r
+ {\r
+ DLOG("ENCODER_BUFFER_FULL wimo.video_info.avail_frame %d wimo.video_info.buffer_num %d\n",wimo.video_info.avail_frame,wimo.video_info.buffer_num);\r
+ ret = ENCODER_BUFFER_FULL;\r
+ goto buffer_full;\r
+ }\r
+ \r
+ if(inf->video_mode == 0)\r
+ {\r
+ do_gettimeofday(&wimo.video_info.Wimo_RGB_time);\r
+ rgb_time++;\r
+ }\r
+ else\r
+ { \r
+ printk("videomode = %d err \n",inf->video_mode);\r
+ }\r
+ \r
+ \r
+ wimo_prepare_para(info,video_info,enc_buff);\r
+ ret = wimo_prepare_buff(enc_buff);\r
+ if(ret == 0)\r
+ {\r
+ video_info->avail_frame++;\r
+ //wimo_info.avail_frame%=(wimo_info.buffer_num + 1);\r
+ video_info->work_index++;\r
+ video_info->work_index%= video_info->buffer_num;\r
+ DLOG("prepare video_info->avail_frame %d video_info->work_index %d video_info->avail_index %d\n",video_info->avail_frame,video_info->work_index,video_info->avail_index);\r
+ // if(((wimo_info.avail_index + wimo_info.avail_frame) % wimo_info.buffer_num)!=wimo_info.work_index)\r
+ // DLOG("wimo_prepare_buff 2 test_sign %d avail_index %d avail_frame %d work_index %d mode %d %d time %lld %lld bitperpixel %d src_width %d src_height %d dst_width %d dst_height %d dst_y %x dst_uv %x\n",\r
+ // wimo_info.test_sign,wimo_info.avail_index,wimo_info.avail_frame,wimo_info.work_index,enc_buff[wimo_info.avail_index].mode,enc_buff[1-wimo_info.avail_index].mode,\r
+ // wimo_info.enc_buff[wimo_info.avail_index].Frame_Time,\r
+ // wimo_info.enc_buff[1-wimo_info.avail_index].Frame_Time, \r
+ // enc_buff->bitperpixel,enc_buff->src_width,enc_buff->src_height,enc_buff->dst_width,enc_buff->dst_height\r
+ // ,overlay_req.dst0.YrgbMst,overlay_req.dst0.CbrMst);\r
+ }\r
+ else\r
+ {\r
+ DLOG("Wimo_IPP_ERROR err %d enc_buff.src0.w %x %x enc_buff %x enc_buff->mode %x format %x workindex %x xaff %x yaff %x xsize %x ysize %x yuv_num %d %x %x %x %x\n"\r
+ ,ret,enc_buff->src_width,enc_buff->src_height,(u32)enc_buff,enc_buff->mode,enc_buff->bitperpixel,video_info->work_index,\r
+ enc_buff->xaff,enc_buff->yaff,enc_buff->xsize,\r
+ enc_buff->ysize,yuv_time,enc_buff->ui_buffer_map[0],enc_buff->ui_buffer_map[1],enc_buff->ui_buffer_map[2],enc_buff->ui_buffer_map[3]);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ //DLOG("wimo_video not open\n");\r
+ ret = VIDEO_ENCODER_CLOSED;\r
+ }\r
+ mutex_unlock(&video_lock);\r
+ \r
+ return ret;\r
+buffer_full:\r
+ mutex_unlock(&video_lock);\r
+ return ret;\r
+}\r
+#endif
+\r
+\r
+static int wimo_open(struct inode *inode, struct file *file)\r
+{\r
+ int ret = 0;\r
+\r
+ DLOG("wimo_open current %u \n", current->pid);\r
+ \r
+ return ret;\r
+}\r
+\r
+static int wimo_mmap(struct file *file, struct vm_area_struct *vma)\r
+{\r
+ int ret = 0;\r
+ DLOG("wimo_mmap do nothing current->pid %u\n",current->pid);\r
+//error:\r
+ return ret;\r
+}\r
+\r
+static int wimo_release(struct inode *inode, struct file *file)\r
+{\r
+ DLOG("wimo_release do nothing current->pid %u\n",current->pid);\r
+\r
+\r
+ return 0;\r
+}\r
+\r
+static long wimo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\r
+{\r
+ long ret = 0;\r
+// DLOG("wimo_ioctl cmd %d \n",cmd);\r
+ switch (cmd) {\r
+ case WIMO_START: \r
+ {\r
+ {\r
+ \r
+ mutex_lock(&wimo_lock);\r
+ wimo_start();\r
+ mutex_unlock(&wimo_lock);\r
+ printk("wimo_ioctl WIMO_START wimo.start_sign %d\n",wimo.start_sign);\r
+ }\r
+ }\r
+ break;\r
+ case WIMO_STOP:\r
+ {\r
+ {\r
+ mutex_lock(&wimo_lock);\r
+ wimo_stop();\r
+ mutex_unlock(&wimo_lock);\r
+ printk("wimo_ioctl WIMO_STOP wimo.start_sign %d\n",wimo.start_sign);\r
+ }\r
+ {\r
+ \r
+ }\r
+ }\r
+ break;\r
+ case WIMO_SET_ROTATION: \r
+ break;\r
+ case WIMO_VIDEO_OPEN: \r
+ \r
+ {\r
+ unsigned long temp[6];\r
+ \r
+ if (copy_from_user(temp, (void*)arg, 24))\r
+ return -EFAULT;\r
+ mutex_lock(&video_lock);\r
+ ret = wimo_video_open(temp);\r
+ mutex_unlock(&video_lock);\r
+ }\r
+ \r
+ break;\r
+ case WIMO_VIDEO_CLOSE: \r
+ \r
+ {\r
+ mutex_lock(&video_lock);\r
+ ret = wimo_video_close(&wimo.video_info);\r
+ mutex_unlock(&video_lock);\r
+ }\r
+ \r
+ break;\r
+ case WIMO_VIDEO_GET_BUF: \r
+ \r
+ {\r
+ \r
+ unsigned long temp_data[8];\r
+ mutex_lock(&video_lock);\r
+ \r
+ if(wimo.video_start_sign == 1 && wimo.start_sign == 1 && wimo.video_info.buffer_num)\r
+ {\r
+ \r
+ ret = wimo_video_find_frame(temp_data,&wimo.video_info);\r
+ if(ret == 0)\r
+ {\r
+ yuv_time = rgb_time = 0;\r
+ }\r
+ } \r
+ else\r
+ {\r
+ ret = -1111;\r
+ DLOG("WIMO_VIDEO_GET_BUF starg_sign %d start_video_sign %d",wimo.start_sign,wimo.video_start_sign);\r
+ }\r
+ mutex_unlock(&video_lock);\r
+ if (copy_to_user((void*)arg, temp_data, 28))\r
+ return -EFAULT;\r
+ }\r
+ \r
+ break;\r
+ \r
+ case WIMO_AUDIO_OPEN: \r
+ \r
+ {\r
+ unsigned long temp[6];\r
+ struct wimo_audio_info *audio_info = &wimo.audio_info;\r
+ if (copy_from_user(temp, (void*)arg, 24))\r
+ return -EFAULT;\r
+ mutex_lock(&audio_lock);\r
+ ret = wimo_audio_open(temp);\r
+ mutex_unlock(&audio_lock);\r
+ printk(" wimo_audio_open ret %daudio_info->Out_Buffer %x temp[0] %x audio_info->audio_data %x audio_info->time_stamp %x len = 3",\r
+ ret,(unsigned long)audio_info->Out_Buffer ,(unsigned long)(temp[0]),audio_info->audio_data,audio_info->time_stamp );\r
+ }\r
+ \r
+ break;\r
+ case WIMO_AUDIO_CLOSE: \r
+ \r
+ {\r
+ printk("WIMO_AUDIO_CLOSE\n");\r
+ mutex_lock(&audio_lock);\r
+ ret = wimo_audio_close();\r
+ mutex_unlock(&audio_lock);\r
+ }\r
+ \r
+ break;\r
+ case WIMO_AUDIO_SET_PARA: \r
+ \r
+ {\r
+ struct wimo_audio_param temp_data;\r
+ if (copy_from_user((void*)(&temp_data), (void*)arg, sizeof(struct wimo_audio_param)))\r
+ return -EFAULT;\r
+ mutex_lock(&audio_lock);\r
+ wimo_audio_set_para(&temp_data);\r
+ mutex_unlock(&audio_lock);\r
+ }\r
+ \r
+ break;\r
+ case WIMO_AUDIO_SET_VOL: \r
+ \r
+ {\r
+ unsigned long temp_data;\r
+ \r
+ if (copy_from_user(&temp_data, (void*)arg, 4))\r
+ return -EFAULT;\r
+ //printk("WIMO_AUDIO_SET_VOL set vol %d\n",temp_data);\r
+ mutex_lock(&audio_lock);\r
+ wimo.volumn_open_sign = temp_data;\r
+ mutex_unlock(&audio_lock);\r
+ }\r
+ \r
+ break; \r
+ case WIMO_AUDIO_GET_VOL:\r
+ {\r
+ //printk("WIMO_AUDIO_SET_VOL get vol %d\n",wimo.volumn_open_sign); \r
+ if(copy_to_user((void*)arg,&wimo.volumn_open_sign,4))\r
+ return -EFAULT;\r
+ }\r
+ break;\r
+ case WIMO_AUDIO_GET_BUF: \r
+ \r
+ {\r
+ struct wimo_audio_info *audio_info = &wimo.audio_info;\r
+ mutex_lock(&audio_lock); \r
+ if(wimo.audio_start_sign == 1 && wimo.start_sign == 1 && wimo.audio_info.buffer_size)\r
+ {\r
+ if(audio_info->data_len >= 1)\r
+ {\r
+ struct timeval timeFirst;\r
+ do_gettimeofday(&timeFirst); \r
+ audio_info->Out_Buffer = (void*)(&audio_info->audio_data[audio_info->head_offset * audio_info->nBytePerFrame]);\r
+ \r
+ \r
+ wimo_filp_output->f_op->write(wimo_filp_output, audio_info->Out_Buffer, audio_info->nBytePerFrame, &wimo_filp_output->f_pos);\r
+ if (copy_to_user((void*)arg,audio_info->Out_Buffer, 4096))\r
+ ret = -EFAULT;\r
+ if (copy_to_user((void*)arg+4096,(void*)(&audio_info->time_stamp[audio_info->head_offset]), 8))\r
+ ret = -EFAULT;\r
+ if (copy_to_user((void*)arg+4104,&timeFirst, 8))\r
+ ret = -EFAULT;\r
+ if (copy_to_user((void*)arg+4112,&audio_info->head_offset, 8))\r
+ ret = -EFAULT;\r
+ audio_info->data_len --;\r
+ audio_info->head_offset ++;\r
+ audio_info->head_offset %= audio_info->buffer_size;\r
+ }\r
+ else\r
+ {\r
+ ret = -1;\r
+ }\r
+ } \r
+ else\r
+ {\r
+ ret = -1111;\r
+ }\r
+ \r
+ mutex_unlock(&audio_lock);\r
+ }\r
+ \r
+ break;\r
+ default:\r
+ return -EINVAL;\r
+ }\r
+ return ret;\r
+}\r
+\r
+struct file_operations wimo_fops = {\r
+ .open = wimo_open,\r
+ .mmap = wimo_mmap,\r
+ .unlocked_ioctl = wimo_ioctl,\r
+ .release = wimo_release,\r
+};\r
+\r
+#if WIMO_DEBUG\r
+static ssize_t debug_open(struct inode *inode, struct file *file)\r
+{\r
+ file->private_data = inode->i_private;\r
+ return 0;\r
+}\r
+\r
+static ssize_t debug_read(struct file *file, char __user *buf, size_t count,\r
+ loff_t *ppos)\r
+{\r
+ wdm_region *region, *tmp_region;\r
+ const int debug_bufmax = 4096;\r
+ static char buffer[4096];\r
+ int n = 0;\r
+\r
+ DLOG("debug open\n");\r
+ n = scnprintf(buffer, debug_bufmax,\r
+ "pid #: mapped regions (offset, len, used, post) ...\n");\r
+ down_read(&wdm_rwsem);\r
+ {\r
+ n += scnprintf(buffer + n, debug_bufmax - n,\r
+ "(%d,%d,%d,%d) ",\r
+ region->index, region->pfn, region->used, region->post);\r
+ }\r
+ up_read(&wdm_rwsem);\r
+ n++;\r
+ buffer[n] = 0;\r
+ return simple_read_from_buffer(buf, count, ppos, buffer, n);\r
+}\r
+\r
+static struct file_operations debug_fops = {\r
+ .read = debug_read,\r
+ .open = debug_open,\r
+};\r
+#endif\r
+\r
+int wimo_setup(struct wimo_platform_data *pdata)\r
+{\r
+ int err = 0;\r
+ DLOG("wimo_setup pdata->name %s\n",pdata->name);\r
+ if (wimo_count) {\r
+ printk(KERN_ALERT "Only one wimo driver can be register!\n");\r
+ goto err_cant_register_device;\r
+ }\r
+\r
+ memset(&wimo, 0, sizeof(struct wimo_info));\r
+\r
+ wimo.rotation_flag = IPP_ROT_0; \r
+\r
+ init_rwsem(&wdm_rwsem);\r
+ wimo.dev.name = pdata->name;\r
+ wimo.dev.minor = MISC_DYNAMIC_MINOR;\r
+ wimo.dev.fops = &wimo_fops;\r
+ \r
+ err = misc_register(&wimo.dev);\r
+ if (err) {\r
+ printk(KERN_ALERT "Unable to register wimo driver!\n");\r
+ goto err_cant_register_device;\r
+ }\r
+ mutex_init(&video_lock); \r
+ mutex_init(&audio_lock); \r
+ mutex_init(&wimo_lock);\r
+ audio_data_to_wimo = wimo_audio_prepare;\r
+ video_data_to_wimo = wimo_video_prepare;\r
+ printk("set audio_data_to_wimo %x %x\n",(unsigned long)wimo_audio_prepare,(unsigned long)audio_data_to_wimo);\r
+ #if WIMO_DEBUG\r
+ debugfs_create_file(pdata->name, S_IFREG | S_IRUGO, NULL, (void *)wimo.dev.minor,\r
+ &debug_fops);\r
+ #endif\r
+ printk("%s: %d initialized\n", pdata->name, wimo.dev.minor);\r
+ wimo_count++;\r
+ return 0;\r
+ \r
+//err_no_mem_for_metadata:\r
+ misc_deregister(&wimo.dev);\r
+err_cant_register_device:\r
+ return -1;\r
+}\r
+\r
+static int wimo_probe(struct platform_device *pdev)\r
+{\r
+ struct wimo_platform_data *pdata;\r
+ printk("wimo_probe\n");\r
+ if (!pdev || !pdev->dev.platform_data) {\r
+ printk(KERN_ALERT "Unable to probe wimo!\n");\r
+ return -1;\r
+ }\r
+ pdata = pdev->dev.platform_data;\r
+ return wimo_setup(pdata);\r
+}\r
+\r
+static int wimo_remove(struct platform_device *pdev)\r
+{\r
+ if (!pdev || !pdev->dev.platform_data) {\r
+ printk(KERN_ALERT "Unable to remove wimo!\n");\r
+ return -1;\r
+ }\r
+ mutex_destroy(&wimo_lock);\r
+ mutex_destroy(&audio_lock); \r
+ mutex_destroy(&video_lock); \r
+ if (wimo_count) {\r
+ misc_deregister(&wimo.dev);\r
+ wimo_count--;\r
+ } else {\r
+ printk(KERN_ALERT "no wimo to remove!\n");\r
+ }\r
+ return 0;\r
+}\r
+\r
+static struct platform_driver wimo_driver = {\r
+ .probe = wimo_probe,\r
+ .remove = wimo_remove,\r
+ .driver = {.name = "wimo"}\r
+ \r
+};\r
+\r
+\r
+static int __init wimo_init(void)\r
+{\r
+ printk("wimo_init\n");\r
+ return platform_driver_register(&wimo_driver);\r
+}\r
+\r
+static void __exit wimo_exit(void)\r
+{\r
+ platform_driver_unregister(&wimo_driver);\r
+}\r
+\r
+module_init(wimo_init);\r
+module_exit(wimo_exit);\r
+\r
+#if 0//def CONFIG_PROC_FS\r
+#include <linux/proc_fs.h>\r
+#include <linux/seq_file.h>\r
+\r
+static int proc_wimo_show(struct seq_file *s, void *v)\r
+{\r
+ if (wimo_count) {\r
+ seq_printf(s, "wimo opened\n");\r
+ } else {\r
+ seq_printf(s, "wimo closed\n");\r
+ return 0;\r
+ }\r
+\r
+ down_read(&wdm_rwsem);\r
+ {\r
+ }\r
+\r
+ up_read(&wdm_rwsem);\r
+ return 0;\r
+}\r
+\r
+static int proc_wimo_open(struct inode *inode, struct file *file)\r
+{\r
+ return single_open(file, proc_wimo_show, NULL);\r
+}\r
+\r
+static const struct file_operations proc_wimo_fops = {\r
+ .open = proc_wimo_open,\r
+ .read = seq_read,\r
+ .llseek = seq_lseek,\r
+ .release = single_release,\r
+};\r
+\r
+static int __init wimo_proc_init(void)\r
+{\r
+ proc_create("wimo", 0, NULL, &proc_wimo_fops);\r
+ return 0;\r
+\r
+}\r
+late_initcall(wimo_proc_init);\r
+#endif /* CONFIG_PROC_FS */\r
+\r