From 4242177a792f0b9da1a0c0d6004159ca5c847d54 Mon Sep 17 00:00:00 2001 From: Huang Jiachai Date: Fri, 18 Sep 2015 17:08:36 +0800 Subject: [PATCH] video: rockchip: fbsys: add node to display a picture 1. su & stop; 2. copy the picture bin to /data/fb0.bin; 3. echo "n xsize ysize format" > /sys/class/graphics/fb0/dsp_buf; ps: a. n is the number of picture b. xsize and ysize is the picture resolution c. format: RGBA=1,RGBX=2,RGB=3,YUV420_SP=17 Change-Id: Id256bee73958b6ab6250a17a723b0b73e7197874 Signed-off-by: Huang Jiachai --- drivers/video/rockchip/rkfb_sysfs.c | 150 +++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) diff --git a/drivers/video/rockchip/rkfb_sysfs.c b/drivers/video/rockchip/rkfb_sysfs.c index cd8af899a5b0..88148a8aa4a5 100755 --- a/drivers/video/rockchip/rkfb_sysfs.c +++ b/drivers/video/rockchip/rkfb_sysfs.c @@ -38,7 +38,7 @@ #include #endif #include "bmp_helper.h" - +#include struct rkfb_sys_trace { int num_frames; int count_frame; @@ -130,6 +130,14 @@ static void fill_buffer(void *handle, void *vaddr, int size) vfs_write(filp, vaddr, size, &filp->f_pos); } +static void read_buffer(void *handle, void *vaddr, int size, loff_t pos) +{ + struct file *filp = handle; + + if (filp) + vfs_read(filp, vaddr, size, &pos); +} + static int dump_win(struct ion_client *ion_client, struct ion_handle *ion_handle, phys_addr_t phys_addr, int width, int height, u8 data_format, uint32_t frameid, @@ -466,6 +474,145 @@ out: return count; } +static ssize_t show_dsp_buffer(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t size; + + size = snprintf(buf, PAGE_SIZE, + "you can display a picture store in " + "/data/fb0.bin use the following cmd:\n" + "echo n xsize ysize format > dsp_buf\n" + "n: picture number" + "xsize: picture horizontal size\n" + "ysize: picture vertical size\n" + "format:\n" + " RGBA=1,RGBX=2,RGB=3,YUV420SP=17"); + + return size; +} +extern int __close_fd(struct files_struct *files, unsigned fd); + +static ssize_t set_dsp_buffer(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par; + struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv; + struct rk_fb *rk_fb = dev_get_drvdata(fbi->device); + struct file *filp; + mm_segment_t old_fs; + int width, height, frame_num; + int i, j, flags, fd; + const char *start = buf; + struct ion_handle *handle = NULL; + char __iomem *screen_base; + struct rk_fb_win_cfg_data win_config; + struct rk_screen *screen = dev_drv->cur_screen; + int space_max = 10; + int format; + size_t mem_size = 0; + char *name = "/data/fb0.bin"; + struct sync_fence *acq_fence; + struct files_struct *files = current->files; + + frame_num = simple_strtoul(start, NULL, 10); + do { + start++; + space_max--; + } while ((*start != ' ') && space_max); + start++; + width = simple_strtoul(start, NULL, 10); + do { + start++; + space_max--; + } while ((*start != ' ') && space_max); + start++; + height = simple_strtoul(start, NULL, 10); + + do { + start++; + space_max--; + } while ((*start != ' ') && space_max); + start++; + format = simple_strtoul(start, NULL, 10); + + pr_info("frame_num=%d,w=%d,h=%d,file=%s,format=%d\n", + frame_num, width, height, name, format); + flags = O_RDWR | O_CREAT | O_NONBLOCK; + filp = filp_open(name, flags, 0x600); + if (!filp) + pr_err("fail to create %s\n", name); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + mem_size = width * height * 4 * frame_num; + if (dev_drv->iommu_enabled) + handle = ion_alloc(rk_fb->ion_client, mem_size, 0, + ION_HEAP(ION_VMALLOC_HEAP_ID), 0); + else + handle = ion_alloc(rk_fb->ion_client, mem_size, 0, + ION_HEAP(ION_CMA_HEAP_ID), 0); + if (IS_ERR(handle)) { + pr_err("failed to ion_alloc:%ld\n", PTR_ERR(handle)); + return -ENOMEM; + } + fd = ion_share_dma_buf_fd(rk_fb->ion_client, handle); + if (fd < 0) { + pr_err("ion_share_dma_buf_fd failed, fd=%d\n", fd); + return fd; + } + screen_base = ion_map_kernel(rk_fb->ion_client, handle); + read_buffer(filp, screen_base, mem_size, 0); + + memset(&win_config, 0, sizeof(win_config)); + win_config.wait_fs = 0; + win_config.win_par[0].win_id = 0; + win_config.win_par[0].z_order = 0; + win_config.win_par[0].area_par[0].data_format = format; + win_config.win_par[0].area_par[0].ion_fd = fd; + win_config.win_par[0].area_par[0].x_offset = 0; + win_config.win_par[0].area_par[0].y_offset = 0; + win_config.win_par[0].area_par[0].xpos = 0; + win_config.win_par[0].area_par[0].ypos = 0; + win_config.win_par[0].area_par[0].xsize = screen->mode.xres; + win_config.win_par[0].area_par[0].ysize = screen->mode.yres; + win_config.win_par[0].area_par[0].xact = width; + win_config.win_par[0].area_par[0].yact = height; + win_config.win_par[0].area_par[0].xvir = width; + win_config.win_par[0].area_par[0].yvir = height; + + for (i = 0; i < frame_num; i++) { + win_config.win_par[0].area_par[0].y_offset = height * i; + fbi->fbops->fb_ioctl(fbi, RK_FBIOSET_CONFIG_DONE, + (unsigned long)(&win_config)); + for (j = 0; j < RK_MAX_BUF_NUM; j++) { + if (win_config.rel_fence_fd[j] > 0) { + acq_fence = + sync_fence_fdget(win_config.rel_fence_fd[j]); + sync_fence_put(acq_fence); + } + } + + if (win_config.ret_fence_fd > 0){ + acq_fence = + sync_fence_fdget(win_config.ret_fence_fd); + sync_fence_put(acq_fence); + } + } + + ion_unmap_kernel(rk_fb->ion_client, handle); + ion_free(rk_fb->ion_client, handle); + __close_fd(files, fd); + + set_fs(old_fs); + filp_close(filp, NULL); + + return count; +} + static ssize_t show_phys(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1060,6 +1207,7 @@ static struct device_attribute rkfb_attrs[] = { __ATTR(virt_addr, S_IRUGO, show_virt, NULL), __ATTR(disp_info, S_IRUGO, show_disp_info, NULL), __ATTR(dump_buf, S_IRUGO | S_IWUSR, show_dump_buffer, set_dump_buffer), + __ATTR(dsp_buf, S_IRUGO | S_IWUSR, show_dsp_buffer, set_dsp_buffer), __ATTR(screen_info, S_IRUGO, show_screen_info, NULL), __ATTR(dual_mode, S_IRUGO, show_dual_mode, NULL), __ATTR(enable, S_IRUGO | S_IWUSR, show_fb_state, set_fb_state), -- 2.34.1