Merge tag 'lsk-v3.10-15.10-android'
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / rkfb_sysfs.c
1 /*
2  * linux/drivers/video/rockchip/rkfb-sysfs.c
3  *
4  * Copyright (C) 2012 Rockchip Corporation
5  * Author: yxj<yxj@rock-chips.com>
6  *
7  * Some code and ideas taken from
8  *drivers/video/omap2/omapfb/omapfb-sys.c
9  *driver by Tomi Valkeinen.
10  *
11  *
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License version 2 as published by
14  * the Free Software Foundation.
15  *
16  * This program is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19  * more details.
20  *
21  * You should have received a copy of the GNU General Public License along with
22  * this program.  If not, see <http://www.gnu.org/licenses/>.
23  */
24
25 #include <linux/fb.h>
26 #include <linux/namei.h>
27 #include <linux/sysfs.h>
28 #include <linux/device.h>
29 #include <linux/uaccess.h>
30 #include <linux/platform_device.h>
31 #include <linux/kernel.h>
32 #include <linux/mm.h>
33 #include <linux/vmalloc.h>
34 #include <asm/div64.h>
35 #include <linux/rk_screen.h>
36 #include <linux/rk_fb.h>
37 #if defined(CONFIG_ION_ROCKCHIP)
38 #include <linux/rockchip_ion.h>
39 #endif
40 #include "bmp_helper.h"
41 #include <linux/delay.h>
42 struct rkfb_sys_trace {
43         int num_frames;
44         int count_frame;
45         int mask_win;
46         int mask_area;
47         bool is_bmp;
48         bool is_append;
49 };
50 #define DUMP_BUF_PATH           "/data/dmp_buf"
51
52 static char *get_format_str(enum data_format format)
53 {
54         switch (format) {
55         case ARGB888:
56                 return "ARGB888";
57         case RGB888:
58                 return "RGB888";
59         case RGB565:
60                 return "RGB565";
61         case YUV420:
62         case YUV420_NV21:
63                 return "YUV420";
64         case YUV422:
65                 return "YUV422";
66         case YUV444:
67                 return "YUV444";
68         case YUV420_A:
69                 return "YUV420_A";
70         case YUV422_A:
71                 return "YUV422_A";
72         case YUV444_A:
73                 return "YUV444_A";
74         case XRGB888:
75                 return "XRGB888";
76         case XBGR888:
77                 return "XBGR888";
78         case ABGR888:
79                 return "ABGR888";
80         case FBDC_RGB_565:
81                 return "FBDC_RGB_565";
82         case FBDC_ARGB_888:
83                 return "FBDC_ARGB_888";
84         case FBDC_RGBX_888:
85                 return "FBDC_RGBX_888";
86         default:
87                 return "invalid";
88         }
89 }
90
91 static ssize_t show_screen_info(struct device *dev,
92                                 struct device_attribute *attr, char *buf)
93 {
94         struct fb_info *fbi = dev_get_drvdata(dev);
95         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
96         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
97         struct rk_screen *screen = dev_drv->cur_screen;
98         int fps = 0;
99         u32 x = screen->mode.left_margin + screen->mode.right_margin +
100                 screen->mode.xres + screen->mode.hsync_len;
101         u32 y = screen->mode.upper_margin + screen->mode.lower_margin +
102                 screen->mode.yres + screen->mode.vsync_len;
103         u64 ft = (u64)x * y * (dev_drv->pixclock);
104
105         if (ft > 0)
106                 fps = div64_u64(1000000000000llu, ft);
107         return snprintf(buf, PAGE_SIZE, "xres:%d\nyres:%d\nfps:%d\n",
108                         screen->mode.xres, screen->mode.yres, fps);
109 }
110
111 static ssize_t show_disp_info(struct device *dev,
112                               struct device_attribute *attr, char *buf)
113 {
114         struct fb_info *fbi = dev_get_drvdata(dev);
115         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
116         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
117         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
118
119         if (dev_drv->ops->get_disp_info)
120                 return dev_drv->ops->get_disp_info(dev_drv, buf, win_id);
121
122         return 0;
123 }
124
125 static void fill_buffer(void *handle, void *vaddr, int size)
126 {
127         struct file *filp = handle;
128
129         if (filp)
130                 vfs_write(filp, vaddr, size, &filp->f_pos);
131 }
132
133 static void read_buffer(void *handle, void *vaddr, int size, loff_t pos)
134 {
135         struct file *filp = handle;
136
137         if (filp)
138                 vfs_read(filp, vaddr, size, &pos);
139 }
140
141 static int dump_win(struct ion_client *ion_client,
142                     struct ion_handle *ion_handle, phys_addr_t phys_addr,
143                     int width, int height, u8 data_format, uint32_t frameid,
144                     int win_id, int area_id, bool is_bmp, bool is_append)
145 {
146         void __iomem *vaddr = NULL;
147         struct file *filp;
148         mm_segment_t old_fs;
149         char name[100];
150         int flags;
151         int bits;
152
153         switch (data_format) {
154         case XRGB888:
155         case XBGR888:
156         case ARGB888:
157         case ABGR888:
158         case FBDC_RGBX_888:
159                 bits = 32;
160                 break;
161         case YUV444_A:
162         case YUV444:
163         case RGB888:
164         case FBDC_ARGB_888:
165                 bits = 24;
166                 break;
167         case RGB565:
168         case FBDC_RGB_565:
169         case YUV422:
170         case YUV422_A:
171                 bits = 16;
172                 break;
173         case YUV420_A:
174         case YUV420:
175         case YUV420_NV21:
176                 bits = 12;
177                 break;
178         default:
179                 return 0;
180         }
181
182         if (ion_handle) {
183                 vaddr = ion_map_kernel(ion_client, ion_handle);
184         } else if (phys_addr) {
185                 unsigned long start;
186                 unsigned int nr_pages;
187                 struct page **pages;
188                 int i = 0;
189
190                 start = phys_addr;
191                 nr_pages = roundup(width * height * (bits >> 3), PAGE_SIZE);
192                 nr_pages /= PAGE_SIZE;
193                 pages = kzalloc(sizeof(struct page) * nr_pages,GFP_KERNEL);
194                 while (i < nr_pages) {
195                         pages[i] = phys_to_page(start);
196                         start += PAGE_SIZE;
197                         i++;
198                 }
199                 vaddr = vmap(pages, nr_pages, VM_MAP,
200                              pgprot_writecombine(PAGE_KERNEL));
201                 if (!vaddr) {
202                         pr_err("failed to vmap phy addr %lx\n",
203                                start);
204                         return -1;
205                 }
206         } else {
207                 return 0;
208         }
209
210         flags = O_RDWR | O_CREAT | O_NONBLOCK;
211         if (is_append) {
212                 snprintf(name, 100, "%s/append_win%d_%d_%dx%d_%s.%s",
213                          DUMP_BUF_PATH, win_id, area_id, width, height,
214                          get_format_str(data_format), is_bmp ? "bmp" : "bin");
215                 flags |= O_APPEND;
216         } else {
217                 snprintf(name, 100, "%s/frame%d_win%d_%d_%dx%d_%s.%s",
218                          DUMP_BUF_PATH, frameid, win_id, area_id, width, height,
219                          get_format_str(data_format), is_bmp ? "bmp" : "bin");
220         }
221
222         pr_info("dump win == > %s\n", name);
223         filp = filp_open(name, flags, 0x600);
224         if (!filp)
225                 printk("fail to create %s\n", name);
226
227         old_fs = get_fs();
228         set_fs(KERNEL_DS);
229
230         if (is_bmp)
231                 bmpencoder(vaddr, width, height,
232                            data_format, filp, fill_buffer);
233         else
234                 fill_buffer(filp, vaddr, width * height * bits >> 3);
235
236         set_fs(old_fs);
237
238         if (ion_handle)
239                 ion_unmap_kernel(ion_client, ion_handle);
240         else if (vaddr)
241                 vunmap(vaddr);
242
243         filp_close(filp, NULL);
244
245         return 0;
246 }
247
248 static ssize_t show_dump_buffer(struct device *dev,
249                               struct device_attribute *attr, char *buf)
250 {
251         ssize_t size;
252
253         size = snprintf(buf, PAGE_SIZE,
254                         "bmp       -- dump buffer to bmp image\n"
255                         "bin       -- dump buffer to bin image\n"
256                         "multi    --  each dump will create new file\n"
257                         "win=num   -- mask win to dump, default mask all\n"
258                         "             win=1, will dump win1 buffer\n"
259                         "             win=23, will dump win2 area3 buffer\n"
260                         "trace=num -- trace num frames buffer dump\n"
261                         "             this option will block buffer switch\n"
262                         "             so recommend use with bin and win=xx\n"
263                         "\nExample:\n"
264                         "echo bmp > dump_buf; -- dump current buf to bmp file\n"
265                         "echo bin > dump_buf; -- dump current buf to bin file\n"
266                         "echo trace=50:win=1:win=23 > dump_buf\n"
267                         "         -- dump 50 frames, dump win1 and win2 area3\n"
268                         "         -- dump all buffer to single file\n"
269                         "You can found dump files at %s\n"
270                         , DUMP_BUF_PATH);
271
272         return size;
273 }
274
275 void trace_buffer_dump(struct device *dev, struct rk_lcdc_driver *dev_drv)
276 {
277         struct rk_fb *rk_fb = dev_get_drvdata(dev);
278         struct rk_fb_reg_data *front_regs;
279         struct rk_fb_reg_win_data *win_data;
280         struct rk_fb_reg_area_data *area_data;
281         struct rkfb_sys_trace *trace = dev_drv->trace_buf;
282         int i,j;
283
284         if (!trace)
285                 return;
286         if (trace->num_frames <= trace->count_frame)
287                 return;
288
289         if (!dev_drv->front_regs)
290                 return;
291         front_regs = dev_drv->front_regs;
292
293         for (i = 0; i < front_regs->win_num; i++) {
294                 if (trace->mask_win && !(trace->mask_win & (1 << i)))
295                         continue;
296                 for (j = 0; j < RK_WIN_MAX_AREA; j++) {
297                         win_data = &front_regs->reg_win_data[i];
298                         area_data = &win_data->reg_area_data[j];
299                         if (trace->mask_area && !(trace->mask_area & (1 << j)))
300                                 continue;
301
302                         dump_win(rk_fb->ion_client, area_data->ion_handle,
303                                  area_data->smem_start,
304                                  area_data->xvir, area_data->yvir,
305                                  area_data->data_format, trace->count_frame,
306                                  i, j, trace->is_bmp, trace->is_append);
307                 }
308         }
309         trace->count_frame++;
310 }
311
312 static ssize_t set_dump_buffer(struct device *dev,
313                                struct device_attribute *attr,
314                                const char *buf, size_t count)
315 {
316         struct fb_info *fbi = dev_get_drvdata(dev);
317         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
318         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
319         struct rk_fb *rk_fb = dev_get_drvdata(fbi->device);
320         struct rk_fb_reg_data *front_regs;
321         struct rk_fb_reg_win_data *win_data;
322         struct rk_fb_reg_area_data *area_data;
323         struct rkfb_sys_trace *trace;
324         struct dentry *dentry;
325         struct path path;
326         int err = 0;
327         int num_frames = 0;
328         int mask_win = 0;
329         int mask_area = 0;
330         bool is_bmp = false;
331         bool is_append = true;
332         char *p;
333         int i, j;
334
335         if (!rk_fb->ion_client)
336                 return 0;
337
338         if (!dev_drv->trace_buf) {
339                 dev_drv->trace_buf = devm_kmalloc(dev_drv->dev,
340                                                   sizeof(struct rkfb_sys_trace),
341                                                   GFP_KERNEL);
342                 if (!dev_drv->trace_buf)
343                         return -ENOMEM;
344         }
345         trace = dev_drv->trace_buf;
346         /*
347          * Stop buffer trace.
348          */
349         trace->num_frames = 0;
350
351         while ((p = strsep((char **)&buf, ":")) != NULL) {
352                 if (!*p)
353                         continue;
354                 if (!strncmp(p, "trace=", 6)) {
355                         if (kstrtoint(p + 6, 0, &num_frames))
356                                 dev_err(dev, "can't found trace frames\n");
357                         continue;
358                 }
359                 if (!strncmp(p, "win=", 4)) {
360                         int win;
361
362                         if (kstrtoint(p + 4, 0, &win))
363                                 dev_err(dev, "can't found trace frames\n");
364                         if (win < 10)
365                                mask_win |= 1 << win;
366                         else {
367                                 mask_win |= 1 << (win / 10);
368                                 mask_area |= 1 << (win % 10);
369                         }
370
371                         continue;
372                 }
373                 if (!strncmp(p, "bmp", 3)) {
374                         is_bmp = true;
375                         is_append = false;
376                         continue;
377                 }
378                 if (!strncmp(p, "bin", 3)) {
379                         is_bmp = false;
380                         continue;
381                 }
382                 if (!strncmp(p, "multi", 5)) {
383                         is_append = true;
384                         is_bmp = false;
385                         continue;
386                 }
387
388                 dev_err(dev, "unknown option %s\n", p);
389         }
390
391         dentry = kern_path_create(AT_FDCWD, DUMP_BUF_PATH, &path,
392                                   LOOKUP_DIRECTORY);
393         if (!IS_ERR(dentry)) {
394                 err = vfs_mkdir(path.dentry->d_inode, dentry, 700);
395                 if (err)
396                         dev_err(dev, "can't create %s err%d\n",
397                                 DUMP_BUF_PATH, err);
398                 done_path_create(&path, dentry);
399         } else if (PTR_ERR(dentry) != -EEXIST) {
400                 dev_err(dev, "can't create PATH %s err%d\n",
401                                 DUMP_BUF_PATH, err);
402                 return PTR_ERR(dentry);
403         }
404
405         if (!num_frames) {
406                 mutex_lock(&dev_drv->front_lock);
407
408                 if (!dev_drv->front_regs) {
409                         u16 xact, yact;
410                         int data_format;
411                         u32 dsp_addr;
412
413                         mutex_unlock(&dev_drv->front_lock);
414
415                         if (dev_drv->ops->get_dspbuf_info)
416                                 dev_drv->ops->get_dspbuf_info(dev_drv, &xact,
417                                                 &yact, &data_format, &dsp_addr);
418
419                         dump_win(NULL, NULL, dsp_addr, xact, yact, data_format,
420                                  0, 0, 0, is_bmp, false);
421                         goto out;
422                 }
423                 front_regs = kmalloc(sizeof(*front_regs), GFP_KERNEL);
424                 if (!front_regs)
425                         return -ENOMEM;
426                 memcpy(front_regs, dev_drv->front_regs, sizeof(*front_regs));
427
428                 for (i = 0; i < front_regs->win_num; i++) {
429                         if (mask_win && !(mask_win & (1 << i)))
430                                 continue;
431                         for (j = 0; j < RK_WIN_MAX_AREA; j++) {
432                                 if (mask_area && !(mask_area & (1 << j)))
433                                         continue;
434                                 win_data = &front_regs->reg_win_data[i];
435                                 area_data = &win_data->reg_area_data[j];
436                                 if (area_data->ion_handle)
437                                         ion_handle_get(area_data->ion_handle);
438                         }
439                 }
440
441                 for (i = 0; i < front_regs->win_num; i++) {
442                         if (mask_win && !(mask_win & (1 << i)))
443                                 continue;
444                         for (j = 0; j < RK_WIN_MAX_AREA; j++) {
445                                 if (mask_area && !(mask_area & (1 << j)))
446                                         continue;
447
448                                 win_data = &front_regs->reg_win_data[i];
449                                 area_data = &win_data->reg_area_data[j];
450
451                                 dump_win(rk_fb->ion_client, area_data->ion_handle,
452                                          area_data->smem_start,
453                                          area_data->xvir, area_data->yvir,
454                                          area_data->data_format, trace->count_frame,
455                                          i, j, trace->is_bmp, trace->is_append);
456                                 if (area_data->ion_handle)
457                                         ion_handle_put(area_data->ion_handle);
458                         }
459                 }
460
461                 kfree(front_regs);
462
463                 mutex_unlock(&dev_drv->front_lock);
464         } else {
465                 trace->num_frames = num_frames;
466                 trace->count_frame = 0;
467                 trace->is_bmp = is_bmp;
468                 trace->is_append = is_append;
469                 trace->mask_win = mask_win;
470                 trace->mask_area = mask_area;
471         }
472 out:
473
474         return count;
475 }
476
477 static ssize_t show_dsp_buffer(struct device *dev,
478                                struct device_attribute *attr, char *buf)
479 {
480         ssize_t size;
481
482         size = snprintf(buf, PAGE_SIZE,
483                         "you can display a picture store in "
484                         "/data/fb0.bin use the following cmd:\n"
485                         "echo n xsize ysize format > dsp_buf\n"
486                         "n: picture number"
487                         "xsize: picture horizontal size\n"
488                         "ysize: picture vertical size\n"
489                         "format:\n"
490                         "    RGBA=1,RGBX=2,RGB=3,YUV420SP=17");
491
492         return size;
493 }
494 extern int __close_fd(struct files_struct *files, unsigned fd);
495
496 static ssize_t set_dsp_buffer(struct device *dev,
497                                struct device_attribute *attr,
498                                const char *buf, size_t count)
499 {
500         struct fb_info *fbi = dev_get_drvdata(dev);
501         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
502         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
503         struct rk_fb *rk_fb = dev_get_drvdata(fbi->device);
504         struct file *filp;
505         mm_segment_t old_fs;
506         int width, height, frame_num;
507         int i, j, flags, fd;
508         const char *start = buf;
509         struct ion_handle *handle = NULL;
510         char __iomem *screen_base;
511         struct rk_fb_win_cfg_data win_config;
512         struct rk_screen *screen = dev_drv->cur_screen;
513         int space_max = 10;
514         int format;
515         size_t mem_size = 0;
516         char *name = "/data/fb0.bin";
517         struct sync_fence *acq_fence;
518         struct files_struct *files = current->files;
519
520         frame_num = simple_strtoul(start, NULL, 10);
521         do {
522                 start++;
523                 space_max--;
524         } while ((*start != ' ') && space_max);
525         start++;
526         width = simple_strtoul(start, NULL, 10);
527         do {
528                 start++;
529                 space_max--;
530         } while ((*start != ' ') && space_max);
531         start++;
532         height = simple_strtoul(start, NULL, 10);
533
534         do {
535                 start++;
536                 space_max--;
537         } while ((*start != ' ') && space_max);
538         start++;
539         format = simple_strtoul(start, NULL, 10);
540
541         pr_info("frame_num=%d,w=%d,h=%d,file=%s,format=%d\n",
542                 frame_num, width, height, name, format);
543         flags = O_RDWR | O_CREAT | O_NONBLOCK;
544         filp = filp_open(name, flags, 0x600);
545         if (!filp)
546                 pr_err("fail to create %s\n", name);
547
548         old_fs = get_fs();
549         set_fs(KERNEL_DS);
550
551         mem_size = width * height * 4 * frame_num;
552         if (dev_drv->iommu_enabled)
553                 handle = ion_alloc(rk_fb->ion_client, mem_size, 0,
554                                    ION_HEAP(ION_VMALLOC_HEAP_ID), 0);
555         else
556                 handle = ion_alloc(rk_fb->ion_client, mem_size, 0,
557                                    ION_HEAP(ION_CMA_HEAP_ID), 0);
558         if (IS_ERR(handle)) {
559                 pr_err("failed to ion_alloc:%ld\n", PTR_ERR(handle));
560                 return -ENOMEM;
561         }
562         fd = ion_share_dma_buf_fd(rk_fb->ion_client, handle);
563         if (fd < 0) {
564                 pr_err("ion_share_dma_buf_fd failed, fd=%d\n", fd);
565                 return fd;
566         }
567         screen_base = ion_map_kernel(rk_fb->ion_client, handle);
568         read_buffer(filp, screen_base, mem_size, 0);
569
570         memset(&win_config, 0, sizeof(win_config));
571         win_config.wait_fs = 0;
572         win_config.win_par[0].win_id = 0;
573         win_config.win_par[0].z_order = 0;
574         win_config.win_par[0].area_par[0].data_format = format;
575         win_config.win_par[0].area_par[0].ion_fd = fd;
576         win_config.win_par[0].area_par[0].x_offset = 0;
577         win_config.win_par[0].area_par[0].y_offset = 0;
578         win_config.win_par[0].area_par[0].xpos = 0;
579         win_config.win_par[0].area_par[0].ypos = 0;
580         win_config.win_par[0].area_par[0].xsize = screen->mode.xres;
581         win_config.win_par[0].area_par[0].ysize = screen->mode.yres;
582         win_config.win_par[0].area_par[0].xact = width;
583         win_config.win_par[0].area_par[0].yact = height;
584         win_config.win_par[0].area_par[0].xvir = width;
585         win_config.win_par[0].area_par[0].yvir = height;
586
587         for (i = 0; i < frame_num; i++) {
588                 win_config.win_par[0].area_par[0].y_offset = height * i;
589                 fbi->fbops->fb_ioctl(fbi, RK_FBIOSET_CONFIG_DONE,
590                                      (unsigned long)(&win_config));
591                 for (j = 0; j < RK_MAX_BUF_NUM; j++) {
592                         if (win_config.rel_fence_fd[j] > 0) {
593                                 acq_fence =
594                                 sync_fence_fdget(win_config.rel_fence_fd[j]);
595                                 sync_fence_put(acq_fence);
596                         }
597                 }
598
599                 if (win_config.ret_fence_fd > 0){
600                         acq_fence =
601                         sync_fence_fdget(win_config.ret_fence_fd);
602                         sync_fence_put(acq_fence);
603                 }
604         }
605
606         ion_unmap_kernel(rk_fb->ion_client, handle);
607         ion_free(rk_fb->ion_client, handle);
608         __close_fd(files, fd);
609
610         set_fs(old_fs);
611         filp_close(filp, NULL);
612
613         return count;
614 }
615
616 static ssize_t show_phys(struct device *dev,
617                          struct device_attribute *attr, char *buf)
618 {
619         struct fb_info *fbi = dev_get_drvdata(dev);
620
621         return snprintf(buf, PAGE_SIZE, "0x%lx-----0x%x\n",
622                         fbi->fix.smem_start, fbi->fix.smem_len);
623 }
624
625 static ssize_t show_virt(struct device *dev,
626                          struct device_attribute *attr, char *buf)
627 {
628         struct fb_info *fbi = dev_get_drvdata(dev);
629
630         return snprintf(buf, PAGE_SIZE, "0x%p-----0x%x\n",
631                         fbi->screen_base, fbi->fix.smem_len);
632 }
633
634 static ssize_t show_fb_state(struct device *dev,
635                              struct device_attribute *attr, char *buf)
636 {
637         struct fb_info *fbi = dev_get_drvdata(dev);
638         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
639         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
640
641         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
642         int state = dev_drv->ops->get_win_state(dev_drv, win_id, 0);
643
644         return snprintf(buf, PAGE_SIZE, "%s\n", state ? "enabled" : "disabled");
645 }
646
647 static ssize_t show_dual_mode(struct device *dev,
648                               struct device_attribute *attr, char *buf)
649 {
650         struct fb_info *fbi = dev_get_drvdata(dev);
651         struct rk_fb *rk_fb = dev_get_drvdata(fbi->device);
652         int mode = rk_fb->disp_mode;
653
654         return snprintf(buf, PAGE_SIZE, "%d\n", mode);
655 }
656
657 static ssize_t set_fb_state(struct device *dev, struct device_attribute *attr,
658                             const char *buf, size_t count)
659 {
660         struct fb_info *fbi = dev_get_drvdata(dev);
661         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
662         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
663         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
664         int state;
665         int ret;
666
667         ret = kstrtoint(buf, 0, &state);
668         if (ret)
669                 return ret;
670         dev_drv->ops->open(dev_drv, win_id, state);
671         if (state) {
672                 dev_drv->ops->set_par(dev_drv, win_id);
673                 dev_drv->ops->pan_display(dev_drv, win_id);
674                 dev_drv->ops->cfg_done(dev_drv);
675         }
676         return count;
677 }
678
679 static ssize_t show_overlay(struct device *dev,
680                             struct device_attribute *attr, char *buf)
681 {
682         struct fb_info *fbi = dev_get_drvdata(dev);
683         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
684         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
685         int ovl;
686
687         if (dev_drv->ops->ovl_mgr)
688                 ovl = dev_drv->ops->ovl_mgr(dev_drv, 0, 0);
689
690         if (ovl < 0)
691                 return ovl;
692
693         return snprintf(buf, PAGE_SIZE, "%s\n",
694                         ovl ? "win0 on the top of win1" :
695                         "win1 on the top of win0");
696 }
697
698 static ssize_t set_overlay(struct device *dev, struct device_attribute *attr,
699                            const char *buf, size_t count)
700 {
701         struct fb_info *fbi = dev_get_drvdata(dev);
702         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
703         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
704         u32 ovl;
705         int ret;
706
707         ret = kstrtou32(buf, 0, &ovl);
708         if (ret)
709                 return ret;
710         if (dev_drv->ops->ovl_mgr)
711                 ret = dev_drv->ops->ovl_mgr(dev_drv, ovl, 1);
712         if (ret < 0)
713                 return ret;
714
715         return count;
716 }
717
718 static ssize_t show_fps(struct device *dev,
719                         struct device_attribute *attr, char *buf)
720 {
721         struct fb_info *fbi = dev_get_drvdata(dev);
722         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
723         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
724         int fps;
725
726         if (dev_drv->ops->fps_mgr)
727                 fps = dev_drv->ops->fps_mgr(dev_drv, 0, 0);
728         if (fps < 0)
729                 return fps;
730
731         return snprintf(buf, PAGE_SIZE, "fps:%d\n", fps);
732 }
733
734 static ssize_t set_fps(struct device *dev, struct device_attribute *attr,
735                        const char *buf, size_t count)
736 {
737         struct fb_info *fbi = dev_get_drvdata(dev);
738         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
739         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
740         u32 fps;
741         int ret;
742
743         ret = kstrtou32(buf, 0, &fps);
744         if (ret)
745                 return ret;
746
747         if (fps == 0 || fps > 60) {
748                 dev_info(dev, "unsupport fps value,pelase set 1~60\n");
749                 return count;
750         }
751
752         if (dev_drv->ops->fps_mgr)
753                 ret = dev_drv->ops->fps_mgr(dev_drv, fps, 1);
754         if (ret < 0)
755                 return ret;
756
757         return count;
758 }
759
760 static ssize_t show_fb_win_map(struct device *dev,
761                                struct device_attribute *attr, char *buf)
762 {
763         int ret;
764         struct fb_info *fbi = dev_get_drvdata(dev);
765         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
766         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
767
768         mutex_lock(&dev_drv->fb_win_id_mutex);
769         ret =
770             snprintf(buf, PAGE_SIZE, "fb0:win%d\nfb1:win%d\nfb2:win%d\n",
771                      dev_drv->fb0_win_id, dev_drv->fb1_win_id,
772                      dev_drv->fb2_win_id);
773         mutex_unlock(&dev_drv->fb_win_id_mutex);
774
775         return ret;
776 }
777
778 static ssize_t set_fb_win_map(struct device *dev, struct device_attribute *attr,
779                               const char *buf, size_t count)
780 {
781         struct fb_info *fbi = dev_get_drvdata(dev);
782         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
783         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
784         u32 order;
785         int ret;
786
787         ret = kstrtou32(buf, 0, &order);
788         if ((order != FB0_WIN2_FB1_WIN1_FB2_WIN0) &&
789             (order != FB0_WIN1_FB1_WIN2_FB2_WIN0) &&
790             (order != FB0_WIN2_FB1_WIN0_FB2_WIN1) &&
791             (order != FB0_WIN0_FB1_WIN2_FB2_WIN1) &&
792             (order != FB0_WIN0_FB1_WIN1_FB2_WIN2) &&
793             (order != FB0_WIN1_FB1_WIN0_FB2_WIN2)) {
794                 dev_info(dev, "un supported map\n"
795                        "you can use the following order:\n" "201:\n"
796                        "fb0-win1\n" "fb1-win0\n" "fb2-win2\n" "210:\n"
797                        "fb0-win0\n" "fb1-win1\n" "fb2-win2\n" "120:\n"
798                        "fb0-win0\n" "fb1-win2\n" "fb2-win1\n" "102:\n"
799                        "fb0-win2\n" "fb1-win0\n" "fb2-win1\n" "021:\n"
800                        "fb0-win1\n" "fb1-win2\n" "fb2-win0\n" "012:\n"
801                        "fb0-win2\n" "fb1-win1\n" "fb2-win0\n");
802                 return count;
803         } else {
804                 if (dev_drv->ops->fb_win_remap)
805                         dev_drv->ops->fb_win_remap(dev_drv, order);
806         }
807
808         return count;
809 }
810
811 static ssize_t show_hwc_lut(struct device *dev,
812                             struct device_attribute *attr, char *buf)
813 {
814         return 0;
815 }
816
817 static ssize_t set_hwc_lut(struct device *dev, struct device_attribute *attr,
818                            const char *buf, size_t count)
819 {
820         int hwc_lut[256];
821         const char *start = buf;
822         int i = 256, temp;
823         int space_max;
824
825         struct fb_info *fbi = dev_get_drvdata(dev);
826         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
827         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
828
829         /*printk("count:%d\n>>%s\n\n",count,start);*/
830         for (i = 0; i < 256; i++) {
831                 space_max = 15; /*max space number 15*/
832                 temp = simple_strtoul(start, NULL, 16);
833                 hwc_lut[i] = temp;
834                 do {
835                         start++;
836                         space_max--;
837                 } while ((*start != ' ') && space_max);
838
839                 if (!space_max)
840                         break;
841                 else
842                         start++;
843         }
844 #if 0
845         for (i = 0; i < 16; i++) {
846                 for (j = 0; j < 16; j++)
847                         printk("0x%08x ", hwc_lut[i * 16 + j]);
848                 printk("\n");
849         }
850 #endif
851         if (dev_drv->ops->set_hwc_lut)
852                 dev_drv->ops->set_hwc_lut(dev_drv, hwc_lut, 1);
853
854         return count;
855 }
856
857 static ssize_t show_cabc_lut(struct device *dev,
858                              struct device_attribute *attr, char *buf)
859 {
860         return 0;
861 }
862
863 static ssize_t set_cabc_lut(struct device *dev, struct device_attribute *attr,
864                             const char *buf, size_t count)
865 {
866         int cabc_lut[256];
867         const char *start = buf;
868         int i = 256, temp;
869         int space_max = 10;
870
871         struct fb_info *fbi = dev_get_drvdata(dev);
872         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
873         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
874
875         for (i = 0; i < 256; i++) {
876                 temp = i;
877                 /*init by default value*/
878                 cabc_lut[i] = temp + (temp << 8) + (temp << 16);
879         }
880         for (i = 0; i < 256; i++) {
881                 space_max = 10; /*max space number 10*/
882                 temp = simple_strtoul(start, NULL, 10);
883                 cabc_lut[i] = temp;
884                 do {
885                         start++;
886                         space_max--;
887                 } while ((*start != ' ') && space_max);
888
889                 if (!space_max)
890                         break;
891                 else
892                         start++;
893         }
894         if (dev_drv->ops->set_cabc_lut)
895                 dev_drv->ops->set_cabc_lut(dev_drv, cabc_lut);
896
897         return count;
898 }
899
900 static ssize_t show_dsp_lut(struct device *dev,
901                             struct device_attribute *attr, char *buf)
902 {
903         return 0;
904 }
905
906 static ssize_t set_dsp_lut(struct device *dev, struct device_attribute *attr,
907                            const char *buf, size_t count)
908 {
909         int dsp_lut[256];
910         const char *start = buf;
911         int i = 256, temp;
912         int space_max = 10;
913
914         struct fb_info *fbi = dev_get_drvdata(dev);
915         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
916         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
917
918         for (i = 0; i < 256; i++) {
919                 temp = i;
920                 /*init by default value*/
921                 dsp_lut[i] = temp + (temp << 8) + (temp << 16);
922         }
923         /*printk("count:%d\n>>%s\n\n",count,start);*/
924         for (i = 0; i < 256; i++) {
925                 space_max = 10; /*max space number 10*/
926                 temp = simple_strtoul(start, NULL, 10);
927                 dsp_lut[i] = temp;
928                 do {
929                         start++;
930                         space_max--;
931                 } while ((*start != ' ') && space_max);
932
933                 if (!space_max)
934                         break;
935                 else
936                         start++;
937         }
938 #if 0
939         for (i = 0; i < 16; i++) {
940                 for (j = 0; j < 16; j++)
941                         printk("0x%08x ", dsp_lut[i * 16 + j]);
942                 printk("\n");
943         }
944 #endif
945         if (dev_drv->ops->set_dsp_lut)
946                 dev_drv->ops->set_dsp_lut(dev_drv, dsp_lut);
947
948         return count;
949 }
950
951 static ssize_t show_dsp_cabc(struct device *dev,
952                              struct device_attribute *attr, char *buf)
953 {
954         struct fb_info *fbi = dev_get_drvdata(dev);
955         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
956         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
957
958         return snprintf(buf, PAGE_SIZE, "cabc mode=%d\n",
959                 dev_drv->cabc_mode);
960         return 0;
961 }
962
963 static ssize_t set_dsp_cabc(struct device *dev, struct device_attribute *attr,
964                             const char *buf, size_t count)
965 {
966         struct fb_info *fbi = dev_get_drvdata(dev);
967         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
968         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
969         int space_max, ret, mode = 0, calc = 0,up = 0, down = 0, global = 0;
970         const char *start = buf;
971
972         space_max = 10; /*max space number 10*/
973         mode = simple_strtoul(start, NULL, 10);
974         do {
975                 start++;
976                 space_max--;
977         } while ((*start != ' ') && space_max);
978         start++;
979         calc = simple_strtoul(start, NULL, 10);
980
981         do {
982                 start++;
983                 space_max--;
984         } while ((*start != ' ') && space_max);
985         start++;
986         up  = simple_strtoul(start, NULL, 10);
987
988         do {
989                 start++;
990                 space_max--;
991         } while ((*start != ' ') && space_max);
992         start++;
993         down = simple_strtoul(start, NULL, 10);
994
995         do {
996                 start++;
997                 space_max--;
998         } while ((*start != ' ') && space_max);
999         start++;
1000         global = simple_strtoul(start, NULL, 10);
1001
1002     if (dev_drv->ops->set_dsp_cabc)
1003                 ret = dev_drv->ops->set_dsp_cabc(dev_drv, mode, calc, up, down, global);
1004         if (ret < 0)
1005                 return ret;
1006
1007         return count;
1008 }
1009
1010 static ssize_t show_dsp_bcsh(struct device *dev,
1011                              struct device_attribute *attr, char *buf)
1012 {
1013         struct fb_info *fbi = dev_get_drvdata(dev);
1014         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
1015         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
1016         int brightness, contrast, sat_con, sin_hue, cos_hue;
1017
1018         if (dev_drv->ops->get_dsp_bcsh_bcs) {
1019                 brightness = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv,
1020                                                             BRIGHTNESS);
1021                 contrast = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, CONTRAST);
1022                 sat_con = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, SAT_CON);
1023         }
1024         if (dev_drv->ops->get_dsp_bcsh_hue) {
1025                 sin_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv, H_SIN);
1026                 cos_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv, H_COS);
1027         }
1028         return snprintf(buf, PAGE_SIZE,
1029                         "brightness:%4d,contrast:%4d,sat_con:%4d,"
1030                         "sin_hue:%4d,cos_hue:%4d\n",
1031                         brightness, contrast, sat_con, sin_hue, cos_hue);
1032 }
1033
1034 static ssize_t set_dsp_bcsh(struct device *dev, struct device_attribute *attr,
1035                             const char *buf, size_t count)
1036 {
1037         struct fb_info *fbi = dev_get_drvdata(dev);
1038         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
1039         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
1040         int brightness, contrast, sat_con, ret = 0, sin_hue, cos_hue;
1041
1042         if (!strncmp(buf, "open", 4)) {
1043                 if (dev_drv->ops->open_bcsh)
1044                         ret = dev_drv->ops->open_bcsh(dev_drv, 1);
1045                 else
1046                         ret = -1;
1047         } else if (!strncmp(buf, "close", 5)) {
1048                 if (dev_drv->ops->open_bcsh)
1049                         ret = dev_drv->ops->open_bcsh(dev_drv, 0);
1050                 else
1051                         ret = -1;
1052         } else if (!strncmp(buf, "brightness", 10)) {
1053                 sscanf(buf, "brightness %d", &brightness);
1054                 if (unlikely(brightness > 255)) {
1055                         dev_err(fbi->dev,
1056                                 "brightness should be [0:255],now=%d\n\n",
1057                                 brightness);
1058                         brightness = 255;
1059                 }
1060                 if (dev_drv->ops->set_dsp_bcsh_bcs)
1061                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
1062                                                              BRIGHTNESS,
1063                                                              brightness);
1064                 else
1065                         ret = -1;
1066         } else if (!strncmp(buf, "contrast", 8)) {
1067                 sscanf(buf, "contrast %d", &contrast);
1068                 if (unlikely(contrast > 510)) {
1069                         dev_err(fbi->dev,
1070                                 "contrast should be [0:510],now=%d\n",
1071                                 contrast);
1072                         contrast = 510;
1073                 }
1074                 if (dev_drv->ops->set_dsp_bcsh_bcs)
1075                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
1076                                                              CONTRAST,
1077                                                              contrast);
1078                 else
1079                         ret = -1;
1080         } else if (!strncmp(buf, "sat_con", 7)) {
1081                 sscanf(buf, "sat_con %d", &sat_con);
1082                 if (unlikely(sat_con > 1015)) {
1083                         dev_err(fbi->dev,
1084                                 "sat_con should be [0:1015],now=%d\n",
1085                                 sat_con);
1086                         sat_con = 1015;
1087                 }
1088                 if (dev_drv->ops->set_dsp_bcsh_bcs)
1089                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
1090                                                              SAT_CON,
1091                                                              sat_con);
1092                 else
1093                         ret = -1;
1094         } else if (!strncmp(buf, "hue", 3)) {
1095                 sscanf(buf, "hue %d %d", &sin_hue, &cos_hue);
1096                 if (unlikely(sin_hue > 511 || cos_hue > 511)) {
1097                         dev_err(fbi->dev, "sin_hue=%d,cos_hue=%d\n",
1098                                 sin_hue, cos_hue);
1099                 }
1100                 if (dev_drv->ops->set_dsp_bcsh_hue)
1101                         ret = dev_drv->ops->set_dsp_bcsh_hue(dev_drv,
1102                                                              sin_hue,
1103                                                              cos_hue);
1104                 else
1105                         ret = -1;
1106         } else {
1107                 dev_info(dev, "format error\n");
1108         }
1109
1110         if (ret < 0)
1111                 return ret;
1112
1113         return count;
1114 }
1115
1116 static ssize_t show_scale(struct device *dev,
1117                           struct device_attribute *attr, char *buf)
1118 {
1119         struct fb_info *fbi = dev_get_drvdata(dev);
1120         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
1121         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
1122
1123         return snprintf(buf, PAGE_SIZE,
1124                 "xscale=%d yscale=%d\nleft=%d top=%d right=%d bottom=%d\n",
1125                 (dev_drv->overscan.left + dev_drv->overscan.right) / 2,
1126                 (dev_drv->overscan.top + dev_drv->overscan.bottom) / 2,
1127                 dev_drv->overscan.left, dev_drv->overscan.top,
1128                 dev_drv->overscan.right, dev_drv->overscan.bottom);
1129 }
1130
1131 static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
1132                          const char *buf, size_t count)
1133 {
1134         struct fb_info *fbi = dev_get_drvdata(dev);
1135         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
1136         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
1137         u32 left, top, right, bottom;
1138
1139         if (!strncmp(buf, "overscan", 8)) {
1140                 sscanf(buf,
1141                        "overscan %d,%d,%d,%d", &left, &top, &right, &bottom);
1142                 if (left > 0 && left <= 100)
1143                         dev_drv->overscan.left = left;
1144                 if (top > 0 && top <= 100)
1145                         dev_drv->overscan.top = top;
1146                 if (right > 0 && right <= 100)
1147                         dev_drv->overscan.right = right;
1148                 if (bottom > 0 && bottom <= 100)
1149                         dev_drv->overscan.bottom = bottom;
1150         } else if (!strncmp(buf, "left", 4)) {
1151                 sscanf(buf, "left=%d", &left);
1152                 if (left > 0 && left <= 100)
1153                         dev_drv->overscan.left = left;
1154         } else if (!strncmp(buf, "top", 3)) {
1155                 sscanf(buf, "top=%d", &top);
1156                 if (top > 0 && top <= 100)
1157                         dev_drv->overscan.top = top;
1158         } else if (!strncmp(buf, "right", 5)) {
1159                 sscanf(buf, "right=%d", &right);
1160                 if (right > 0 && right <= 100)
1161                         dev_drv->overscan.right = right;
1162         } else if (!strncmp(buf, "bottom", 6)) {
1163                 sscanf(buf, "bottom=%d", &bottom);
1164                 if (bottom > 0 && bottom <= 100)
1165                         dev_drv->overscan.bottom = bottom;
1166         } else if (!strncmp(buf, "xscale", 6)) {
1167                 sscanf(buf, "xscale=%d", &left);
1168                 if (left > 0 && left <= 100) {
1169                         dev_drv->overscan.left = left;
1170                         dev_drv->overscan.right = left;
1171                 }
1172         } else if (!strncmp(buf, "yscale", 6)) {
1173                 sscanf(buf, "yscale=%d", &left);
1174                 if (left > 0 && left <= 100) {
1175                         dev_drv->overscan.top = left;
1176                         dev_drv->overscan.bottom = left;
1177                 }
1178         } else {
1179                 sscanf(buf, "%d", &left);
1180                 if (left > 0 && left <= 100) {
1181                         dev_drv->overscan.left = left;
1182                         dev_drv->overscan.right = left;
1183                         dev_drv->overscan.top = left;
1184                         dev_drv->overscan.bottom = left;
1185                 }
1186         }
1187
1188         if (dev_drv->ops->set_overscan)
1189                 dev_drv->ops->set_overscan(dev_drv, &dev_drv->overscan);
1190
1191         return count;
1192 }
1193
1194 static ssize_t show_lcdc_id(struct device *dev,
1195                             struct device_attribute *attr,
1196                             char *buf)
1197 {
1198         struct fb_info *fbi = dev_get_drvdata(dev);
1199         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
1200         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
1201
1202         return snprintf(buf, PAGE_SIZE, "%d\n", dev_drv->id);
1203 }
1204
1205 static struct device_attribute rkfb_attrs[] = {
1206         __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
1207         __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
1208         __ATTR(disp_info, S_IRUGO, show_disp_info, NULL),
1209         __ATTR(dump_buf, S_IRUGO | S_IWUSR, show_dump_buffer, set_dump_buffer),
1210         __ATTR(dsp_buf, S_IRUGO | S_IWUSR, show_dsp_buffer, set_dsp_buffer),
1211         __ATTR(screen_info, S_IRUGO, show_screen_info, NULL),
1212         __ATTR(dual_mode, S_IRUGO, show_dual_mode, NULL),
1213         __ATTR(enable, S_IRUGO | S_IWUSR, show_fb_state, set_fb_state),
1214         __ATTR(overlay, S_IRUGO | S_IWUSR, show_overlay, set_overlay),
1215         __ATTR(fps, S_IRUGO | S_IWUSR, show_fps, set_fps),
1216         __ATTR(map, S_IRUGO | S_IWUSR, show_fb_win_map, set_fb_win_map),
1217         __ATTR(dsp_lut, S_IRUGO | S_IWUSR, show_dsp_lut, set_dsp_lut),
1218         __ATTR(cabc_lut, S_IRUGO | S_IWUSR, show_cabc_lut, set_cabc_lut),
1219         __ATTR(hwc_lut, S_IRUGO | S_IWUSR, show_hwc_lut, set_hwc_lut),
1220         __ATTR(cabc, S_IRUGO | S_IWUSR, show_dsp_cabc, set_dsp_cabc),
1221         __ATTR(bcsh, S_IRUGO | S_IWUSR, show_dsp_bcsh, set_dsp_bcsh),
1222         __ATTR(scale, S_IRUGO | S_IWUSR, show_scale, set_scale),
1223         __ATTR(lcdcid, S_IRUGO, show_lcdc_id, NULL),
1224 };
1225
1226 int rkfb_create_sysfs(struct fb_info *fbi)
1227 {
1228         int r, t;
1229
1230         for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++) {
1231                 r = device_create_file(fbi->dev, &rkfb_attrs[t]);
1232                 if (r) {
1233                         dev_err(fbi->dev, "failed to create sysfs " "file\n");
1234                         return r;
1235                 }
1236         }
1237
1238         return 0;
1239 }
1240
1241 void rkfb_remove_sysfs(struct rk_fb *rk_fb)
1242 {
1243         int i, t;
1244
1245         for (i = 0; i < rk_fb->num_fb; i++) {
1246                 for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++)
1247                         device_remove_file(rk_fb->fb[i]->dev, &rkfb_attrs[t]);
1248         }
1249 }