rk fb: add support yuv420sp nv21 data format
[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/sysfs.h>
27 #include <linux/device.h>
28 #include <linux/uaccess.h>
29 #include <linux/platform_device.h>
30 #include <linux/kernel.h>
31 #include <linux/mm.h>
32 #include <linux/vmalloc.h>
33 #include <asm/div64.h>
34 #include <linux/rk_screen.h>
35 #include <linux/rk_fb.h>
36 #if defined(CONFIG_ION_ROCKCHIP)
37 #include <linux/rockchip_ion.h>
38 #endif
39 #include "bmp_helper.h"
40
41 static char *get_format_str(enum data_format format)
42 {
43         switch (format) {
44         case ARGB888:
45                 return "ARGB888";
46         case RGB888:
47                 return "RGB888";
48         case RGB565:
49                 return "RGB565";
50         case YUV420:
51         case YUV420_NV21:
52                 return "YUV420";
53         case YUV422:
54                 return "YUV422";
55         case YUV444:
56                 return "YUV444";
57         case YUV420_A:
58                 return "YUV420_A";
59         case YUV422_A:
60                 return "YUV422_A";
61         case YUV444_A:
62                 return "YUV444_A";
63         case XRGB888:
64                 return "XRGB888";
65         case XBGR888:
66                 return "XBGR888";
67         case ABGR888:
68                 return "ABGR888";
69         default:
70                 return "invalid";        
71         }
72 }
73
74 static ssize_t show_screen_info(struct device *dev,
75                                 struct device_attribute *attr, char *buf)
76 {
77         struct fb_info *fbi = dev_get_drvdata(dev);
78         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
79         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
80         struct rk_screen *screen = dev_drv->cur_screen;
81         int fps = 0;
82         u32 x = screen->mode.left_margin + screen->mode.right_margin +
83                 screen->mode.xres + screen->mode.hsync_len;
84         u32 y = screen->mode.upper_margin + screen->mode.lower_margin +
85                 screen->mode.yres + screen->mode.vsync_len;
86         u64 ft = (u64)x * y * (dev_drv->pixclock);
87
88         if (ft > 0)
89                 fps = div64_u64(1000000000000llu, ft);
90         return snprintf(buf, PAGE_SIZE, "xres:%d\nyres:%d\nfps:%d\n",
91                         screen->mode.xres, screen->mode.yres, fps);
92 }
93
94 static ssize_t show_disp_info(struct device *dev,
95                               struct device_attribute *attr, char *buf)
96 {
97         struct fb_info *fbi = dev_get_drvdata(dev);
98         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
99         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
100         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
101
102         if (dev_drv->ops->get_disp_info)
103                 return dev_drv->ops->get_disp_info(dev_drv, buf, win_id);
104
105         return 0;
106 }
107
108 static void fill_buffer(void *handle, void *vaddr, int size)
109 {
110         struct file *filp = handle;
111
112         if (filp)
113                 vfs_write(filp, vaddr, size, &filp->f_pos);
114 }
115
116 static int dump_win(struct rk_fb *rk_fb, struct rk_fb_reg_area_data *area_data,
117                     u8 data_format, int win_id, int area_id, bool is_bmp)
118 {
119         void __iomem *vaddr = NULL;
120         struct file *filp;
121         mm_segment_t old_fs;
122         char name[100];
123         struct ion_handle *ion_handle = area_data->ion_handle;
124         int width = area_data->xvir;
125         int height = area_data->yvir;
126
127         if (ion_handle) {
128                 vaddr = ion_map_kernel(rk_fb->ion_client, ion_handle);
129         } else if (area_data->smem_start && area_data->smem_start != -1) {
130                 unsigned long start;
131                 unsigned int nr_pages;
132                 struct page **pages;
133                 int i = 0;
134
135                 start = area_data->smem_start;
136                 nr_pages = width * height * 3 / 2 / PAGE_SIZE;
137                 pages = kzalloc(sizeof(struct page) * nr_pages,GFP_KERNEL);
138                 while (i < nr_pages) {
139                         pages[i] = phys_to_page(start);
140                         start += PAGE_SIZE;
141                         i++;
142                 }
143                 vaddr = vmap(pages, nr_pages, VM_MAP,
144                              pgprot_writecombine(PAGE_KERNEL));
145                 if (!vaddr) {
146                         pr_err("failed to vmap phy addr %lx\n",
147                                area_data->smem_start);
148                         return -1;
149                 }
150         } else {
151                 return -1;
152         }
153
154         snprintf(name, 100, "/data/win%d_%d_%dx%d_%s.%s", win_id, area_id,
155                  width, height, get_format_str(data_format),
156                  is_bmp ? "bmp" : "bin");
157
158         pr_info("dump win == > /data/win%d_%d_%dx%d_%s.%s\n", win_id, area_id,
159                 width, height, get_format_str(data_format),
160                 is_bmp ? "bmp" : "bin");
161
162         filp = filp_open(name, O_RDWR | O_CREAT, 0x664);
163         if (!filp)
164                 printk("fail to create %s\n", name);
165
166         old_fs = get_fs();
167         set_fs(KERNEL_DS);
168
169         if (is_bmp)
170                 bmpencoder(vaddr, width, height,
171                            data_format, filp, fill_buffer);
172         else
173                 fill_buffer(filp, vaddr, width * height * 4);
174
175         set_fs(old_fs);
176
177         if (ion_handle) {
178                 ion_unmap_kernel(rk_fb->ion_client, ion_handle);
179
180                 ion_handle_put(ion_handle);
181         } else if (vaddr) {
182                 vunmap(vaddr);
183         }
184
185         filp_close(filp, NULL);
186
187         return 0;
188 }
189
190 static ssize_t set_dump_info(struct device *dev, struct device_attribute *attr,
191                              const char *buf, size_t count)
192
193 {
194         struct fb_info *fbi = dev_get_drvdata(dev);
195         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
196         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
197         struct rk_fb *rk_fb = dev_get_drvdata(fbi->device);
198         struct rk_fb_reg_data *front_regs;
199         struct rk_fb_reg_win_data *win_data;
200         struct rk_fb_reg_area_data *area_data;
201         bool is_img;
202         int i, j;
203
204         if (!rk_fb->ion_client)
205                 return 0;
206
207         front_regs = kmalloc(sizeof(*front_regs), GFP_KERNEL);
208         if (!front_regs)
209                 return -ENOMEM;
210
211         mutex_lock(&dev_drv->front_lock);
212
213         if (!dev_drv->front_regs) {
214                 mutex_unlock(&dev_drv->front_lock);
215                 return 0;
216         }
217         memcpy(front_regs, dev_drv->front_regs, sizeof(*front_regs));
218         for (i = 0; i < front_regs->win_num; i++) {
219                 for (j = 0; j < RK_WIN_MAX_AREA; j++) {
220                         win_data = &front_regs->reg_win_data[i];
221                         area_data = &win_data->reg_area_data[j];
222                         if (area_data->ion_handle) {
223                                 ion_handle_get(area_data->ion_handle);
224                         }
225                 }
226         }
227         mutex_unlock(&dev_drv->front_lock);
228
229         if (strncmp(buf, "bin", 3))
230                 is_img = true;
231         else
232                 is_img = false;
233
234         for (i = 0; i < front_regs->win_num; i++) {
235                 for (j = 0; j < RK_WIN_MAX_AREA; j++) {
236                         win_data = &front_regs->reg_win_data[i];
237                         if (dump_win(rk_fb, &win_data->reg_area_data[j],
238                                      win_data->reg_area_data[i].data_format,i,
239                                      j, is_img))
240                                 continue;
241                 }
242         }
243         kfree(front_regs);
244
245         return count;
246 }
247
248 static ssize_t show_phys(struct device *dev,
249                          struct device_attribute *attr, char *buf)
250 {
251         struct fb_info *fbi = dev_get_drvdata(dev);
252
253         return snprintf(buf, PAGE_SIZE, "0x%lx-----0x%x\n",
254                         fbi->fix.smem_start, fbi->fix.smem_len);
255 }
256
257 static ssize_t show_virt(struct device *dev,
258                          struct device_attribute *attr, char *buf)
259 {
260         struct fb_info *fbi = dev_get_drvdata(dev);
261
262         return snprintf(buf, PAGE_SIZE, "0x%p-----0x%x\n",
263                         fbi->screen_base, fbi->fix.smem_len);
264 }
265
266 static ssize_t show_fb_state(struct device *dev,
267                              struct device_attribute *attr, char *buf)
268 {
269         struct fb_info *fbi = dev_get_drvdata(dev);
270         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
271         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
272
273         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
274         int state = dev_drv->ops->get_win_state(dev_drv, win_id);
275
276         return snprintf(buf, PAGE_SIZE, "%s\n", state ? "enabled" : "disabled");
277 }
278
279 static ssize_t show_dual_mode(struct device *dev,
280                               struct device_attribute *attr, char *buf)
281 {
282         struct fb_info *fbi = dev_get_drvdata(dev);
283         struct rk_fb *rk_fb = dev_get_drvdata(fbi->device);
284         int mode = rk_fb->disp_mode;
285
286         return snprintf(buf, PAGE_SIZE, "%d\n", mode);
287 }
288
289 static ssize_t set_fb_state(struct device *dev, struct device_attribute *attr,
290                             const char *buf, size_t count)
291 {
292         struct fb_info *fbi = dev_get_drvdata(dev);
293         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
294         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
295         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
296         int state;
297         int ret;
298
299         ret = kstrtoint(buf, 0, &state);
300         if (ret)
301                 return ret;
302         dev_drv->ops->open(dev_drv, win_id, state);
303         if (state) {
304                 dev_drv->ops->set_par(dev_drv, win_id);
305                 dev_drv->ops->pan_display(dev_drv, win_id);
306                 dev_drv->ops->cfg_done(dev_drv);
307         }
308         return count;
309 }
310
311 static ssize_t show_overlay(struct device *dev,
312                             struct device_attribute *attr, char *buf)
313 {
314         struct fb_info *fbi = dev_get_drvdata(dev);
315         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
316         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
317         int ovl;
318
319         if (dev_drv->ops->ovl_mgr)
320                 ovl = dev_drv->ops->ovl_mgr(dev_drv, 0, 0);
321
322         if (ovl < 0)
323                 return ovl;
324
325         return snprintf(buf, PAGE_SIZE, "%s\n",
326                         ovl ? "win0 on the top of win1" :
327                         "win1 on the top of win0");
328 }
329
330 static ssize_t set_overlay(struct device *dev, struct device_attribute *attr,
331                            const char *buf, size_t count)
332 {
333         struct fb_info *fbi = dev_get_drvdata(dev);
334         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
335         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
336         u32 ovl;
337         int ret;
338
339         ret = kstrtou32(buf, 0, &ovl);
340         if (ret)
341                 return ret;
342         if (dev_drv->ops->ovl_mgr)
343                 ret = dev_drv->ops->ovl_mgr(dev_drv, ovl, 1);
344         if (ret < 0)
345                 return ret;
346
347         return count;
348 }
349
350 static ssize_t show_fps(struct device *dev,
351                         struct device_attribute *attr, char *buf)
352 {
353         struct fb_info *fbi = dev_get_drvdata(dev);
354         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
355         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
356         int fps;
357
358         if (dev_drv->ops->fps_mgr)
359                 fps = dev_drv->ops->fps_mgr(dev_drv, 0, 0);
360         if (fps < 0)
361                 return fps;
362
363         return snprintf(buf, PAGE_SIZE, "fps:%d\n", fps);
364 }
365
366 static ssize_t set_fps(struct device *dev, struct device_attribute *attr,
367                        const char *buf, size_t count)
368 {
369         struct fb_info *fbi = dev_get_drvdata(dev);
370         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
371         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
372         u32 fps;
373         int ret;
374
375         ret = kstrtou32(buf, 0, &fps);
376         if (ret)
377                 return ret;
378
379         if (fps == 0 || fps > 60) {
380                 dev_info(dev, "unsupport fps value,pelase set 1~60\n");
381                 return count;
382         }
383
384         if (dev_drv->ops->fps_mgr)
385                 ret = dev_drv->ops->fps_mgr(dev_drv, fps, 1);
386         if (ret < 0)
387                 return ret;
388
389         return count;
390 }
391
392 static ssize_t show_fb_win_map(struct device *dev,
393                                struct device_attribute *attr, char *buf)
394 {
395         int ret;
396         struct fb_info *fbi = dev_get_drvdata(dev);
397         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
398         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
399
400         mutex_lock(&dev_drv->fb_win_id_mutex);
401         ret =
402             snprintf(buf, PAGE_SIZE, "fb0:win%d\nfb1:win%d\nfb2:win%d\n",
403                      dev_drv->fb0_win_id, dev_drv->fb1_win_id,
404                      dev_drv->fb2_win_id);
405         mutex_unlock(&dev_drv->fb_win_id_mutex);
406
407         return ret;
408 }
409
410 static ssize_t set_fb_win_map(struct device *dev, struct device_attribute *attr,
411                               const char *buf, size_t count)
412 {
413         struct fb_info *fbi = dev_get_drvdata(dev);
414         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
415         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
416         u32 order;
417         int ret;
418
419         ret = kstrtou32(buf, 0, &order);
420         if ((order != FB0_WIN2_FB1_WIN1_FB2_WIN0) &&
421             (order != FB0_WIN1_FB1_WIN2_FB2_WIN0) &&
422             (order != FB0_WIN2_FB1_WIN0_FB2_WIN1) &&
423             (order != FB0_WIN0_FB1_WIN2_FB2_WIN1) &&
424             (order != FB0_WIN0_FB1_WIN1_FB2_WIN2) &&
425             (order != FB0_WIN1_FB1_WIN0_FB2_WIN2)) {
426                 dev_info(dev, "un supported map\n"
427                        "you can use the following order:\n" "201:\n"
428                        "fb0-win1\n" "fb1-win0\n" "fb2-win2\n" "210:\n"
429                        "fb0-win0\n" "fb1-win1\n" "fb2-win2\n" "120:\n"
430                        "fb0-win0\n" "fb1-win2\n" "fb2-win1\n" "102:\n"
431                        "fb0-win2\n" "fb1-win0\n" "fb2-win1\n" "021:\n"
432                        "fb0-win1\n" "fb1-win2\n" "fb2-win0\n" "012:\n"
433                        "fb0-win2\n" "fb1-win1\n" "fb2-win0\n");
434                 return count;
435         } else {
436                 if (dev_drv->ops->fb_win_remap)
437                         dev_drv->ops->fb_win_remap(dev_drv, order);
438         }
439
440         return count;
441 }
442
443 static ssize_t show_hwc_lut(struct device *dev,
444                             struct device_attribute *attr, char *buf)
445 {
446         return 0;
447 }
448
449 static ssize_t set_hwc_lut(struct device *dev, struct device_attribute *attr,
450                            const char *buf, size_t count)
451 {
452         int hwc_lut[256];
453         const char *start = buf;
454         int i = 256, temp;
455         int space_max;
456
457         struct fb_info *fbi = dev_get_drvdata(dev);
458         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
459         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
460
461         /*printk("count:%d\n>>%s\n\n",count,start);*/
462         for (i = 0; i < 256; i++) {
463                 space_max = 15; /*max space number 15*/
464                 temp = simple_strtoul(start, NULL, 16);
465                 hwc_lut[i] = temp;
466                 do {
467                         start++;
468                         space_max--;
469                 } while ((*start != ' ') && space_max);
470
471                 if (!space_max)
472                         break;
473                 else
474                         start++;
475         }
476 #if 0
477         for (i = 0; i < 16; i++) {
478                 for (j = 0; j < 16; j++)
479                         printk("0x%08x ", hwc_lut[i * 16 + j]);
480                 printk("\n");
481         }
482 #endif
483         if (dev_drv->ops->set_hwc_lut)
484                 dev_drv->ops->set_hwc_lut(dev_drv, hwc_lut, 1);
485
486         return count;
487 }
488
489 static ssize_t show_dsp_lut(struct device *dev,
490                             struct device_attribute *attr, char *buf)
491 {
492         return 0;
493 }
494
495 static ssize_t set_dsp_lut(struct device *dev, struct device_attribute *attr,
496                            const char *buf, size_t count)
497 {
498         int dsp_lut[256];
499         const char *start = buf;
500         int i = 256, temp;
501         int space_max = 10;
502
503         struct fb_info *fbi = dev_get_drvdata(dev);
504         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
505         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
506
507         for (i = 0; i < 256; i++) {
508                 temp = i;
509                 /*init by default value*/
510                 dsp_lut[i] = temp + (temp << 8) + (temp << 16);
511         }
512         /*printk("count:%d\n>>%s\n\n",count,start);*/
513         for (i = 0; i < 256; i++) {
514                 space_max = 10; /*max space number 10*/
515                 temp = simple_strtoul(start, NULL, 10);
516                 dsp_lut[i] = temp;
517                 do {
518                         start++;
519                         space_max--;
520                 } while ((*start != ' ') && space_max);
521
522                 if (!space_max)
523                         break;
524                 else
525                         start++;
526         }
527 #if 0
528         for (i = 0; i < 16; i++) {
529                 for (j = 0; j < 16; j++)
530                         printk("0x%08x ", dsp_lut[i * 16 + j]);
531                 printk("\n");
532         }
533 #endif
534         if (dev_drv->ops->set_dsp_lut)
535                 dev_drv->ops->set_dsp_lut(dev_drv, dsp_lut);
536
537         return count;
538 }
539
540 static ssize_t show_dsp_cabc(struct device *dev,
541                              struct device_attribute *attr, char *buf)
542 {
543         struct fb_info *fbi = dev_get_drvdata(dev);
544         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
545         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
546
547         return snprintf(buf, PAGE_SIZE, "cabc mode=%d\n",
548                 dev_drv->cabc_mode);
549         return 0;
550 }
551
552 static ssize_t set_dsp_cabc(struct device *dev, struct device_attribute *attr,
553                             const char *buf, size_t count)
554 {
555         struct fb_info *fbi = dev_get_drvdata(dev);
556         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
557         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
558         int ret, mode = 0;
559
560         ret = kstrtoint(buf, 0, &mode);
561         if (ret)
562                 return ret;
563
564         if (dev_drv->ops->set_dsp_cabc)
565                 ret = dev_drv->ops->set_dsp_cabc(dev_drv, mode);
566         if (ret < 0)
567                 return ret;
568
569         return count;
570 }
571
572 static ssize_t show_dsp_bcsh(struct device *dev,
573                              struct device_attribute *attr, char *buf)
574 {
575         struct fb_info *fbi = dev_get_drvdata(dev);
576         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
577         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
578         int brightness, contrast, sat_con, sin_hue, cos_hue;
579
580         if (dev_drv->ops->get_dsp_bcsh_bcs) {
581                 brightness = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv,
582                                                             BRIGHTNESS);
583                 contrast = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, CONTRAST);
584                 sat_con = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, SAT_CON);
585         }
586         if (dev_drv->ops->get_dsp_bcsh_hue) {
587                 sin_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv, H_SIN);
588                 cos_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv, H_COS);
589         }
590         return snprintf(buf, PAGE_SIZE,
591                         "brightness:%4d,contrast:%4d,sat_con:%4d,"
592                         "sin_hue:%4d,cos_hue:%4d\n",
593                         brightness, contrast, sat_con, sin_hue, cos_hue);
594 }
595
596 static ssize_t set_dsp_bcsh(struct device *dev, struct device_attribute *attr,
597                             const char *buf, size_t count)
598 {
599         struct fb_info *fbi = dev_get_drvdata(dev);
600         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
601         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
602         int brightness, contrast, sat_con, ret = 0, sin_hue, cos_hue;
603
604         if (!strncmp(buf, "open", 4)) {
605                 if (dev_drv->ops->open_bcsh)
606                         ret = dev_drv->ops->open_bcsh(dev_drv, 1);
607                 else
608                         ret = -1;
609         } else if (!strncmp(buf, "close", 5)) {
610                 if (dev_drv->ops->open_bcsh)
611                         ret = dev_drv->ops->open_bcsh(dev_drv, 0);
612                 else
613                         ret = -1;
614         } else if (!strncmp(buf, "brightness", 10)) {
615                 sscanf(buf, "brightness %d", &brightness);
616                 if (unlikely(brightness > 255)) {
617                         dev_err(fbi->dev,
618                                 "brightness should be [0:255],now=%d\n\n",
619                                 brightness);
620                         brightness = 255;
621                 }
622                 if (dev_drv->ops->set_dsp_bcsh_bcs)
623                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
624                                                              BRIGHTNESS,
625                                                              brightness);
626                 else
627                         ret = -1;
628         } else if (!strncmp(buf, "contrast", 8)) {
629                 sscanf(buf, "contrast %d", &contrast);
630                 if (unlikely(contrast > 510)) {
631                         dev_err(fbi->dev,
632                                 "contrast should be [0:510],now=%d\n",
633                                 contrast);
634                         contrast = 510;
635                 }
636                 if (dev_drv->ops->set_dsp_bcsh_bcs)
637                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
638                                                              CONTRAST,
639                                                              contrast);
640                 else
641                         ret = -1;
642         } else if (!strncmp(buf, "sat_con", 7)) {
643                 sscanf(buf, "sat_con %d", &sat_con);
644                 if (unlikely(sat_con > 1015)) {
645                         dev_err(fbi->dev,
646                                 "sat_con should be [0:1015],now=%d\n",
647                                 sat_con);
648                         sat_con = 1015;
649                 }
650                 if (dev_drv->ops->set_dsp_bcsh_bcs)
651                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
652                                                              SAT_CON,
653                                                              sat_con);
654                 else
655                         ret = -1;
656         } else if (!strncmp(buf, "hue", 3)) {
657                 sscanf(buf, "hue %d %d", &sin_hue, &cos_hue);
658                 if (unlikely(sin_hue > 511 || cos_hue > 511)) {
659                         dev_err(fbi->dev, "sin_hue=%d,cos_hue=%d\n",
660                                 sin_hue, cos_hue);
661                 }
662                 if (dev_drv->ops->set_dsp_bcsh_hue)
663                         ret = dev_drv->ops->set_dsp_bcsh_hue(dev_drv,
664                                                              sin_hue,
665                                                              cos_hue);
666                 else
667                         ret = -1;
668         } else {
669                 dev_info(dev, "format error\n");
670         }
671
672         if (ret < 0)
673                 return ret;
674
675         return count;
676 }
677
678 static ssize_t show_scale(struct device *dev,
679                           struct device_attribute *attr, char *buf)
680 {
681         struct fb_info *fbi = dev_get_drvdata(dev);
682         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
683         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
684         struct rk_screen *screen = dev_drv->cur_screen;
685
686         return snprintf(buf, PAGE_SIZE,
687                 "xscale=%d yscale=%d\nleft=%d top=%d right=%d bottom=%d\n",
688                 (screen->overscan.left + screen->overscan.right)/2,
689                 (screen->overscan.top + screen->overscan.bottom)/2,
690                 screen->overscan.left, screen->overscan.top,
691                 screen->overscan.right, screen->overscan.bottom);
692 }
693
694 static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
695                          const char *buf, size_t count)
696 {
697         struct fb_info *fbi = dev_get_drvdata(dev);
698         struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par;
699         struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv;
700         struct rk_screen *screen = dev_drv->cur_screen;
701         u32 left, top, right, bottom;
702
703         if (!strncmp(buf, "overscan", 8)) {
704                 sscanf(buf,
705                        "overscan %d,%d,%d,%d", &left, &top, &right, &bottom);
706                 if (left > 0 && left <= 100)
707                         screen->overscan.left = left;
708                 if (top > 0 && top <= 100)
709                         screen->overscan.top = top;
710                 if (right > 0 && right <= 100)
711                         screen->overscan.right = right;
712                 if (bottom > 0 && bottom <= 100)
713                         screen->overscan.bottom = bottom;
714         } else if (!strncmp(buf, "left", 4)) {
715                 sscanf(buf, "left=%d", &left);
716                 if (left > 0 && left <= 100)
717                         screen->overscan.left = left;
718         } else if (!strncmp(buf, "top", 3)) {
719                 sscanf(buf, "top=%d", &top);
720                 if (top > 0 && top <= 100)
721                         screen->overscan.top = top;
722         } else if (!strncmp(buf, "right", 5)) {
723                 sscanf(buf, "right=%d", &right);
724                 if (right > 0 && right <= 100)
725                         screen->overscan.right = right;
726         } else if (!strncmp(buf, "bottom", 6)) {
727                 sscanf(buf, "bottom=%d", &bottom);
728                 if (bottom > 0 && bottom <= 100)
729                         screen->overscan.bottom = bottom;
730         } else if (!strncmp(buf, "xscale", 6)) {
731                 sscanf(buf, "xscale=%d", &left);
732                 if (left > 0 && left <= 100) {
733                         screen->overscan.left = left;
734                         screen->overscan.right = left;
735                 }
736         } else if (!strncmp(buf, "yscale", 6)) {
737                 sscanf(buf, "yscale=%d", &left);
738                 if (left > 0 && left <= 100) {
739                         screen->overscan.top = left;
740                         screen->overscan.bottom = left;
741                 }
742         } else {
743                 sscanf(buf, "%d", &left);
744                 if (left > 0 && left <= 100) {
745                         screen->overscan.left = left;
746                         screen->overscan.right = left;
747                         screen->overscan.top = left;
748                         screen->overscan.bottom = left;
749                 }
750         }
751
752         if (dev_drv->ops->set_overscan)
753                 dev_drv->ops->set_overscan(dev_drv, &screen->overscan);
754
755         return count;
756 }
757
758 static struct device_attribute rkfb_attrs[] = {
759         __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
760         __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
761         __ATTR(disp_info, S_IRUGO | S_IWUSR, show_disp_info, set_dump_info),
762         __ATTR(screen_info, S_IRUGO, show_screen_info, NULL),
763         __ATTR(dual_mode, S_IRUGO, show_dual_mode, NULL),
764         __ATTR(enable, S_IRUGO | S_IWUSR, show_fb_state, set_fb_state),
765         __ATTR(overlay, S_IRUGO | S_IWUSR, show_overlay, set_overlay),
766         __ATTR(fps, S_IRUGO | S_IWUSR, show_fps, set_fps),
767         __ATTR(map, S_IRUGO | S_IWUSR, show_fb_win_map, set_fb_win_map),
768         __ATTR(dsp_lut, S_IRUGO | S_IWUSR, show_dsp_lut, set_dsp_lut),
769         __ATTR(hwc_lut, S_IRUGO | S_IWUSR, show_hwc_lut, set_hwc_lut),
770         __ATTR(cabc, S_IRUGO | S_IWUSR, show_dsp_cabc, set_dsp_cabc),
771         __ATTR(bcsh, S_IRUGO | S_IWUSR, show_dsp_bcsh, set_dsp_bcsh),
772         __ATTR(scale, S_IRUGO | S_IWUSR, show_scale, set_scale),
773 };
774
775 int rkfb_create_sysfs(struct fb_info *fbi)
776 {
777         int r, t;
778
779         for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++) {
780                 r = device_create_file(fbi->dev, &rkfb_attrs[t]);
781                 if (r) {
782                         dev_err(fbi->dev, "failed to create sysfs " "file\n");
783                         return r;
784                 }
785         }
786
787         return 0;
788 }
789
790 void rkfb_remove_sysfs(struct rk_fb *rk_fb)
791 {
792         int i, t;
793
794         for (i = 0; i < rk_fb->num_fb; i++) {
795                 for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++)
796                         device_remove_file(rk_fb->fb[i]->dev, &rkfb_attrs[t]);
797         }
798 }