1 /* drivers/video/wimo.c
\r
3 * Copyright (C) 2010 ROCKCHIP, Inc.
\r
4 * author: chenhengming chm@rock-chips.com
\r
6 * This software is licensed under the terms of the GNU General Public
\r
7 * License version 2, as published by the Free Software Foundation, and
\r
8 * may be copied, distributed, and modified under those terms.
\r
10 * This program is distributed in the hope that it will be useful,
\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 * GNU General Public License for more details.
\r
16 #include <linux/miscdevice.h>
17 #include <linux/platform_device.h>
19 #include <linux/file.h>
21 #include <linux/list.h>
22 #include <linux/debugfs.h>
23 #include <linux/mempolicy.h>
24 #include <linux/sched.h>
\r
26 #include <asm/uaccess.h>
\r
27 #include <asm/cacheflush.h>
\r
28 #include <linux/fb.h>
\r
29 #include <plat/ipp.h>
\r
30 #include "linux/wimo.h"
\r
31 #include<linux/rk_fb.h>
\r
32 #define WIMO_MIN_ALLOC PAGE_SIZE
\r
33 #define WIMO_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
\r
35 #define WIMO_DEBUG 0
\r
36 #define WIMO_DEBUG_MSGS 0
\r
39 #define DLOG(fmt,args...) \
\r
40 do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
\r
44 #define DLOG(x...) do {} while (0)
\r
46 #define WIMO_WRITE_FILE
49 volatile u32 y_offset;
50 volatile u32 c_offset;
58 u32 xpos; //size in panel
60 u32 xsize; //start point in panel
64 wait_queue_head_t wait;
65 struct win_set mirror;
75 * struct for global wimo info
\r
77 struct enc_buff_info{
\r
97 unsigned char* ui_buffer;
98 unsigned char* ui_buffer_map;
103 struct wimo_video_info{
\r
117 u32 rot_dst_height;
\r
121 int Last_rotation_flag;
\r
123 long long Last_Frame_Time;
124 struct timeval Wimo_RGB_time;
125 struct timeval Wimo_YUV_time;
126 struct timeval Wimo_Cur_time;
127 struct enc_buff_info enc_buff[4];
131 volatile u32 avail_frame;
\r
136 struct wimo_audio_info{
\r
137 volatile u32 buffer_size;
\r
138 volatile u32 head_offset;
\r
139 volatile u32 tail_offset;
\r
140 volatile u32 data_len;
\r
141 u32 nSamplePerFrame;
\r
143 u32 nBytePerSample;
\r
145 unsigned char* Out_Buffer;
\r
146 struct timeval *time_stamp;
\r
147 unsigned char *audio_data;
\r
150 struct wimo_audio_param{
\r
152 u32 nSamplePerFrame;
\r
154 u32 nBytePerSample;
\r
161 struct wimo_video_info video_info;
\r
162 struct wimo_audio_info audio_info;
\r
163 struct rw_semaphore rw_sem;
\r
164 struct miscdevice dev;
\r
165 int video_start_sign;
\r
166 int audio_start_sign;
\r
168 int volumn_open_sign;
\r
171 struct mutex video_lock;
\r
172 struct mutex audio_lock;
\r
173 struct mutex wimo_lock;
\r
174 //int wimo_prepare_para(struct fb_info *info);
\r
175 //int wimo_prepare_buff(struct fb_info *info);
\r
176 //int wimo_prepare(struct fb_info *info);
\r
179 static int wimo_count = 0;
\r
180 static struct wimo_info wimo;
\r
181 #define wdm_rwsem (wimo.rw_sem)
\r
182 extern int (*audio_data_to_wimo)(void* data,int size,int channel);
\r
183 extern int (*video_data_to_wimo)(struct fb_info *info,u32 yuv_phy[2]);
\r
185 unsigned long temp_vv;
\r
186 static int frame_num = 0;
\r
187 static int Is_Wimo_Loaded()
\r
194 static int wimo_start(void)
\r
197 wimo.start_sign = 1;
\r
201 static int wimo_stop(void)
\r
205 wimo.start_sign = 0;
\r
208 static int wimo_set_rotation(int rotation_flag)
\r
212 wimo.rotation_flag = rotation_flag;
\r
215 struct file* wimo_filp;
\r
216 mm_segment_t old_fs;
\r
217 struct file* wimo_filp_output;
\r
218 mm_segment_t old_fs_output;
\r
219 static int wimo_audio_open(unsigned long *temp)
\r
222 struct wimo_audio_info *audio_info = &wimo.audio_info;
\r
223 struct timeval timeFirst;
\r
224 do_gettimeofday(&timeFirst);
\r
225 if(wimo.start_sign == 0)
\r
227 printk("Apk didn't start when audio start \n");
\r
230 memset(audio_info, 0, sizeof(struct wimo_audio_info));
\r
231 wimo.audio_start_sign = 1;
\r
232 audio_info->Out_Buffer = NULL;
\r
234 audio_info->buffer_size = 50;
\r
235 audio_info->nSamplePerFrame = 1024;
\r
236 audio_info->nBytePerSample = 2;
\r
237 audio_info->nChannel = 2;
\r
238 audio_info->nBytePerFrame = 4096;
\r
241 audio_info->head_offset = 0;
\r
242 audio_info->tail_offset = 0;
\r
243 audio_info->data_len = 0;
\r
245 audio_info->audio_data = (unsigned char*)kmalloc(audio_info->buffer_size * audio_info->nBytePerFrame,GFP_KERNEL);
\r
246 audio_info->time_stamp = (struct timeval*)kmalloc(audio_info->buffer_size * sizeof(struct timeval),GFP_KERNEL);
\r
247 memset(audio_info->audio_data, 0,audio_info->buffer_size * audio_info->nBytePerFrame);
\r
248 printk("audio_info->buffer_size * audio_info->nBytePerFrame timestamp %d audio_info->Out_Buffer %x time %lld %x %x\n",
\r
249 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
250 ,__pa(audio_info->audio_data),__pa(audio_info->time_stamp));
\r
251 #ifdef WIMO_WRITE_FILE
\r
253 wimo_filp = filp_open("/data/test/input_cmp.pcm",O_CREAT|O_TRUNC|O_RDWR,0);
\r
259 wimo_filp_output = NULL;
\r
260 wimo_filp_output = filp_open("/data/test/output_cmp.pcm",O_CREAT|O_TRUNC|O_RDWR,0);
\r
261 if (wimo_filp_output)
\r
263 old_fs_output = get_fs();
\r
269 static int wimo_audio_close(void)
\r
272 struct wimo_audio_info *audio_info = &wimo.audio_info;
\r
273 #ifdef WIMO_WRITE_FILE
\r
275 filp_close(wimo_filp,NULL);
\r
277 set_fs(old_fs_output);
\r
278 filp_close(wimo_filp_output,NULL);
\r
281 printk("wimo_audio_close\n");
\r
282 kfree((void *)audio_info->time_stamp);
\r
283 kfree((void *)audio_info->audio_data);
\r
285 audio_info->Out_Buffer = NULL;
\r
286 wimo.audio_start_sign = 0;
\r
289 static void wimo_audio_set_para(struct wimo_audio_param *param)
\r
291 struct wimo_audio_info *audio_info = &wimo.audio_info;
\r
292 audio_info->buffer_size = param->buffer_size;
\r
293 audio_info->nSamplePerFrame = param->nSamplePerFrame;
\r
294 audio_info->nChannel = param->nChannel;
\r
295 audio_info->nBytePerSample = param->nBytePerSample;
\r
296 audio_info->nBytePerFrame = param->nBytePerFrame;
\r
297 DLOG("param %d %d %d %d %d audio_info %d %d %d %d %d",
\r
298 param->buffer_size,param->nSamplePerFrame,param->nChannel,param->nBytePerSample,param->nBytePerFrame,
\r
299 audio_info->buffer_size,audio_info->nSamplePerFrame,audio_info->nChannel,audio_info->nBytePerSample,audio_info->nBytePerFrame);
\r
303 static void wimo_audio_set_vol(u32 temp_data)
\r
305 wimo.volumn_open_sign = temp_data;
\r
308 static int wimo_audio_find_frame()
\r
310 struct wimo_audio_info *audio_info = &wimo.audio_info;
\r
312 if(audio_info->data_len >= 1)
\r
314 audio_info->Out_Buffer = (void*)(&audio_info->audio_data[audio_info->head_offset * audio_info->nBytePerFrame]);
\r
315 //wimo_filp_output->f_op->write(wimo_filp_output, audio_info->Out_Buffer, audio_info->nBytePerFrame, &wimo_filp_output->f_pos);
\r
316 audio_info->data_len --;
\r
317 audio_info->head_offset ++;
\r
318 audio_info->head_offset %= audio_info->buffer_size;
\r
327 static int wimo_audio_prepare(void* data,int size,int channel)
\r
330 mutex_lock(&audio_lock);
\r
332 if(wimo.audio_start_sign && wimo.start_sign)
\r
334 struct timeval timeFirst;
\r
335 unsigned long* temp = (unsigned long*)data;
\r
336 struct wimo_audio_info *audio_info = &wimo.audio_info;
\r
337 unsigned char* buf = data;
\r
338 do_gettimeofday(&timeFirst);
\r
339 memcpy((void*)(&audio_info->audio_data[audio_info->tail_offset * audio_info->nBytePerFrame]), (void*)data,size);
\r
340 memcpy((void*)(&audio_info->time_stamp[audio_info->tail_offset]),(void*)(&timeFirst),sizeof(struct timeval));
\r
341 audio_info->tail_offset ++;
\r
342 audio_info->tail_offset %= audio_info->buffer_size;
\r
343 wimo_filp->f_op->write(wimo_filp, data, size, &wimo_filp->f_pos);
\r
344 if(audio_info->data_len + 1 < audio_info->buffer_size)
\r
346 audio_info->data_len ++;
\r
350 audio_info->head_offset=audio_info->tail_offset;
\r
351 audio_info->data_len = audio_info->buffer_size;
\r
353 // if(wimo.volumn_open_sign==0)
\r
355 // memset((void*)data,0,size);
\r
361 //DLOG("wimo_video not open\n");
\r
362 ret = AUDIO_ENCODER_CLOSED;
\r
364 if(wimo.start_sign && wimo.volumn_open_sign == 0)
\r
365 memset((void*)data,0,size);
\r
367 mutex_unlock(&audio_lock);
\r
371 wimo_video can be opened once at a time.
\r
372 Other user must wait for last open closed.
\r
374 static int wimo_video_open(unsigned long *temp)
\r
376 struct wimo_video_info *video_info = &wimo.video_info;
\r
379 printk("wimo_video_open\n");
\r
380 if(wimo.start_sign == 0)
\r
382 printk("Apk didn't start when video start ");
\r
385 if(wimo.video_start_sign == 1)
\r
387 printk("last wimo_video still opened ,something wrong\n");
\r
390 memset(&wimo.video_info,0,sizeof(struct wimo_video_info));
\r
391 if(wimo.rotation_flag < 0 )
\r
392 DLOG("wimo_set_buff rotation_flag < 0,maybe something wrong\n");
\r
394 video_info->Last_rotation_flag = -1;
\r
395 video_info->rotation_flag = wimo.rotation_flag;
\r
396 for(i = 0; i < temp[3]; i++)
\r
398 video_info->enc_buff[i].ui_buffer= (unsigned char*)temp[i+4];
\r
399 video_info->enc_buff[i].ui_buffer_map= ioremap(temp[i+4],temp[2]);
\r
400 if(video_info->enc_buff[i].ui_buffer_map == NULL)
\r
402 printk("can't map a buffer for ui\n");
406 video_info->buffer_num = temp[3];
\r
407 video_info->dst_width = (temp[0] + 15) & 0xfff0;
\r
408 video_info->dst_height = (temp[1] + 15) & 0xfff0;
\r
409 video_info->xsize = video_info->dst_width;
\r
410 video_info->ysize = video_info->dst_height;
\r
411 wimo.video_start_sign = 1;
\r
412 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
413 video_info->dst_width,video_info->dst_height,video_info->buffer_num,(long)&wimo.video_info.buffer_num,
\r
414 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
415 ,video_info->enc_buff[1].ui_buffer_map);
\r
416 rgb_time = yuv_time = 0;
\r
424 static int wimo_video_close(struct wimo_video_info *video_info)
\r
428 if(video_info->buffer_num && wimo.video_start_sign && wimo.start_sign)
\r
429 printk("something is okay with wimo video in close");
\r
432 printk("somethint wrong with wimo video in close");
\r
433 wimo.video_start_sign = 0;
\r
434 DLOG("video_info->dst_width %d video_info->dst_height %d ui_buffer %x %x ui_buffer_map %x %x\n",
\r
435 video_info->dst_width,video_info->dst_height,video_info->enc_buff[0].ui_buffer,video_info->enc_buff[1].ui_buffer,
\r
436 video_info->enc_buff[0].ui_buffer_map,video_info->enc_buff[1].ui_buffer_map);
\r
438 for(i = 0; i < 4; i++)
440 DLOG("closebuf ui_buffer %x ui_buffer_map %x ui_buffer_map addr %x wimo_info.buffer_num %d i %d\n",
\r
441 (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
442 if(video_info->enc_buff[i].ui_buffer_map!=0)
\r
444 iounmap(video_info->enc_buff[i].ui_buffer_map);
\r
445 video_info->enc_buff[i].ui_buffer_map = 0;
\r
446 video_info->enc_buff[i].ui_buffer = 0;
\r
454 it return -1 when no frame is availiable
\r
456 static int wimo_video_find_frame(unsigned long* temp_data,struct wimo_video_info *video_info)
\r
460 do_gettimeofday(&video_info->Wimo_Cur_time);
\r
461 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
462 (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
463 (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
464 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
465 ,(long long)video_info->Wimo_RGB_time.tv_sec * 1000000ll + video_info->Wimo_RGB_time.tv_usec,yuv_time);
\r
466 if(video_info->avail_frame)
\r
468 if(video_info->Last_Frame_Time > video_info->enc_buff[video_info->avail_index].Frame_Time)
\r
471 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
472 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
473 (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
474 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
475 ,(long long)video_info->Wimo_RGB_time.tv_sec * 1000000ll + video_info->Wimo_RGB_time.tv_usec,yuv_time);
\r
476 video_info->test_sign = 2;
\r
478 video_info->Last_Frame_Time = video_info->enc_buff[video_info->avail_index].Frame_Time;
\r
483 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
486 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
487 video_info->avail_index,video_info->avail_frame,video_info->work_index,
\r
488 video_info->test_sign,video_info->enc_buff[video_info->avail_index].Frame_Time,
\r
489 (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
490 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
491 ,(long long)video_info->Wimo_RGB_time.tv_sec * 1000000ll + video_info->Wimo_RGB_time.tv_usec,yuv_time);
\r
492 video_info->test_sign = 3;
\r
493 video_info->Last_Frame_Time =(long long)video_info->Wimo_Cur_time.tv_sec * 1000000ll + video_info->Wimo_Cur_time.tv_usec;
\r
494 if(video_info->mode == 0 )
\r
496 video_info->Wimo_RGB_time.tv_sec = video_info->Wimo_Cur_time.tv_sec;
\r
497 video_info->Wimo_RGB_time.tv_usec = video_info->Wimo_Cur_time.tv_usec;
\r
500 video_info->avail_index--;
\r
501 video_info->avail_index %= video_info->buffer_num;
\r
502 video_info->avail_frame++;
\r
507 video_info->test_sign = 4;
\r
508 DLOG ("no avail frame \n");
\r
513 temp_data[0] = (video_info->enc_buff[video_info->avail_index].bitperpixel << 16);
\r
514 temp_data[0] |= video_info->enc_buff[video_info->avail_index].mode;
\r
516 temp_data[1] = video_info->avail_index ;
\r
517 memcpy(&temp_data[2],&video_info->enc_buff[video_info->avail_index].Frame_Time,8);
\r
518 temp_data[4] = video_info->enc_buff[video_info->avail_index].rotation_flag| (yuv_time<<16);
\r
519 temp_data[5] = video_info->Wimo_Cur_time.tv_sec;
\r
520 temp_data[6] = video_info->Wimo_Cur_time.tv_usec;
\r
522 video_info->avail_index++;
\r
523 video_info->avail_index %= video_info->buffer_num;
\r
524 video_info->avail_frame--;
\r
525 video_info->frame_num++;
\r
526 yuv_time = rgb_time = 0;
532 int wimo_prepare_para(struct fb_info *info,struct wimo_video_info *video_info,struct enc_buff_info *enc_buff)
\r
535 //struct rk29fb_inf *inf = dev_get_drvdata(info->device);
\r
536 struct rk_fb_inf *inf = dev_get_drvdata(info->device);
537 struct fb_var_screeninfo *var = &info->var;
\r
539 struct layer_par *par = NULL;
\r
540 struct fb_fix_screeninfo * fix = &info->fix;
\r
541 struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver *)info->par;
\r
543 layer_id = get_fb_layer_id(fix);
\r
550 par = dev_drv->layer_par[layer_id];
\r
552 video_info->mode = inf->video_mode;
\r
553 video_info->src_width = var->xres_virtual;
\r
554 video_info->src_height = var->yres_virtual/2;
\r
555 if(inf->video_mode == 0 )
561 enc_buff->bitperpixel = 16;
562 enc_buff->rotation_flag = video_info->rotation_flag;
\r
566 enc_buff->bitperpixel =32;// wimo_info.bitperpixel_fb1;
567 enc_buff->rotation_flag = video_info->rotation_flag + 8;
\r
569 enc_buff->dst_width = video_info->dst_width;
\r
570 enc_buff->dst_height = video_info->dst_height;
\r
574 enc_buff->src_width = video_info->src_width;
\r
575 enc_buff->src_height = video_info->src_height;
\r
578 enc_buff->dst_vir_w = video_info->dst_width;
\r
579 enc_buff->dst_vir_h = video_info->dst_height;
\r
580 enc_buff->y_offset = enc_buff->c_offset = 0;
583 enc_buff->src_y = info->fix.smem_start + par->y_offset;//info->screen_base + par->y_offset;//info_buffer[8];
584 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
585 enc_buff->Frame_Time = (long long)video_info->Wimo_RGB_time.tv_sec * 1000000ll + video_info->Wimo_RGB_time.tv_usec;
\r
587 if(0)//rotation_sign == IPP_ROT_90 || rotation_sign == IPP_ROT_270)
589 if(enc_buff->dst_vir_w > enc_buff->dst_vir_h)
591 enc_buff->dst_height = enc_buff->dst_vir_h;
592 enc_buff->dst_width = ((enc_buff->dst_vir_h * enc_buff->dst_vir_h) / enc_buff->dst_vir_w) & 0xfffc;
594 enc_buff->c_offset = enc_buff->y_offset = ((enc_buff->dst_vir_w - enc_buff->dst_width ) ) & 0xfffc;
597 enc_buff->c_offset = enc_buff->y_offset = ((enc_buff->dst_vir_w - enc_buff->dst_width ) *2) & 0xfffc;
602 enc_buff->dst_width = enc_buff->dst_vir_w;
603 enc_buff->dst_height = ((enc_buff->dst_vir_w * enc_buff->dst_vir_w) / enc_buff->dst_vir_h) ;
604 enc_buff->y_offset = (enc_buff->dst_vir_h - enc_buff->dst_height ) * enc_buff->dst_vir_w * 2;
605 enc_buff->c_offset = (enc_buff->dst_vir_h - enc_buff->dst_height ) * enc_buff->dst_vir_w ; ;
608 // 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,
609 // enc_buff->c_offset,rotation_sign);
610 // 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
611 // ,enc_buff->mode,enc_buff->bitperpixel,par->format);
614 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
615 ,video_info->Last_rotation_flag , enc_buff->rotation_flag,
\r
616 video_info->enc_buff[0].ui_buffer_map,video_info->enc_buff[1].ui_buffer_map);
\r
617 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
620 if(enc_buff->rotation_flag & 0x8)
\r
622 for(i = 0; i < video_info->buffer_num; i++)
\r
624 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
627 else if((enc_buff->rotation_flag & 0x8 )== 0)
\r
629 for(i = 0; i < video_info->buffer_num; i++)
\r
631 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
634 // memset(ui_buffer_map,0,enc_buff->dst_vir_w * enc_buff->dst_vir_h * 4);//dst_width*dst_height);
635 //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);
636 // printk("rotation change wimo_info.Last_rotation_flag %d enc_buff->rotation_sign %d\n",wimo_info.Last_rotation_flag,enc_buff->rotation_sign);
638 video_info->Last_rotation_flag = enc_buff->rotation_flag;
\r
642 int wimo_prepare_buff(struct enc_buff_info *enc_buff)
\r
645 struct rk29_ipp_req overlay_req;
646 struct rk29_ipp_req overlay_req_1;
649 memset(&overlay_req, 0 , sizeof(overlay_req));
650 memset(&overlay_req_1, 0 , sizeof(overlay_req_1));
651 //printk("inf->video_mode %d\n",inf->video_mode);
652 if(enc_buff->mode == 0 )
655 overlay_req.src0.YrgbMst = enc_buff->src_y;//info->fix.smem_start + par->y_offset;//info->screen_base + par->y_offset;//info_buffer[8];
656 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];
657 overlay_req.src0.w = enc_buff->src_width ;//dst_width;//info_buffer[2];
658 overlay_req.src0.h = enc_buff->src_height ;//dst_height;//info_buffer[3];
659 overlay_req.src0.fmt = (enc_buff->bitperpixel == 16) ? 1 : 0;//3;
660 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
661 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
663 overlay_req.dst0.w = enc_buff->dst_width ;//dst_width;//info_buffer[6];
664 overlay_req.dst0.h = enc_buff->dst_height ;//dst_height;//info_buffer[7];
665 overlay_req.dst0.fmt = (enc_buff->bitperpixel== 16) ? 1 : 0;//3;3;
666 overlay_req.deinterlace_enable = 0;
667 overlay_req.timeout = 1000000;
668 overlay_req.src_vir_w = enc_buff->src_width ;//dst_width;//info_buffer[2];
669 overlay_req.dst_vir_w = enc_buff->dst_vir_w ;//dst_width;
672 //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);
673 overlay_req.flag = enc_buff->rotation_flag & 0x7;
\r
674 err = ipp_blit_sync(&overlay_req);
\r
677 //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);
678 // 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);
689 if(enc_buff->xaff * 3 < enc_buff->xsize || enc_buff->yaff * 3 < enc_buff->ysize)// 3time or bigger scale up
\r
691 unsigned long mid_width, mid_height;
692 struct rk29_ipp_req overlay_req_1;
693 if(enc_buff->xaff * 3 < enc_buff->xsize)
694 mid_width = enc_buff->xaff * 3;
696 mid_width = enc_buff->xsize;
698 if(enc_buff->yaff * 3 < enc_buff->ysize)
699 mid_height = enc_buff->yaff * 3;
701 mid_height = enc_buff->ysize;
702 overlay_req.src0.YrgbMst = enc_buff->src_y;//info_buffer[8];
703 overlay_req.src0.CbrMst = enc_buff->src_uv;//info_buffer[9];
704 overlay_req.src0.w = enc_buff->xaff;// info_buffer[2];
705 overlay_req.src0.h = enc_buff->yaff;// info_buffer[3];
706 overlay_req.src0.fmt = 3;
707 overlay_req.dst0.YrgbMst = (unsigned long)(enc_buff->ui_buffer + 2048000) ;//info_buffer[4] + info_buffer[5] * dst_width; //С³ß´çƬԴÐèÒª2´Î·Å´ó£¬ËùÒÔ½«bufferµÄºó°ë¶ÎÓÃÓÚ»º´æ
\r
708 overlay_req.dst0.CbrMst = (unsigned long)( (unsigned char*) enc_buff->ui_buffer + mid_height * mid_width + 2048000);
\r
710 overlay_req.dst0.w = mid_width;//info_buffer[6];
711 overlay_req.dst0.h = mid_height;//info_buffer[7];
712 overlay_req.dst0.fmt = 3;
713 overlay_req.timeout = 100000;
714 overlay_req.src_vir_w = enc_buff->xaff;//info_buffer[2];
715 overlay_req.dst_vir_w = mid_width;//dst_width;
716 overlay_req.flag = IPP_ROT_0;
721 overlay_req_1.src0.YrgbMst = (unsigned long)(enc_buff->ui_buffer + 2048000);
\r
722 overlay_req_1.src0.CbrMst = (unsigned long)((unsigned char*) enc_buff->ui_buffer + mid_height * mid_width + 2048000);
\r
723 overlay_req_1.src0.w = mid_width;
724 overlay_req_1.src0.h = mid_height;// info_buffer[3];
725 overlay_req_1.src0.fmt = 3;
726 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
727 overlay_req_1.dst0.CbrMst = (unsigned long)((unsigned char*) enc_buff->ui_buffer + enc_buff->dst_width * enc_buff->dst_height +
\r
728 ((enc_buff->xpos + 1)&0xfffe) + ( enc_buff->ypos / 2)* enc_buff->dst_width) ;
\r
730 overlay_req_1.dst0.w = enc_buff->xsize;//info_buffer[6];
731 overlay_req_1.dst0.h = enc_buff->ysize;//info_buffer[7];
732 overlay_req_1.dst0.fmt = 3;
733 overlay_req_1.timeout = 100000;
734 overlay_req_1.src_vir_w = mid_width;//info_buffer[2];
735 overlay_req_1.dst_vir_w = enc_buff->dst_vir_w;//dst_width;
736 overlay_req_1.flag = IPP_ROT_0;
739 err = ipp_blit_sync(&overlay_req);
742 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
743 err = ipp_blit_sync(&overlay_req_1);
746 // printk("err1 %d w h fmt time out %d %d %d %d workindex %d encbuff %x xaff %d yaff %d xsize %d ysize %d",
747 // err,overlay_req.src0.w,overlay_req.src0.h,overlay_req.src0.fmt,overlay_req.timeout,wimo_info.work_index,(unsigned long)enc_buff
748 // ,enc_buff->xaff,enc_buff->yaff,enc_buff->xsize,enc_buff->ysize);
752 overlay_req.src0.YrgbMst = enc_buff->src_y;//info_buffer[8];
753 overlay_req.src0.CbrMst = enc_buff->src_uv;//info_buffer[9];
754 overlay_req.src0.w = enc_buff->xaff;// info_buffer[2];
755 overlay_req.src0.h = enc_buff->yaff;// info_buffer[3];
756 overlay_req.src0.fmt = 3;
757 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
758 overlay_req.dst0.CbrMst = (unsigned long)((unsigned char*) enc_buff->ui_buffer + ((enc_buff->xpos + 1)&0xfffe) +
\r
759 ( enc_buff->ypos / 2)* enc_buff->dst_width + enc_buff->dst_width * enc_buff->dst_height);
\r
761 overlay_req.dst0.w = enc_buff->xsize;//wimo_info.xsize;//wimo_info.xaff;// wimo_info.xsize;//info_buffer[6];
762 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];
763 overlay_req.dst0.fmt = 3;
764 overlay_req.timeout = 100000;
765 overlay_req.src_vir_w = (enc_buff->xaff + 15) & 0xfff0;//enc_buff->xaff;//info_buffer[2];
766 overlay_req.dst_vir_w = enc_buff->dst_vir_w;//wimo_info.dst_width;//wimo_info.yaff;//wimo_info.dst_width;//dst_width;
767 overlay_req.flag = IPP_ROT_0;
770 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
771 err = ipp_blit_sync(&overlay_req);
772 //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",
773 // 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,
774 // 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]);
778 //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);
790 int wimo_video_prepare(struct fb_info *info,u32 yuv_phy[2])
\r
793 static int comin_time = 0;
\r
795 return WIMO_COUNT_ZERO;
\r
796 mutex_lock(&video_lock);
\r
797 DLOG("before wimo prepare para wimo_count %d wimo.video_start_sign %d %d %d %x %x\n"
\r
798 ,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
799 if(wimo.video_start_sign && wimo.start_sign)
\r
801 struct wimo_video_info *video_info = &wimo.video_info;
\r
802 struct enc_buff_info *enc_buff = &video_info->enc_buff[video_info->work_index];
\r
803 //struct rk29fb_inf *inf = dev_get_drvdata(info->device);
\r
804 struct rk_fb_inf *inf = dev_get_drvdata(info->device);
806 if(comin_time == 1)
\r
808 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
809 // ret = ENCODER_BUFFER_FULL;
\r
810 // goto buffer_full;
\r
813 if((wimo.video_info.avail_frame>=wimo.video_info.buffer_num-1) )
\r
815 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
816 ret = ENCODER_BUFFER_FULL;
\r
820 if(inf->video_mode == 0)
\r
822 do_gettimeofday(&wimo.video_info.Wimo_RGB_time);
\r
827 printk("videomode = %d err \n",inf->video_mode);
\r
831 wimo_prepare_para(info,video_info,enc_buff);
\r
832 ret = wimo_prepare_buff(enc_buff);
\r
835 video_info->avail_frame++;
\r
836 //wimo_info.avail_frame%=(wimo_info.buffer_num + 1);
\r
837 video_info->work_index++;
\r
838 video_info->work_index%= video_info->buffer_num;
\r
839 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
840 // if(((wimo_info.avail_index + wimo_info.avail_frame) % wimo_info.buffer_num)!=wimo_info.work_index)
\r
841 // 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
842 // 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
843 // wimo_info.enc_buff[wimo_info.avail_index].Frame_Time,
\r
844 // wimo_info.enc_buff[1-wimo_info.avail_index].Frame_Time,
\r
845 // enc_buff->bitperpixel,enc_buff->src_width,enc_buff->src_height,enc_buff->dst_width,enc_buff->dst_height
\r
846 // ,overlay_req.dst0.YrgbMst,overlay_req.dst0.CbrMst);
\r
850 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
851 ,ret,enc_buff->src_width,enc_buff->src_height,(u32)enc_buff,enc_buff->mode,enc_buff->bitperpixel,video_info->work_index,
\r
852 enc_buff->xaff,enc_buff->yaff,enc_buff->xsize,
\r
853 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
858 //DLOG("wimo_video not open\n");
\r
859 ret = VIDEO_ENCODER_CLOSED;
\r
861 mutex_unlock(&video_lock);
\r
865 mutex_unlock(&video_lock);
\r
871 static int wimo_open(struct inode *inode, struct file *file)
\r
875 DLOG("wimo_open current %u \n", current->pid);
\r
880 static int wimo_mmap(struct file *file, struct vm_area_struct *vma)
\r
883 DLOG("wimo_mmap do nothing current->pid %u\n",current->pid);
\r
888 static int wimo_release(struct inode *inode, struct file *file)
\r
890 DLOG("wimo_release do nothing current->pid %u\n",current->pid);
\r
896 static long wimo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
\r
899 // DLOG("wimo_ioctl cmd %d \n",cmd);
\r
905 mutex_lock(&wimo_lock);
\r
907 mutex_unlock(&wimo_lock);
\r
908 printk("wimo_ioctl WIMO_START wimo.start_sign %d\n",wimo.start_sign);
\r
915 mutex_lock(&wimo_lock);
\r
917 mutex_unlock(&wimo_lock);
\r
918 printk("wimo_ioctl WIMO_STOP wimo.start_sign %d\n",wimo.start_sign);
\r
925 case WIMO_SET_ROTATION:
\r
927 case WIMO_VIDEO_OPEN:
\r
930 unsigned long temp[6];
\r
932 if (copy_from_user(temp, (void*)arg, 24))
\r
934 mutex_lock(&video_lock);
\r
935 ret = wimo_video_open(temp);
\r
936 mutex_unlock(&video_lock);
\r
940 case WIMO_VIDEO_CLOSE:
\r
943 mutex_lock(&video_lock);
\r
944 ret = wimo_video_close(&wimo.video_info);
\r
945 mutex_unlock(&video_lock);
\r
949 case WIMO_VIDEO_GET_BUF:
\r
953 unsigned long temp_data[8];
\r
954 mutex_lock(&video_lock);
\r
956 if(wimo.video_start_sign == 1 && wimo.start_sign == 1 && wimo.video_info.buffer_num)
\r
959 ret = wimo_video_find_frame(temp_data,&wimo.video_info);
\r
962 yuv_time = rgb_time = 0;
\r
968 DLOG("WIMO_VIDEO_GET_BUF starg_sign %d start_video_sign %d",wimo.start_sign,wimo.video_start_sign);
\r
970 mutex_unlock(&video_lock);
\r
971 if (copy_to_user((void*)arg, temp_data, 28))
\r
977 case WIMO_AUDIO_OPEN:
\r
980 unsigned long temp[6];
\r
981 struct wimo_audio_info *audio_info = &wimo.audio_info;
\r
982 if (copy_from_user(temp, (void*)arg, 24))
\r
984 mutex_lock(&audio_lock);
\r
985 ret = wimo_audio_open(temp);
\r
986 mutex_unlock(&audio_lock);
\r
987 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
988 ret,(unsigned long)audio_info->Out_Buffer ,(unsigned long)(temp[0]),audio_info->audio_data,audio_info->time_stamp );
\r
992 case WIMO_AUDIO_CLOSE:
\r
995 printk("WIMO_AUDIO_CLOSE\n");
\r
996 mutex_lock(&audio_lock);
\r
997 ret = wimo_audio_close();
\r
998 mutex_unlock(&audio_lock);
\r
1002 case WIMO_AUDIO_SET_PARA:
\r
1005 struct wimo_audio_param temp_data;
\r
1006 if (copy_from_user((void*)(&temp_data), (void*)arg, sizeof(struct wimo_audio_param)))
\r
1008 mutex_lock(&audio_lock);
\r
1009 wimo_audio_set_para(&temp_data);
\r
1010 mutex_unlock(&audio_lock);
\r
1014 case WIMO_AUDIO_SET_VOL:
\r
1017 unsigned long temp_data;
\r
1019 if (copy_from_user(&temp_data, (void*)arg, 4))
\r
1021 //printk("WIMO_AUDIO_SET_VOL set vol %d\n",temp_data);
\r
1022 mutex_lock(&audio_lock);
\r
1023 wimo.volumn_open_sign = temp_data;
\r
1024 mutex_unlock(&audio_lock);
\r
1028 case WIMO_AUDIO_GET_VOL:
\r
1030 //printk("WIMO_AUDIO_SET_VOL get vol %d\n",wimo.volumn_open_sign);
\r
1031 if(copy_to_user((void*)arg,&wimo.volumn_open_sign,4))
\r
1035 case WIMO_AUDIO_GET_BUF:
\r
1038 struct wimo_audio_info *audio_info = &wimo.audio_info;
\r
1039 mutex_lock(&audio_lock);
\r
1040 if(wimo.audio_start_sign == 1 && wimo.start_sign == 1 && wimo.audio_info.buffer_size)
\r
1042 if(audio_info->data_len >= 1)
\r
1044 struct timeval timeFirst;
\r
1045 do_gettimeofday(&timeFirst);
\r
1046 audio_info->Out_Buffer = (void*)(&audio_info->audio_data[audio_info->head_offset * audio_info->nBytePerFrame]);
\r
1049 wimo_filp_output->f_op->write(wimo_filp_output, audio_info->Out_Buffer, audio_info->nBytePerFrame, &wimo_filp_output->f_pos);
\r
1050 if (copy_to_user((void*)arg,audio_info->Out_Buffer, 4096))
\r
1052 if (copy_to_user((void*)arg+4096,(void*)(&audio_info->time_stamp[audio_info->head_offset]), 8))
\r
1054 if (copy_to_user((void*)arg+4104,&timeFirst, 8))
\r
1056 if (copy_to_user((void*)arg+4112,&audio_info->head_offset, 8))
\r
1058 audio_info->data_len --;
\r
1059 audio_info->head_offset ++;
\r
1060 audio_info->head_offset %= audio_info->buffer_size;
\r
1072 mutex_unlock(&audio_lock);
\r
1082 struct file_operations wimo_fops = {
\r
1083 .open = wimo_open,
\r
1084 .mmap = wimo_mmap,
\r
1085 .unlocked_ioctl = wimo_ioctl,
\r
1086 .release = wimo_release,
\r
1090 static ssize_t debug_open(struct inode *inode, struct file *file)
\r
1092 file->private_data = inode->i_private;
\r
1096 static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
\r
1099 wdm_region *region, *tmp_region;
\r
1100 const int debug_bufmax = 4096;
\r
1101 static char buffer[4096];
\r
1104 DLOG("debug open\n");
\r
1105 n = scnprintf(buffer, debug_bufmax,
\r
1106 "pid #: mapped regions (offset, len, used, post) ...\n");
\r
1107 down_read(&wdm_rwsem);
\r
1109 n += scnprintf(buffer + n, debug_bufmax - n,
\r
1111 region->index, region->pfn, region->used, region->post);
\r
1113 up_read(&wdm_rwsem);
\r
1116 return simple_read_from_buffer(buf, count, ppos, buffer, n);
\r
1119 static struct file_operations debug_fops = {
\r
1120 .read = debug_read,
\r
1121 .open = debug_open,
\r
1125 int wimo_setup(struct wimo_platform_data *pdata)
\r
1128 DLOG("wimo_setup pdata->name %s\n",pdata->name);
\r
1130 printk(KERN_ALERT "Only one wimo driver can be register!\n");
\r
1131 goto err_cant_register_device;
\r
1134 memset(&wimo, 0, sizeof(struct wimo_info));
\r
1136 wimo.rotation_flag = IPP_ROT_0;
\r
1138 init_rwsem(&wdm_rwsem);
\r
1139 wimo.dev.name = pdata->name;
\r
1140 wimo.dev.minor = MISC_DYNAMIC_MINOR;
\r
1141 wimo.dev.fops = &wimo_fops;
\r
1143 err = misc_register(&wimo.dev);
\r
1145 printk(KERN_ALERT "Unable to register wimo driver!\n");
\r
1146 goto err_cant_register_device;
\r
1148 mutex_init(&video_lock);
\r
1149 mutex_init(&audio_lock);
\r
1150 mutex_init(&wimo_lock);
\r
1151 audio_data_to_wimo = wimo_audio_prepare;
\r
1152 video_data_to_wimo = wimo_video_prepare;
\r
1153 printk("set audio_data_to_wimo %x %x\n",(unsigned long)wimo_audio_prepare,(unsigned long)audio_data_to_wimo);
\r
1155 debugfs_create_file(pdata->name, S_IFREG | S_IRUGO, NULL, (void *)wimo.dev.minor,
\r
1158 printk("%s: %d initialized\n", pdata->name, wimo.dev.minor);
\r
1162 //err_no_mem_for_metadata:
\r
1163 misc_deregister(&wimo.dev);
\r
1164 err_cant_register_device:
\r
1168 static int wimo_probe(struct platform_device *pdev)
\r
1170 struct wimo_platform_data *pdata;
\r
1171 printk("wimo_probe\n");
\r
1172 if (!pdev || !pdev->dev.platform_data) {
\r
1173 printk(KERN_ALERT "Unable to probe wimo!\n");
\r
1176 pdata = pdev->dev.platform_data;
\r
1177 return wimo_setup(pdata);
\r
1180 static int wimo_remove(struct platform_device *pdev)
\r
1182 if (!pdev || !pdev->dev.platform_data) {
\r
1183 printk(KERN_ALERT "Unable to remove wimo!\n");
\r
1186 mutex_destroy(&wimo_lock);
\r
1187 mutex_destroy(&audio_lock);
\r
1188 mutex_destroy(&video_lock);
\r
1190 misc_deregister(&wimo.dev);
\r
1193 printk(KERN_ALERT "no wimo to remove!\n");
\r
1198 static struct platform_driver wimo_driver = {
\r
1199 .probe = wimo_probe,
\r
1200 .remove = wimo_remove,
\r
1201 .driver = {.name = "wimo"}
\r
1206 static int __init wimo_init(void)
\r
1208 printk("wimo_init\n");
\r
1209 return platform_driver_register(&wimo_driver);
\r
1212 static void __exit wimo_exit(void)
\r
1214 platform_driver_unregister(&wimo_driver);
\r
1217 module_init(wimo_init);
\r
1218 module_exit(wimo_exit);
\r
1220 #if 0//def CONFIG_PROC_FS
\r
1221 #include <linux/proc_fs.h>
\r
1222 #include <linux/seq_file.h>
\r
1224 static int proc_wimo_show(struct seq_file *s, void *v)
\r
1227 seq_printf(s, "wimo opened\n");
\r
1229 seq_printf(s, "wimo closed\n");
\r
1233 down_read(&wdm_rwsem);
\r
1237 up_read(&wdm_rwsem);
\r
1241 static int proc_wimo_open(struct inode *inode, struct file *file)
\r
1243 return single_open(file, proc_wimo_show, NULL);
\r
1246 static const struct file_operations proc_wimo_fops = {
\r
1247 .open = proc_wimo_open,
\r
1249 .llseek = seq_lseek,
\r
1250 .release = single_release,
\r
1253 static int __init wimo_proc_init(void)
\r
1255 proc_create("wimo", 0, NULL, &proc_wimo_fops);
\r
1259 late_initcall(wimo_proc_init);
\r
1260 #endif /* CONFIG_PROC_FS */
\r