Merge branch develop-3.10-next
[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
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 int dump_win(struct ion_client *ion_client,
134                     struct ion_handle *ion_handle, phys_addr_t phys_addr,
135                     int width, int height, u8 data_format, uint32_t frameid,
136                     int win_id, int area_id, bool is_bmp, bool is_append)
137 {
138         void __iomem *vaddr = NULL;
139         struct file *filp;
140         mm_segment_t old_fs;
141         char name[100];
142         int flags;
143         int bits;
144
145         switch (data_format) {
146         case XRGB888:
147         case XBGR888:
148         case ARGB888:
149         case ABGR888:
150         case FBDC_RGBX_888:
151                 bits = 32;
152                 break;
153         case YUV444_A:
154         case YUV444:
155         case RGB888:
156         case FBDC_ARGB_888:
157                 bits = 24;
158                 break;
159         case RGB565:
160         case FBDC_RGB_565:
161         case YUV422:
162         case YUV422_A:
163                 bits = 16;
164                 break;
165         case YUV420_A:
166         case YUV420:
167         case YUV420_NV21:
168                 bits = 12;
169                 break;
170         default:
171                 return 0;
172         }
173
174         if (ion_handle) {
175                 vaddr = ion_map_kernel(ion_client, ion_handle);
176         } else if (phys_addr) {
177                 unsigned long start;
178                 unsigned int nr_pages;
179                 struct page **pages;
180                 int i = 0;
181
182                 start = phys_addr;
183                 nr_pages = roundup(width * height * (bits >> 3), PAGE_SIZE);
184                 nr_pages /= PAGE_SIZE;
185                 pages = kzalloc(sizeof(struct page) * nr_pages,GFP_KERNEL);
186                 while (i < nr_pages) {
187                         pages[i] = phys_to_page(start);
188                         start += PAGE_SIZE;
189                         i++;
190                 }
191                 vaddr = vmap(pages, nr_pages, VM_MAP,
192                              pgprot_writecombine(PAGE_KERNEL));
193                 if (!vaddr) {
194                         pr_err("failed to vmap phy addr %lx\n",
195                                start);
196                         return -1;
197                 }
198         } else {
199                 return 0;
200         }
201
202         flags = O_RDWR | O_CREAT | O_NONBLOCK;
203         if (is_append) {
204                 snprintf(name, 100, "%s/append_win%d_%d_%dx%d_%s.%s",
205                          DUMP_BUF_PATH, win_id, area_id, width, height,
206                          get_format_str(data_format), is_bmp ? "bmp" : "bin");
207                 flags |= O_APPEND;
208         } else {
209                 snprintf(name, 100, "%s/frame%d_win%d_%d_%dx%d_%s.%s",
210                          DUMP_BUF_PATH, frameid, win_id, area_id, width, height,
211                          get_format_str(data_format), is_bmp ? "bmp" : "bin");
212         }
213
214         pr_info("dump win == > %s\n", name);
215         filp = filp_open(name, flags, 0x600);
216         if (!filp)
217                 printk("fail to create %s\n", name);
218
219         old_fs = get_fs();
220         set_fs(KERNEL_DS);
221
222         if (is_bmp)
223                 bmpencoder(vaddr, width, height,
224                            data_format, filp, fill_buffer);
225         else
226                 fill_buffer(filp, vaddr, width * height * bits >> 3);
227
228         set_fs(old_fs);
229
230         if (ion_handle)
231                 ion_unmap_kernel(ion_client, ion_handle);
232         else if (vaddr)
233                 vunmap(vaddr);
234
235         filp_close(filp, NULL);
236
237         return 0;
238 }
239
240 static ssize_t show_dump_buffer(struct device *dev,
241                               struct device_attribute *attr, char *buf)
242 {
243         ssize_t size;
244
245         size = snprintf(buf, PAGE_SIZE,
246                         "bmp       -- dump buffer to bmp image\n"
247                         "bin       -- dump buffer to bin image\n"
248                         "multi    --  each dump will create new file\n"
249                         "win=num   -- mask win to dump, default mask all\n"
250                         "             win=1, will dump win1 buffer\n"
251                         "             win=23, will dump win2 area3 buffer\n"
252                         "trace=num -- trace num frames buffer dump\n"
253                         "             this option will block buffer switch\n"
254                         "             so recommend use with bin and win=xx\n"
255                         "\nExample:\n"
256                         "echo bmp > dump_buf; -- dump current buf to bmp file\n"
257                         "echo bin > dump_buf; -- dump current buf to bin file\n"
258                         "echo trace=50:win=1:win=23 > dump_buf\n"
259                         "         -- dump 50 frames, dump win1 and win2 area3\n"
260                         "         -- dump all buffer to single file\n"
261                         "You can found dump files at %s\n"
262                         , DUMP_BUF_PATH);
263
264         return size;
265 }
266
267 void trace_buffer_dump(struct device *dev, struct rk_lcdc_driver *dev_drv)
268 {
269         struct rk_fb *rk_fb = dev_get_drvdata(dev);
270         struct rk_fb_reg_data *front_regs;
271         struct rk_fb_reg_win_data *win_data;
272         struct rk_fb_reg_area_data *area_data;
273         struct rkfb_sys_trace *trace = dev_drv->trace_buf;
274         int i,j;
275
276         if (!trace)
277                 return;
278         if (trace->num_frames <= trace->count_frame)
279                 return;
280
281         if (!dev_drv->front_regs)
282                 return;
283         front_regs = dev_drv->front_regs;
284
285         for (i = 0; i < front_regs->win_num; i++) {
286                 if (trace->mask_win && !(trace->mask_win & (1 << i)))
287                         continue;
288                 for (j = 0; j < RK_WIN_MAX_AREA; j++) {
289                         win_data = &front_regs->reg_win_data[i];
290                         area_data = &win_data->reg_area_data[j];
291                         if (trace->mask_area && !(trace->mask_area & (1 << j)))
292                                 continue;
293
294                         dump_win(rk_fb->ion_client, area_data->ion_handle,
295                                  area_data->smem_start,
296                                  area_data->xvir, area_data->yvir,
297                                  area_data->data_format, trace->count_frame,
298                                  i, j, trace->is_bmp, trace->is_append);
299                 }
300         }
301         trace->count_frame++;
302 }
303
304 static ssize_t set_dump_buffer(struct device *dev,
305                                struct device_attribute *attr,
306                                const char *buf, size_t count)
307 {
308         struct fb_info *fbi = dev_get_drvdata(dev);
309         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
310         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
311         struct rk_fb *rk_fb = dev_get_drvdata(fbi->device);
312         struct rk_fb_reg_data *front_regs;
313         struct rk_fb_reg_win_data *win_data;
314         struct rk_fb_reg_area_data *area_data;
315         struct rkfb_sys_trace *trace;
316         struct dentry *dentry;
317         struct path path;
318         int err = 0;
319         int num_frames = 0;
320         int mask_win = 0;
321         int mask_area = 0;
322         bool is_bmp = false;
323         bool is_append = true;
324         char *p;
325         int i, j;
326
327         if (!rk_fb->ion_client)
328                 return 0;
329
330         if (!dev_drv->trace_buf) {
331                 dev_drv->trace_buf = devm_kmalloc(dev_drv->dev,
332                                                   sizeof(struct rkfb_sys_trace),
333                                                   GFP_KERNEL);
334                 if (!dev_drv->trace_buf)
335                         return -ENOMEM;
336         }
337         trace = dev_drv->trace_buf;
338         /*
339          * Stop buffer trace.
340          */
341         trace->num_frames = 0;
342
343         while ((p = strsep((char **)&buf, ":")) != NULL) {
344                 if (!*p)
345                         continue;
346                 if (!strncmp(p, "trace=", 6)) {
347                         if (kstrtoint(p + 6, 0, &num_frames))
348                                 dev_err(dev, "can't found trace frames\n");
349                         continue;
350                 }
351                 if (!strncmp(p, "win=", 4)) {
352                         int win;
353
354                         if (kstrtoint(p + 4, 0, &win))
355                                 dev_err(dev, "can't found trace frames\n");
356                         if (win < 10)
357                                mask_win |= 1 << win;
358                         else {
359                                 mask_win |= 1 << (win / 10);
360                                 mask_area |= 1 << (win % 10);
361                         }
362
363                         continue;
364                 }
365                 if (!strncmp(p, "bmp", 3)) {
366                         is_bmp = true;
367                         is_append = false;
368                         continue;
369                 }
370                 if (!strncmp(p, "bin", 3)) {
371                         is_bmp = false;
372                         continue;
373                 }
374                 if (!strncmp(p, "multi", 5)) {
375                         is_append = true;
376                         is_bmp = false;
377                         continue;
378                 }
379
380                 dev_err(dev, "unknown option %s\n", p);
381         }
382
383         dentry = kern_path_create(AT_FDCWD, DUMP_BUF_PATH, &path,
384                                   LOOKUP_DIRECTORY);
385         if (!IS_ERR(dentry)) {
386                 err = vfs_mkdir(path.dentry->d_inode, dentry, 700);
387                 if (err)
388                         dev_err(dev, "can't create %s err%d\n",
389                                 DUMP_BUF_PATH, err);
390                 done_path_create(&path, dentry);
391         } else if (PTR_ERR(dentry) != -EEXIST) {
392                 dev_err(dev, "can't create PATH %s err%d\n",
393                                 DUMP_BUF_PATH, err);
394                 return PTR_ERR(dentry);
395         }
396
397         if (!num_frames) {
398                 mutex_lock(&dev_drv->front_lock);
399
400                 if (!dev_drv->front_regs) {
401                         u16 xact, yact;
402                         int data_format;
403                         u32 dsp_addr;
404
405                         mutex_unlock(&dev_drv->front_lock);
406
407                         if (dev_drv->ops->get_dspbuf_info)
408                                 dev_drv->ops->get_dspbuf_info(dev_drv, &xact,
409                                                 &yact, &data_format, &dsp_addr);
410
411                         dump_win(NULL, NULL, dsp_addr, xact, yact, data_format,
412                                  0, 0, 0, is_bmp, false);
413                         goto out;
414                 }
415                 front_regs = kmalloc(sizeof(*front_regs), GFP_KERNEL);
416                 if (!front_regs)
417                         return -ENOMEM;
418                 memcpy(front_regs, dev_drv->front_regs, sizeof(*front_regs));
419
420                 for (i = 0; i < front_regs->win_num; i++) {
421                         if (mask_win && !(mask_win & (1 << i)))
422                                 continue;
423                         for (j = 0; j < RK_WIN_MAX_AREA; j++) {
424                                 if (mask_area && !(mask_area & (1 << j)))
425                                         continue;
426                                 win_data = &front_regs->reg_win_data[i];
427                                 area_data = &win_data->reg_area_data[j];
428                                 if (area_data->ion_handle)
429                                         ion_handle_get(area_data->ion_handle);
430                         }
431                 }
432
433                 for (i = 0; i < front_regs->win_num; i++) {
434                         if (mask_win && !(mask_win & (1 << i)))
435                                 continue;
436                         for (j = 0; j < RK_WIN_MAX_AREA; j++) {
437                                 if (mask_area && !(mask_area & (1 << j)))
438                                         continue;
439
440                                 win_data = &front_regs->reg_win_data[i];
441                                 area_data = &win_data->reg_area_data[j];
442
443                                 dump_win(rk_fb->ion_client, area_data->ion_handle,
444                                          area_data->smem_start,
445                                          area_data->xvir, area_data->yvir,
446                                          area_data->data_format, trace->count_frame,
447                                          i, j, trace->is_bmp, trace->is_append);
448                                 if (area_data->ion_handle)
449                                         ion_handle_put(area_data->ion_handle);
450                         }
451                 }
452
453                 kfree(front_regs);
454
455                 mutex_unlock(&dev_drv->front_lock);
456         } else {
457                 trace->num_frames = num_frames;
458                 trace->count_frame = 0;
459                 trace->is_bmp = is_bmp;
460                 trace->is_append = is_append;
461                 trace->mask_win = mask_win;
462                 trace->mask_area = mask_area;
463         }
464 out:
465
466         return count;
467 }
468
469 static ssize_t show_phys(struct device *dev,
470                          struct device_attribute *attr, char *buf)
471 {
472         struct fb_info *fbi = dev_get_drvdata(dev);
473
474         return snprintf(buf, PAGE_SIZE, "0x%lx-----0x%x\n",
475                         fbi->fix.smem_start, fbi->fix.smem_len);
476 }
477
478 static ssize_t show_virt(struct device *dev,
479                          struct device_attribute *attr, char *buf)
480 {
481         struct fb_info *fbi = dev_get_drvdata(dev);
482
483         return snprintf(buf, PAGE_SIZE, "0x%p-----0x%x\n",
484                         fbi->screen_base, fbi->fix.smem_len);
485 }
486
487 static ssize_t show_fb_state(struct device *dev,
488                              struct device_attribute *attr, char *buf)
489 {
490         struct fb_info *fbi = dev_get_drvdata(dev);
491         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
492         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
493
494         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
495         int state = dev_drv->ops->get_win_state(dev_drv, win_id, 0);
496
497         return snprintf(buf, PAGE_SIZE, "%s\n", state ? "enabled" : "disabled");
498 }
499
500 static ssize_t show_dual_mode(struct device *dev,
501                               struct device_attribute *attr, char *buf)
502 {
503         struct fb_info *fbi = dev_get_drvdata(dev);
504         struct rk_fb *rk_fb = dev_get_drvdata(fbi->device);
505         int mode = rk_fb->disp_mode;
506
507         return snprintf(buf, PAGE_SIZE, "%d\n", mode);
508 }
509
510 static ssize_t set_fb_state(struct device *dev, struct device_attribute *attr,
511                             const char *buf, size_t count)
512 {
513         struct fb_info *fbi = dev_get_drvdata(dev);
514         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
515         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
516         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
517         int state;
518         int ret;
519
520         ret = kstrtoint(buf, 0, &state);
521         if (ret)
522                 return ret;
523         dev_drv->ops->open(dev_drv, win_id, state);
524         if (state) {
525                 dev_drv->ops->set_par(dev_drv, win_id);
526                 dev_drv->ops->pan_display(dev_drv, win_id);
527                 dev_drv->ops->cfg_done(dev_drv);
528         }
529         return count;
530 }
531
532 static ssize_t show_overlay(struct device *dev,
533                             struct device_attribute *attr, char *buf)
534 {
535         struct fb_info *fbi = dev_get_drvdata(dev);
536         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
537         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
538         int ovl;
539
540         if (dev_drv->ops->ovl_mgr)
541                 ovl = dev_drv->ops->ovl_mgr(dev_drv, 0, 0);
542
543         if (ovl < 0)
544                 return ovl;
545
546         return snprintf(buf, PAGE_SIZE, "%s\n",
547                         ovl ? "win0 on the top of win1" :
548                         "win1 on the top of win0");
549 }
550
551 static ssize_t set_overlay(struct device *dev, struct device_attribute *attr,
552                            const char *buf, size_t count)
553 {
554         struct fb_info *fbi = dev_get_drvdata(dev);
555         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
556         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
557         u32 ovl;
558         int ret;
559
560         ret = kstrtou32(buf, 0, &ovl);
561         if (ret)
562                 return ret;
563         if (dev_drv->ops->ovl_mgr)
564                 ret = dev_drv->ops->ovl_mgr(dev_drv, ovl, 1);
565         if (ret < 0)
566                 return ret;
567
568         return count;
569 }
570
571 static ssize_t show_fps(struct device *dev,
572                         struct device_attribute *attr, char *buf)
573 {
574         struct fb_info *fbi = dev_get_drvdata(dev);
575         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
576         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
577         int fps;
578
579         if (dev_drv->ops->fps_mgr)
580                 fps = dev_drv->ops->fps_mgr(dev_drv, 0, 0);
581         if (fps < 0)
582                 return fps;
583
584         return snprintf(buf, PAGE_SIZE, "fps:%d\n", fps);
585 }
586
587 static ssize_t set_fps(struct device *dev, struct device_attribute *attr,
588                        const char *buf, size_t count)
589 {
590         struct fb_info *fbi = dev_get_drvdata(dev);
591         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
592         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
593         u32 fps;
594         int ret;
595
596         ret = kstrtou32(buf, 0, &fps);
597         if (ret)
598                 return ret;
599
600         if (fps == 0 || fps > 60) {
601                 dev_info(dev, "unsupport fps value,pelase set 1~60\n");
602                 return count;
603         }
604
605         if (dev_drv->ops->fps_mgr)
606                 ret = dev_drv->ops->fps_mgr(dev_drv, fps, 1);
607         if (ret < 0)
608                 return ret;
609
610         return count;
611 }
612
613 static ssize_t show_fb_win_map(struct device *dev,
614                                struct device_attribute *attr, char *buf)
615 {
616         int ret;
617         struct fb_info *fbi = dev_get_drvdata(dev);
618         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
619         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
620
621         mutex_lock(&dev_drv->fb_win_id_mutex);
622         ret =
623             snprintf(buf, PAGE_SIZE, "fb0:win%d\nfb1:win%d\nfb2:win%d\n",
624                      dev_drv->fb0_win_id, dev_drv->fb1_win_id,
625                      dev_drv->fb2_win_id);
626         mutex_unlock(&dev_drv->fb_win_id_mutex);
627
628         return ret;
629 }
630
631 static ssize_t set_fb_win_map(struct device *dev, struct device_attribute *attr,
632                               const char *buf, size_t count)
633 {
634         struct fb_info *fbi = dev_get_drvdata(dev);
635         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
636         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
637         u32 order;
638         int ret;
639
640         ret = kstrtou32(buf, 0, &order);
641         if ((order != FB0_WIN2_FB1_WIN1_FB2_WIN0) &&
642             (order != FB0_WIN1_FB1_WIN2_FB2_WIN0) &&
643             (order != FB0_WIN2_FB1_WIN0_FB2_WIN1) &&
644             (order != FB0_WIN0_FB1_WIN2_FB2_WIN1) &&
645             (order != FB0_WIN0_FB1_WIN1_FB2_WIN2) &&
646             (order != FB0_WIN1_FB1_WIN0_FB2_WIN2)) {
647                 dev_info(dev, "un supported map\n"
648                        "you can use the following order:\n" "201:\n"
649                        "fb0-win1\n" "fb1-win0\n" "fb2-win2\n" "210:\n"
650                        "fb0-win0\n" "fb1-win1\n" "fb2-win2\n" "120:\n"
651                        "fb0-win0\n" "fb1-win2\n" "fb2-win1\n" "102:\n"
652                        "fb0-win2\n" "fb1-win0\n" "fb2-win1\n" "021:\n"
653                        "fb0-win1\n" "fb1-win2\n" "fb2-win0\n" "012:\n"
654                        "fb0-win2\n" "fb1-win1\n" "fb2-win0\n");
655                 return count;
656         } else {
657                 if (dev_drv->ops->fb_win_remap)
658                         dev_drv->ops->fb_win_remap(dev_drv, order);
659         }
660
661         return count;
662 }
663
664 static ssize_t show_hwc_lut(struct device *dev,
665                             struct device_attribute *attr, char *buf)
666 {
667         return 0;
668 }
669
670 static ssize_t set_hwc_lut(struct device *dev, struct device_attribute *attr,
671                            const char *buf, size_t count)
672 {
673         int hwc_lut[256];
674         const char *start = buf;
675         int i = 256, temp;
676         int space_max;
677
678         struct fb_info *fbi = dev_get_drvdata(dev);
679         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
680         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
681
682         /*printk("count:%d\n>>%s\n\n",count,start);*/
683         for (i = 0; i < 256; i++) {
684                 space_max = 15; /*max space number 15*/
685                 temp = simple_strtoul(start, NULL, 16);
686                 hwc_lut[i] = temp;
687                 do {
688                         start++;
689                         space_max--;
690                 } while ((*start != ' ') && space_max);
691
692                 if (!space_max)
693                         break;
694                 else
695                         start++;
696         }
697 #if 0
698         for (i = 0; i < 16; i++) {
699                 for (j = 0; j < 16; j++)
700                         printk("0x%08x ", hwc_lut[i * 16 + j]);
701                 printk("\n");
702         }
703 #endif
704         if (dev_drv->ops->set_hwc_lut)
705                 dev_drv->ops->set_hwc_lut(dev_drv, hwc_lut, 1);
706
707         return count;
708 }
709
710 static ssize_t show_cabc_lut(struct device *dev,
711                              struct device_attribute *attr, char *buf)
712 {
713         return 0;
714 }
715
716 static ssize_t set_cabc_lut(struct device *dev, struct device_attribute *attr,
717                             const char *buf, size_t count)
718 {
719         int cabc_lut[256];
720         const char *start = buf;
721         int i = 256, temp;
722         int space_max = 10;
723
724         struct fb_info *fbi = dev_get_drvdata(dev);
725         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
726         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
727
728         for (i = 0; i < 256; i++) {
729                 temp = i;
730                 /*init by default value*/
731                 cabc_lut[i] = temp + (temp << 8) + (temp << 16);
732         }
733         for (i = 0; i < 256; i++) {
734                 space_max = 10; /*max space number 10*/
735                 temp = simple_strtoul(start, NULL, 10);
736                 cabc_lut[i] = temp;
737                 do {
738                         start++;
739                         space_max--;
740                 } while ((*start != ' ') && space_max);
741
742                 if (!space_max)
743                         break;
744                 else
745                         start++;
746         }
747         if (dev_drv->ops->set_cabc_lut)
748                 dev_drv->ops->set_cabc_lut(dev_drv, cabc_lut);
749
750         return count;
751 }
752
753 static ssize_t show_dsp_lut(struct device *dev,
754                             struct device_attribute *attr, char *buf)
755 {
756         return 0;
757 }
758
759 static ssize_t set_dsp_lut(struct device *dev, struct device_attribute *attr,
760                            const char *buf, size_t count)
761 {
762         int dsp_lut[256];
763         const char *start = buf;
764         int i = 256, temp;
765         int space_max = 10;
766
767         struct fb_info *fbi = dev_get_drvdata(dev);
768         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
769         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
770
771         for (i = 0; i < 256; i++) {
772                 temp = i;
773                 /*init by default value*/
774                 dsp_lut[i] = temp + (temp << 8) + (temp << 16);
775         }
776         /*printk("count:%d\n>>%s\n\n",count,start);*/
777         for (i = 0; i < 256; i++) {
778                 space_max = 10; /*max space number 10*/
779                 temp = simple_strtoul(start, NULL, 10);
780                 dsp_lut[i] = temp;
781                 do {
782                         start++;
783                         space_max--;
784                 } while ((*start != ' ') && space_max);
785
786                 if (!space_max)
787                         break;
788                 else
789                         start++;
790         }
791 #if 0
792         for (i = 0; i < 16; i++) {
793                 for (j = 0; j < 16; j++)
794                         printk("0x%08x ", dsp_lut[i * 16 + j]);
795                 printk("\n");
796         }
797 #endif
798         if (dev_drv->ops->set_dsp_lut)
799                 dev_drv->ops->set_dsp_lut(dev_drv, dsp_lut);
800
801         return count;
802 }
803
804 static ssize_t show_dsp_cabc(struct device *dev,
805                              struct device_attribute *attr, char *buf)
806 {
807         struct fb_info *fbi = dev_get_drvdata(dev);
808         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
809         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
810
811         return snprintf(buf, PAGE_SIZE, "cabc mode=%d\n",
812                 dev_drv->cabc_mode);
813         return 0;
814 }
815
816 static ssize_t set_dsp_cabc(struct device *dev, struct device_attribute *attr,
817                             const char *buf, size_t count)
818 {
819         struct fb_info *fbi = dev_get_drvdata(dev);
820         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
821         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
822         int space_max, ret, mode = 0, calc = 0,up = 0, down = 0, global = 0;
823         const char *start = buf;
824
825         space_max = 10; /*max space number 10*/
826         mode = simple_strtoul(start, NULL, 10);
827         do {
828                 start++;
829                 space_max--;
830         } while ((*start != ' ') && space_max);
831         start++;
832         calc = simple_strtoul(start, NULL, 10);
833
834         do {
835                 start++;
836                 space_max--;
837         } while ((*start != ' ') && space_max);
838         start++;
839         up  = simple_strtoul(start, NULL, 10);
840
841         do {
842                 start++;
843                 space_max--;
844         } while ((*start != ' ') && space_max);
845         start++;
846         down = simple_strtoul(start, NULL, 10);
847
848         do {
849                 start++;
850                 space_max--;
851         } while ((*start != ' ') && space_max);
852         start++;
853         global = simple_strtoul(start, NULL, 10);
854
855     if (dev_drv->ops->set_dsp_cabc)
856                 ret = dev_drv->ops->set_dsp_cabc(dev_drv, mode, calc, up, down, global);
857         if (ret < 0)
858                 return ret;
859
860         return count;
861 }
862
863 static ssize_t show_dsp_bcsh(struct device *dev,
864                              struct device_attribute *attr, char *buf)
865 {
866         struct fb_info *fbi = dev_get_drvdata(dev);
867         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
868         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
869         int brightness, contrast, sat_con, sin_hue, cos_hue;
870
871         if (dev_drv->ops->get_dsp_bcsh_bcs) {
872                 brightness = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv,
873                                                             BRIGHTNESS);
874                 contrast = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, CONTRAST);
875                 sat_con = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, SAT_CON);
876         }
877         if (dev_drv->ops->get_dsp_bcsh_hue) {
878                 sin_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv, H_SIN);
879                 cos_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv, H_COS);
880         }
881         return snprintf(buf, PAGE_SIZE,
882                         "brightness:%4d,contrast:%4d,sat_con:%4d,"
883                         "sin_hue:%4d,cos_hue:%4d\n",
884                         brightness, contrast, sat_con, sin_hue, cos_hue);
885 }
886
887 static ssize_t set_dsp_bcsh(struct device *dev, struct device_attribute *attr,
888                             const char *buf, size_t count)
889 {
890         struct fb_info *fbi = dev_get_drvdata(dev);
891         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
892         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
893         int brightness, contrast, sat_con, ret = 0, sin_hue, cos_hue;
894
895         if (!strncmp(buf, "open", 4)) {
896                 if (dev_drv->ops->open_bcsh)
897                         ret = dev_drv->ops->open_bcsh(dev_drv, 1);
898                 else
899                         ret = -1;
900         } else if (!strncmp(buf, "close", 5)) {
901                 if (dev_drv->ops->open_bcsh)
902                         ret = dev_drv->ops->open_bcsh(dev_drv, 0);
903                 else
904                         ret = -1;
905         } else if (!strncmp(buf, "brightness", 10)) {
906                 sscanf(buf, "brightness %d", &brightness);
907                 if (unlikely(brightness > 255)) {
908                         dev_err(fbi->dev,
909                                 "brightness should be [0:255],now=%d\n\n",
910                                 brightness);
911                         brightness = 255;
912                 }
913                 if (dev_drv->ops->set_dsp_bcsh_bcs)
914                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
915                                                              BRIGHTNESS,
916                                                              brightness);
917                 else
918                         ret = -1;
919         } else if (!strncmp(buf, "contrast", 8)) {
920                 sscanf(buf, "contrast %d", &contrast);
921                 if (unlikely(contrast > 510)) {
922                         dev_err(fbi->dev,
923                                 "contrast should be [0:510],now=%d\n",
924                                 contrast);
925                         contrast = 510;
926                 }
927                 if (dev_drv->ops->set_dsp_bcsh_bcs)
928                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
929                                                              CONTRAST,
930                                                              contrast);
931                 else
932                         ret = -1;
933         } else if (!strncmp(buf, "sat_con", 7)) {
934                 sscanf(buf, "sat_con %d", &sat_con);
935                 if (unlikely(sat_con > 1015)) {
936                         dev_err(fbi->dev,
937                                 "sat_con should be [0:1015],now=%d\n",
938                                 sat_con);
939                         sat_con = 1015;
940                 }
941                 if (dev_drv->ops->set_dsp_bcsh_bcs)
942                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
943                                                              SAT_CON,
944                                                              sat_con);
945                 else
946                         ret = -1;
947         } else if (!strncmp(buf, "hue", 3)) {
948                 sscanf(buf, "hue %d %d", &sin_hue, &cos_hue);
949                 if (unlikely(sin_hue > 511 || cos_hue > 511)) {
950                         dev_err(fbi->dev, "sin_hue=%d,cos_hue=%d\n",
951                                 sin_hue, cos_hue);
952                 }
953                 if (dev_drv->ops->set_dsp_bcsh_hue)
954                         ret = dev_drv->ops->set_dsp_bcsh_hue(dev_drv,
955                                                              sin_hue,
956                                                              cos_hue);
957                 else
958                         ret = -1;
959         } else {
960                 dev_info(dev, "format error\n");
961         }
962
963         if (ret < 0)
964                 return ret;
965
966         return count;
967 }
968
969 static ssize_t show_scale(struct device *dev,
970                           struct device_attribute *attr, char *buf)
971 {
972         struct fb_info *fbi = dev_get_drvdata(dev);
973         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
974         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
975
976         return snprintf(buf, PAGE_SIZE,
977                 "xscale=%d yscale=%d\nleft=%d top=%d right=%d bottom=%d\n",
978                 (dev_drv->overscan.left + dev_drv->overscan.right) / 2,
979                 (dev_drv->overscan.top + dev_drv->overscan.bottom) / 2,
980                 dev_drv->overscan.left, dev_drv->overscan.top,
981                 dev_drv->overscan.right, dev_drv->overscan.bottom);
982 }
983
984 static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
985                          const char *buf, size_t count)
986 {
987         struct fb_info *fbi = dev_get_drvdata(dev);
988         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
989         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
990         u32 left, top, right, bottom;
991
992         if (!strncmp(buf, "overscan", 8)) {
993                 sscanf(buf,
994                        "overscan %d,%d,%d,%d", &left, &top, &right, &bottom);
995                 if (left > 0 && left <= 100)
996                         dev_drv->overscan.left = left;
997                 if (top > 0 && top <= 100)
998                         dev_drv->overscan.top = top;
999                 if (right > 0 && right <= 100)
1000                         dev_drv->overscan.right = right;
1001                 if (bottom > 0 && bottom <= 100)
1002                         dev_drv->overscan.bottom = bottom;
1003         } else if (!strncmp(buf, "left", 4)) {
1004                 sscanf(buf, "left=%d", &left);
1005                 if (left > 0 && left <= 100)
1006                         dev_drv->overscan.left = left;
1007         } else if (!strncmp(buf, "top", 3)) {
1008                 sscanf(buf, "top=%d", &top);
1009                 if (top > 0 && top <= 100)
1010                         dev_drv->overscan.top = top;
1011         } else if (!strncmp(buf, "right", 5)) {
1012                 sscanf(buf, "right=%d", &right);
1013                 if (right > 0 && right <= 100)
1014                         dev_drv->overscan.right = right;
1015         } else if (!strncmp(buf, "bottom", 6)) {
1016                 sscanf(buf, "bottom=%d", &bottom);
1017                 if (bottom > 0 && bottom <= 100)
1018                         dev_drv->overscan.bottom = bottom;
1019         } else if (!strncmp(buf, "xscale", 6)) {
1020                 sscanf(buf, "xscale=%d", &left);
1021                 if (left > 0 && left <= 100) {
1022                         dev_drv->overscan.left = left;
1023                         dev_drv->overscan.right = left;
1024                 }
1025         } else if (!strncmp(buf, "yscale", 6)) {
1026                 sscanf(buf, "yscale=%d", &left);
1027                 if (left > 0 && left <= 100) {
1028                         dev_drv->overscan.top = left;
1029                         dev_drv->overscan.bottom = left;
1030                 }
1031         } else {
1032                 sscanf(buf, "%d", &left);
1033                 if (left > 0 && left <= 100) {
1034                         dev_drv->overscan.left = left;
1035                         dev_drv->overscan.right = left;
1036                         dev_drv->overscan.top = left;
1037                         dev_drv->overscan.bottom = left;
1038                 }
1039         }
1040
1041         if (dev_drv->ops->set_overscan)
1042                 dev_drv->ops->set_overscan(dev_drv, &dev_drv->overscan);
1043
1044         return count;
1045 }
1046
1047 static struct device_attribute rkfb_attrs[] = {
1048         __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
1049         __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
1050         __ATTR(disp_info, S_IRUGO, show_disp_info, NULL),
1051         __ATTR(dump_buf, S_IRUGO | S_IWUSR, show_dump_buffer, set_dump_buffer),
1052         __ATTR(screen_info, S_IRUGO, show_screen_info, NULL),
1053         __ATTR(dual_mode, S_IRUGO, show_dual_mode, NULL),
1054         __ATTR(enable, S_IRUGO | S_IWUSR, show_fb_state, set_fb_state),
1055         __ATTR(overlay, S_IRUGO | S_IWUSR, show_overlay, set_overlay),
1056         __ATTR(fps, S_IRUGO | S_IWUSR, show_fps, set_fps),
1057         __ATTR(map, S_IRUGO | S_IWUSR, show_fb_win_map, set_fb_win_map),
1058         __ATTR(dsp_lut, S_IRUGO | S_IWUSR, show_dsp_lut, set_dsp_lut),
1059         __ATTR(cabc_lut, S_IRUGO | S_IWUSR, show_cabc_lut, set_cabc_lut),
1060         __ATTR(hwc_lut, S_IRUGO | S_IWUSR, show_hwc_lut, set_hwc_lut),
1061         __ATTR(cabc, S_IRUGO | S_IWUSR, show_dsp_cabc, set_dsp_cabc),
1062         __ATTR(bcsh, S_IRUGO | S_IWUSR, show_dsp_bcsh, set_dsp_bcsh),
1063         __ATTR(scale, S_IRUGO | S_IWUSR, show_scale, set_scale),
1064 };
1065
1066 int rkfb_create_sysfs(struct fb_info *fbi)
1067 {
1068         int r, t;
1069
1070         for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++) {
1071                 r = device_create_file(fbi->dev, &rkfb_attrs[t]);
1072                 if (r) {
1073                         dev_err(fbi->dev, "failed to create sysfs " "file\n");
1074                         return r;
1075                 }
1076         }
1077
1078         return 0;
1079 }
1080
1081 void rkfb_remove_sysfs(struct rk_fb *rk_fb)
1082 {
1083         int i, t;
1084
1085         for (i = 0; i < rk_fb->num_fb; i++) {
1086                 for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++)
1087                         device_remove_file(rk_fb->fb[i]->dev, &rkfb_attrs[t]);
1088         }
1089 }