diff options
Diffstat (limited to 'drivers/video/samsung_extdisp')
-rw-r--r-- | drivers/video/samsung_extdisp/s3cfb_extdsp.h | 20 | ||||
-rw-r--r-- | drivers/video/samsung_extdisp/s3cfb_extdsp_ops.c | 104 |
2 files changed, 113 insertions, 11 deletions
diff --git a/drivers/video/samsung_extdisp/s3cfb_extdsp.h b/drivers/video/samsung_extdisp/s3cfb_extdsp.h index 964c549..99f134c 100644 --- a/drivers/video/samsung_extdisp/s3cfb_extdsp.h +++ b/drivers/video/samsung_extdisp/s3cfb_extdsp.h @@ -50,6 +50,12 @@ enum s3cfb_extdsp_mem_owner_t { DMA_MEM_OTHER = 2, }; +enum s3cfb_extdsp_buf_status_t { + BUF_FREE = 0, + BUF_ACTIVE = 1, + BUF_LOCKED = 2, +}; + struct s3cfb_extdsp_lcd_polarity { int rise_vclk; int inv_hsync; @@ -73,6 +79,12 @@ struct s3cfb_extdsp_time_stamp { struct timeval time_marker; }; +struct s3cfb_extdsp_buf_list { + unsigned int phys_addr; + struct timeval time_marker; + int buf_status; +}; + struct s3cfb_extdsp_global { struct mutex lock; struct device *dev; @@ -90,8 +102,9 @@ struct s3cfb_extdsp_global { struct early_suspend early_suspend; struct wake_lock idle_lock; #endif - struct s3cfb_extdsp_time_stamp time_stamp[CONFIG_FB_S5P_EXTDSP_NR_BUFFERS]; + struct s3cfb_extdsp_buf_list buf_list[CONFIG_FB_S5P_EXTDSP_NR_BUFFERS]; unsigned int enabled_tz; + unsigned int lock_cnt; }; struct s3cfb_extdsp_window { @@ -105,6 +118,7 @@ struct s3cfb_extdsp_window { int lock_status; int lock_buf_idx; unsigned int lock_buf_offset; + unsigned int free_buf_offset; }; struct s3cfb_extdsp_user_window { @@ -131,6 +145,10 @@ struct s3cfb_extdsp_user_window { struct s3cfb_extdsp_time_stamp) #define S3CFB_EXTDSP_GET_TZ_MODE _IOW ('F', 325, unsigned int) #define S3CFB_EXTDSP_SET_TZ_MODE _IOW ('F', 326, unsigned int) +#define S3CFB_EXTDSP_GET_LOCKED_NUMBER _IOW ('F', 327, unsigned int) +#define S3CFB_EXTDSP_LOCK_AND_GET_BUF _IOW ('F', 328, \ + struct s3cfb_extdsp_buf_list) +#define S3CFB_EXTDSP_GET_FREE_BUFFER _IOW('F', 329, unsigned int) extern struct fb_ops s3cfb_extdsp_ops; extern inline struct s3cfb_extdsp_global *get_extdsp_global(int id); diff --git a/drivers/video/samsung_extdisp/s3cfb_extdsp_ops.c b/drivers/video/samsung_extdisp/s3cfb_extdsp_ops.c index b5867b4..522442d 100644 --- a/drivers/video/samsung_extdisp/s3cfb_extdsp_ops.c +++ b/drivers/video/samsung_extdisp/s3cfb_extdsp_ops.c @@ -505,6 +505,7 @@ int s3cfb_extdsp_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) struct s3cfb_extdsp_user_window user_window; int vsync; int lock; + struct s3cfb_extdsp_buf_list buf_list; } p; switch (cmd) { @@ -522,10 +523,61 @@ int s3cfb_extdsp_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) win->lock_buf_offset = fix->smem_start + ((var->xres_virtual * var->yoffset + var->xoffset) * (var->bits_per_pixel / 8)); + for (i = 0; i < CONFIG_FB_S5P_EXTDSP_NR_BUFFERS; i++) { + if (fbdev->buf_list[i].phys_addr == + (unsigned int)win->lock_buf_offset) + fbdev->buf_list[i].buf_status = + BUF_LOCKED; + } } else { /* Unlocked */ + for (i = 0; i < CONFIG_FB_S5P_EXTDSP_NR_BUFFERS; i++) { + if (fbdev->buf_list[i].phys_addr == + (unsigned int)win->lock_buf_offset) + fbdev->buf_list[i].buf_status = + BUF_FREE; + } win->lock_buf_offset = 0; } break; + case S3CFB_EXTDSP_LOCK_AND_GET_BUF: + if (copy_from_user(&p.buf_list, + (struct s3cfb_extdsp_buf_list __user *)arg, + sizeof(p.buf_list))) + return -EFAULT; + + if (p.buf_list.buf_status == BUF_LOCKED) { /* Locked */ + memset(&p.buf_list, 0, sizeof(p.buf_list)); + for (i = 0; i < CONFIG_FB_S5P_EXTDSP_NR_BUFFERS; i++) { + if (fbdev->buf_list[i].buf_status == + BUF_ACTIVE) { + fbdev->buf_list[i].buf_status = + BUF_LOCKED; + + p.buf_list.phys_addr = + fbdev->buf_list[i].phys_addr; + p.buf_list.time_marker = + fbdev->buf_list[i].time_marker; + p.buf_list.buf_status = + fbdev->buf_list[i].buf_status; + break; + } + } + } else if (p.buf_list.buf_status == BUF_FREE) { /* Unlocked */ + for (i = 0; i < CONFIG_FB_S5P_EXTDSP_NR_BUFFERS; i++) { + if (fbdev->buf_list[i].phys_addr == + p.buf_list.phys_addr) { + fbdev->buf_list[i].buf_status = + BUF_FREE; + break; + } + } + } + if (copy_to_user((void *)arg, &(p.buf_list), + sizeof(unsigned int))) { + dev_err(fbdev->dev, "copy_to_user error\n"); + return -EFAULT; + } + break; case S3CFB_EXTDSP_GET_LOCKED_BUFFER: if (copy_to_user((void *)arg, &(win->lock_buf_offset), @@ -535,6 +587,22 @@ int s3cfb_extdsp_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) } break; + case S3CFB_EXTDSP_GET_FREE_BUFFER: + win->free_buf_offset = 0; + for (i = 0; i < CONFIG_FB_S5P_EXTDSP_NR_BUFFERS; i++) { + if (fbdev->buf_list[i].buf_status == BUF_FREE) { + win->free_buf_offset = + fbdev->buf_list[i].phys_addr; + break; + } + } + if (copy_to_user((void *)arg, &(win->free_buf_offset), + sizeof(unsigned int))) { + dev_err(fbdev->dev, "copy_to_user error\n"); + return -EFAULT; + } + break; + case S3CFB_EXTDSP_GET_NEXT_INDEX: cur_nrbuffer = var->yoffset / (var->yres_virtual / CONFIG_FB_S5P_EXTDSP_NR_BUFFERS); @@ -606,20 +674,20 @@ int s3cfb_extdsp_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) } do_gettimeofday(&time_stamp.time_marker); for(i = 0; i < CONFIG_FB_S5P_EXTDSP_NR_BUFFERS; i++) { - if (fbdev->time_stamp[i].phys_addr == time_stamp.phys_addr) { - fbdev->time_stamp[i].time_marker = time_stamp.time_marker; + if (fbdev->buf_list[i].phys_addr == time_stamp.phys_addr) { + fbdev->buf_list[i].time_marker = time_stamp.time_marker; break; } - if (!fbdev->time_stamp[i].phys_addr) { - fbdev->time_stamp[i].phys_addr = time_stamp.phys_addr; - fbdev->time_stamp[i].time_marker = time_stamp.time_marker; + if (!fbdev->buf_list[i].phys_addr) { + fbdev->buf_list[i].phys_addr = time_stamp.phys_addr; + fbdev->buf_list[i].time_marker = time_stamp.time_marker; break; } if (i == (CONFIG_FB_S5P_EXTDSP_NR_BUFFERS -1)) { - fbdev->time_stamp[0].phys_addr = time_stamp.phys_addr; - fbdev->time_stamp[0].time_marker = time_stamp.time_marker; + fbdev->buf_list[0].phys_addr = time_stamp.phys_addr; + fbdev->buf_list[0].time_marker = time_stamp.time_marker; for(i = 1; i < CONFIG_FB_S5P_EXTDSP_NR_BUFFERS; i++) - fbdev->time_stamp[i].phys_addr = 0; + fbdev->buf_list[i].phys_addr = 0; break; } } @@ -633,8 +701,8 @@ int s3cfb_extdsp_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) return -EFAULT; } for(i = 0; i < CONFIG_FB_S5P_EXTDSP_NR_BUFFERS; i++) { - if (fbdev->time_stamp[i].phys_addr == time_stamp.phys_addr) { - time_stamp.time_marker = fbdev->time_stamp[i].time_marker; + if (fbdev->buf_list[i].phys_addr == time_stamp.phys_addr) { + time_stamp.time_marker = fbdev->buf_list[i].time_marker; break; } } @@ -646,6 +714,15 @@ int s3cfb_extdsp_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) } break; + case S3CFB_EXTDSP_GET_LOCKED_NUMBER: + fbdev->lock_cnt = 0; + for (i = 0; i < CONFIG_FB_S5P_EXTDSP_NR_BUFFERS; i++) { + if (fbdev->buf_list[i].buf_status == BUF_LOCKED) + fbdev->lock_cnt++; + } + ret = memcpy(argp, &fbdev->lock_cnt, sizeof(fbdev->lock_cnt)) ? 0 : -EFAULT; + break; + case FBIOGET_FSCREENINFO: ret = memcpy(argp, &fb->fix, sizeof(fb->fix)) ? 0 : -EFAULT; break; @@ -700,6 +777,13 @@ int s3cfb_extdsp_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) case S3CFB_EXTDSP_SET_WIN_ADDR: fix->smem_start = (unsigned long)argp; + for (i = 0; i < CONFIG_FB_S5P_EXTDSP_NR_BUFFERS; i++) { + if (fbdev->buf_list[i].phys_addr == + (unsigned int)fix->smem_start) + fbdev->buf_list[i].buf_status = BUF_ACTIVE; + else if (fbdev->buf_list[i].buf_status != BUF_LOCKED) + fbdev->buf_list[i].buf_status = BUF_FREE; + } break; case S3CFB_EXTDSP_GET_TZ_MODE: |