Merge branch 'develop-3.10' of ssh://10.10.10.29/rk/kernel into my_wifi
[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 <asm/div64.h>
33 #include <linux/rk_screen.h>
34 #include <linux/rk_fb.h>
35
36 static ssize_t show_screen_info(struct device *dev,
37                                 struct device_attribute *attr, char *buf)
38 {
39         struct fb_info *fbi = dev_get_drvdata(dev);
40         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)fbi->par;
41         struct rk_screen *screen = dev_drv->cur_screen;
42         int fps = 0;
43         u32 x = screen->mode.left_margin + screen->mode.right_margin +
44                 screen->mode.xres + screen->mode.hsync_len;
45         u32 y = screen->mode.upper_margin + screen->mode.lower_margin +
46                 screen->mode.yres + screen->mode.vsync_len;
47         u64 ft = (u64)x * y * (dev_drv->pixclock);
48
49         if (ft > 0)
50                 fps = div64_u64(1000000000000llu, ft);
51         return snprintf(buf, PAGE_SIZE, "xres:%d\nyres:%d\nfps:%d\n",
52                         screen->mode.xres, screen->mode.yres, fps);
53 }
54
55 static ssize_t show_disp_info(struct device *dev,
56                               struct device_attribute *attr, char *buf)
57 {
58         struct fb_info *fbi = dev_get_drvdata(dev);
59         struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)fbi->par;
60         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
61
62         if (dev_drv->ops->get_disp_info)
63                 return dev_drv->ops->get_disp_info(dev_drv, buf, win_id);
64
65         return 0;
66 }
67
68 static ssize_t show_phys(struct device *dev,
69                          struct device_attribute *attr, char *buf)
70 {
71         struct fb_info *fbi = dev_get_drvdata(dev);
72
73         return snprintf(buf, PAGE_SIZE, "0x%lx-----0x%x\n",
74                         fbi->fix.smem_start, fbi->fix.smem_len);
75 }
76
77 static ssize_t show_virt(struct device *dev,
78                          struct device_attribute *attr, char *buf)
79 {
80         struct fb_info *fbi = dev_get_drvdata(dev);
81
82         return snprintf(buf, PAGE_SIZE, "0x%p-----0x%x\n",
83                         fbi->screen_base, fbi->fix.smem_len);
84 }
85
86 static ssize_t show_fb_state(struct device *dev,
87                              struct device_attribute *attr, char *buf)
88 {
89         struct fb_info *fbi = dev_get_drvdata(dev);
90         struct rk_lcdc_driver *dev_drv =
91             (struct rk_lcdc_driver *)fbi->par;
92         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
93         int state = dev_drv->ops->get_win_state(dev_drv, win_id);
94
95         return snprintf(buf, PAGE_SIZE, "%s\n", state ? "enabled" : "disabled");
96 }
97
98 static ssize_t show_dual_mode(struct device *dev,
99                               struct device_attribute *attr, char *buf)
100 {
101         struct fb_info *fbi = dev_get_drvdata(dev);
102         struct rk_fb *rk_fb = dev_get_drvdata(fbi->device);
103         int mode = rk_fb->disp_mode;
104
105         return snprintf(buf, PAGE_SIZE, "%d\n", mode);
106 }
107
108 static ssize_t set_fb_state(struct device *dev, struct device_attribute *attr,
109                             const char *buf, size_t count)
110 {
111         struct fb_info *fbi = dev_get_drvdata(dev);
112         struct rk_lcdc_driver *dev_drv =
113             (struct rk_lcdc_driver *)fbi->par;
114         int win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
115         int state;
116         int ret;
117
118         ret = kstrtoint(buf, 0, &state);
119         if (ret)
120                 return ret;
121         dev_drv->ops->open(dev_drv, win_id, state);
122         if (state) {
123                 dev_drv->ops->set_par(dev_drv, win_id);
124                 dev_drv->ops->pan_display(dev_drv, win_id);
125                 dev_drv->ops->cfg_done(dev_drv);
126         }
127         return count;
128 }
129
130 static ssize_t show_overlay(struct device *dev,
131                             struct device_attribute *attr, char *buf)
132 {
133         struct fb_info *fbi = dev_get_drvdata(dev);
134         struct rk_lcdc_driver *dev_drv =
135             (struct rk_lcdc_driver *)fbi->par;
136         int ovl;
137
138         if (dev_drv->ops->ovl_mgr)
139                 ovl = dev_drv->ops->ovl_mgr(dev_drv, 0, 0);
140
141         if (ovl < 0)
142                 return ovl;
143
144         return snprintf(buf, PAGE_SIZE, "%s\n",
145                         ovl ? "win0 on the top of win1" :
146                         "win1 on the top of win0");
147 }
148
149 static ssize_t set_overlay(struct device *dev, struct device_attribute *attr,
150                            const char *buf, size_t count)
151 {
152         struct fb_info *fbi = dev_get_drvdata(dev);
153         struct rk_lcdc_driver *dev_drv =
154             (struct rk_lcdc_driver *)fbi->par;
155         u32 ovl;
156         int ret;
157
158         ret = kstrtou32(buf, 0, &ovl);
159         if (ret)
160                 return ret;
161         if (dev_drv->ops->ovl_mgr)
162                 ret = dev_drv->ops->ovl_mgr(dev_drv, ovl, 1);
163         if (ret < 0)
164                 return ret;
165
166         return count;
167 }
168
169 static ssize_t show_fps(struct device *dev,
170                         struct device_attribute *attr, char *buf)
171 {
172         struct fb_info *fbi = dev_get_drvdata(dev);
173         struct rk_lcdc_driver *dev_drv =
174             (struct rk_lcdc_driver *)fbi->par;
175         int fps;
176
177         if (dev_drv->ops->fps_mgr)
178                 fps = dev_drv->ops->fps_mgr(dev_drv, 0, 0);
179         if (fps < 0)
180                 return fps;
181
182         return snprintf(buf, PAGE_SIZE, "fps:%d\n", fps);
183 }
184
185 static ssize_t set_fps(struct device *dev, struct device_attribute *attr,
186                        const char *buf, size_t count)
187 {
188         struct fb_info *fbi = dev_get_drvdata(dev);
189         struct rk_lcdc_driver *dev_drv =
190             (struct rk_lcdc_driver *)fbi->par;
191         u32 fps;
192         int ret;
193
194         ret = kstrtou32(buf, 0, &fps);
195         if (ret)
196                 return ret;
197
198         if (fps == 0 || fps > 60) {
199                 dev_info(dev, "unsupport fps value,pelase set 1~60\n");
200                 return count;
201         }
202
203         if (dev_drv->ops->fps_mgr)
204                 ret = dev_drv->ops->fps_mgr(dev_drv, fps, 1);
205         if (ret < 0)
206                 return ret;
207
208         return count;
209 }
210
211 static ssize_t show_fb_win_map(struct device *dev,
212                                struct device_attribute *attr, char *buf)
213 {
214         int ret;
215         struct fb_info *fbi = dev_get_drvdata(dev);
216         struct rk_lcdc_driver *dev_drv =
217             (struct rk_lcdc_driver *)fbi->par;
218
219         mutex_lock(&dev_drv->fb_win_id_mutex);
220         ret =
221             snprintf(buf, PAGE_SIZE, "fb0:win%d\nfb1:win%d\nfb2:win%d\n",
222                      dev_drv->fb0_win_id, dev_drv->fb1_win_id,
223                      dev_drv->fb2_win_id);
224         mutex_unlock(&dev_drv->fb_win_id_mutex);
225
226         return ret;
227 }
228
229 static ssize_t set_fb_win_map(struct device *dev, struct device_attribute *attr,
230                               const char *buf, size_t count)
231 {
232         struct fb_info *fbi = dev_get_drvdata(dev);
233         struct rk_lcdc_driver *dev_drv =
234             (struct rk_lcdc_driver *)fbi->par;
235         u32 order;
236         int ret;
237
238         ret = kstrtou32(buf, 0, &order);
239         if ((order != FB0_WIN2_FB1_WIN1_FB2_WIN0) &&
240             (order != FB0_WIN1_FB1_WIN2_FB2_WIN0) &&
241             (order != FB0_WIN2_FB1_WIN0_FB2_WIN1) &&
242             (order != FB0_WIN0_FB1_WIN2_FB2_WIN1) &&
243             (order != FB0_WIN0_FB1_WIN1_FB2_WIN2) &&
244             (order != FB0_WIN1_FB1_WIN0_FB2_WIN2)) {
245                 dev_info(dev, "un supported map\n"
246                        "you can use the following order:\n" "201:\n"
247                        "fb0-win1\n" "fb1-win0\n" "fb2-win2\n" "210:\n"
248                        "fb0-win0\n" "fb1-win1\n" "fb2-win2\n" "120:\n"
249                        "fb0-win0\n" "fb1-win2\n" "fb2-win1\n" "102:\n"
250                        "fb0-win2\n" "fb1-win0\n" "fb2-win1\n" "021:\n"
251                        "fb0-win1\n" "fb1-win2\n" "fb2-win0\n" "012:\n"
252                        "fb0-win2\n" "fb1-win1\n" "fb2-win0\n");
253                 return count;
254         } else {
255                 if (dev_drv->ops->fb_win_remap)
256                         dev_drv->ops->fb_win_remap(dev_drv, order);
257         }
258
259         return count;
260 }
261
262 static ssize_t show_hwc_lut(struct device *dev,
263                             struct device_attribute *attr, char *buf)
264 {
265         return 0;
266 }
267
268 static ssize_t set_hwc_lut(struct device *dev, struct device_attribute *attr,
269                            const char *buf, size_t count)
270 {
271         int hwc_lut[256];
272         const char *start = buf;
273         int i = 256, temp;
274         int space_max;
275
276         struct fb_info *fbi = dev_get_drvdata(dev);
277         struct rk_lcdc_driver *dev_drv =
278             (struct rk_lcdc_driver *)fbi->par;
279
280         /*printk("count:%d\n>>%s\n\n",count,start);*/
281         for (i = 0; i < 256; i++) {
282                 space_max = 15; /*max space number 15*/
283                 temp = simple_strtoul(start, NULL, 16);
284                 hwc_lut[i] = temp;
285                 do {
286                         start++;
287                         space_max--;
288                 } while ((*start != ' ') && space_max);
289
290                 if (!space_max)
291                         break;
292                 else
293                         start++;
294         }
295 #if 0
296         for (i = 0; i < 16; i++) {
297                 for (j = 0; j < 16; j++)
298                         printk("0x%08x ", hwc_lut[i * 16 + j]);
299                 printk("\n");
300         }
301 #endif
302         if (dev_drv->ops->set_hwc_lut)
303                 dev_drv->ops->set_hwc_lut(dev_drv, hwc_lut, 1);
304
305         return count;
306 }
307
308 static ssize_t show_dsp_lut(struct device *dev,
309                             struct device_attribute *attr, char *buf)
310 {
311         return 0;
312 }
313
314 static ssize_t set_dsp_lut(struct device *dev, struct device_attribute *attr,
315                            const char *buf, size_t count)
316 {
317         int dsp_lut[256];
318         const char *start = buf;
319         int i = 256, temp;
320         int space_max = 10;
321
322         struct fb_info *fbi = dev_get_drvdata(dev);
323         struct rk_lcdc_driver *dev_drv =
324             (struct rk_lcdc_driver *)fbi->par;
325
326         for (i = 0; i < 256; i++) {
327                 temp = i;
328                 /*init by default value*/
329                 dsp_lut[i] = temp + (temp << 8) + (temp << 16);
330         }
331         /*printk("count:%d\n>>%s\n\n",count,start);*/
332         for (i = 0; i < 256; i++) {
333                 space_max = 10; /*max space number 10*/
334                 temp = simple_strtoul(start, NULL, 10);
335                 dsp_lut[i] = temp;
336                 do {
337                         start++;
338                         space_max--;
339                 } while ((*start != ' ') && space_max);
340
341                 if (!space_max)
342                         break;
343                 else
344                         start++;
345         }
346 #if 0
347         for (i = 0; i < 16; i++) {
348                 for (j = 0; j < 16; j++)
349                         printk("0x%08x ", dsp_lut[i * 16 + j]);
350                 printk("\n");
351         }
352 #endif
353         if (dev_drv->ops->set_dsp_lut)
354                 dev_drv->ops->set_dsp_lut(dev_drv, dsp_lut);
355
356         return count;
357 }
358
359 static ssize_t show_dsp_cabc(struct device *dev,
360                              struct device_attribute *attr, char *buf)
361 {
362         struct fb_info *fbi = dev_get_drvdata(dev);
363         struct rk_lcdc_driver *dev_drv =
364             (struct rk_lcdc_driver *)fbi->par;
365
366         return snprintf(buf, PAGE_SIZE, "cabc mode=%d\n",
367                 dev_drv->cabc_mode);
368         return 0;
369 }
370
371 static ssize_t set_dsp_cabc(struct device *dev, struct device_attribute *attr,
372                             const char *buf, size_t count)
373 {
374         struct fb_info *fbi = dev_get_drvdata(dev);
375         struct rk_lcdc_driver *dev_drv =
376             (struct rk_lcdc_driver *)fbi->par;
377         int ret, mode = 0;
378
379         ret = kstrtoint(buf, 0, &mode);
380         if (ret)
381                 return ret;
382
383         if (dev_drv->ops->set_dsp_cabc)
384                 ret = dev_drv->ops->set_dsp_cabc(dev_drv, mode);
385         if (ret < 0)
386                 return ret;
387
388         return count;
389 }
390
391 static ssize_t show_dsp_bcsh(struct device *dev,
392                              struct device_attribute *attr, char *buf)
393 {
394         struct fb_info *fbi = dev_get_drvdata(dev);
395         struct rk_lcdc_driver *dev_drv =
396             (struct rk_lcdc_driver *)fbi->par;
397         int brightness, contrast, sat_con, sin_hue, cos_hue;
398
399         if (dev_drv->ops->get_dsp_bcsh_bcs) {
400                 brightness = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv,
401                                                             BRIGHTNESS);
402                 contrast = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, CONTRAST);
403                 sat_con = dev_drv->ops->get_dsp_bcsh_bcs(dev_drv, SAT_CON);
404         }
405         if (dev_drv->ops->get_dsp_bcsh_hue) {
406                 sin_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv, H_SIN);
407                 cos_hue = dev_drv->ops->get_dsp_bcsh_hue(dev_drv, H_COS);
408         }
409         return snprintf(buf, PAGE_SIZE,
410                         "brightness:%4d,contrast:%4d,sat_con:%4d,"
411                         "sin_hue:%4d,cos_hue:%4d\n",
412                         brightness, contrast, sat_con, sin_hue, cos_hue);
413 }
414
415 static ssize_t set_dsp_bcsh(struct device *dev, struct device_attribute *attr,
416                             const char *buf, size_t count)
417 {
418         struct fb_info *fbi = dev_get_drvdata(dev);
419         struct rk_lcdc_driver *dev_drv =
420             (struct rk_lcdc_driver *)fbi->par;
421         int brightness, contrast, sat_con, ret = 0, sin_hue, cos_hue;
422
423         if (!strncmp(buf, "open", 4)) {
424                 if (dev_drv->ops->open_bcsh)
425                         ret = dev_drv->ops->open_bcsh(dev_drv, 1);
426                 else
427                         ret = -1;
428         } else if (!strncmp(buf, "close", 5)) {
429                 if (dev_drv->ops->open_bcsh)
430                         ret = dev_drv->ops->open_bcsh(dev_drv, 0);
431                 else
432                         ret = -1;
433         } else if (!strncmp(buf, "brightness", 10)) {
434                 sscanf(buf, "brightness %d", &brightness);
435                 if (unlikely(brightness > 255)) {
436                         dev_err(fbi->dev,
437                                 "brightness should be [0:255],now=%d\n\n",
438                                 brightness);
439                         brightness = 255;
440                 }
441                 if (dev_drv->ops->set_dsp_bcsh_bcs)
442                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
443                                                              BRIGHTNESS,
444                                                              brightness);
445                 else
446                         ret = -1;
447         } else if (!strncmp(buf, "contrast", 8)) {
448                 sscanf(buf, "contrast %d", &contrast);
449                 if (unlikely(contrast > 510)) {
450                         dev_err(fbi->dev,
451                                 "contrast should be [0:510],now=%d\n",
452                                 contrast);
453                         contrast = 510;
454                 }
455                 if (dev_drv->ops->set_dsp_bcsh_bcs)
456                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
457                                                              CONTRAST,
458                                                              contrast);
459                 else
460                         ret = -1;
461         } else if (!strncmp(buf, "sat_con", 7)) {
462                 sscanf(buf, "sat_con %d", &sat_con);
463                 if (unlikely(sat_con > 1015)) {
464                         dev_err(fbi->dev,
465                                 "sat_con should be [0:1015],now=%d\n",
466                                 sat_con);
467                         sat_con = 1015;
468                 }
469                 if (dev_drv->ops->set_dsp_bcsh_bcs)
470                         ret = dev_drv->ops->set_dsp_bcsh_bcs(dev_drv,
471                                                              SAT_CON,
472                                                              sat_con);
473                 else
474                         ret = -1;
475         } else if (!strncmp(buf, "hue", 3)) {
476                 sscanf(buf, "hue %d %d", &sin_hue, &cos_hue);
477                 if (unlikely(sin_hue > 511 || cos_hue > 511)) {
478                         dev_err(fbi->dev, "sin_hue=%d,cos_hue=%d\n",
479                                 sin_hue, cos_hue);
480                 }
481                 if (dev_drv->ops->set_dsp_bcsh_hue)
482                         ret = dev_drv->ops->set_dsp_bcsh_hue(dev_drv,
483                                                              sin_hue,
484                                                              cos_hue);
485                 else
486                         ret = -1;
487         } else {
488                 dev_info(dev, "format error\n");
489         }
490
491         if (ret < 0)
492                 return ret;
493
494         return count;
495 }
496
497 static ssize_t show_scale(struct device *dev,
498                           struct device_attribute *attr, char *buf)
499 {
500         struct fb_info *fbi = dev_get_drvdata(dev);
501         struct rk_lcdc_driver *dev_drv =
502             (struct rk_lcdc_driver *)fbi->par;
503         struct rk_screen *screen = dev_drv->cur_screen;
504
505         return snprintf(buf, PAGE_SIZE,
506                 "xscale=%d yscale=%d\nleft=%d top=%d right=%d bottom=%d\n",
507                 (screen->overscan.left + screen->overscan.right)/2,
508                 (screen->overscan.top + screen->overscan.bottom)/2,
509                 screen->overscan.left, screen->overscan.top,
510                 screen->overscan.right, screen->overscan.bottom);
511 }
512
513 static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
514                          const char *buf, size_t count)
515 {
516         struct fb_info *fbi = dev_get_drvdata(dev);
517         struct rk_lcdc_driver *dev_drv =
518             (struct rk_lcdc_driver *)fbi->par;
519         struct rk_screen *screen = dev_drv->cur_screen;
520         u32 left, top, right, bottom;
521
522         if (!strncmp(buf, "overscan", 8)) {
523                 sscanf(buf,
524                        "overscan %d,%d,%d,%d", &left, &top, &right, &bottom);
525                 if (left > 0 && left <= 100)
526                         screen->overscan.left = left;
527                 if (top > 0 && top <= 100)
528                         screen->overscan.top = top;
529                 if (right > 0 && right <= 100)
530                         screen->overscan.right = right;
531                 if (bottom > 0 && bottom <= 100)
532                         screen->overscan.bottom = bottom;
533         } else if (!strncmp(buf, "left", 4)) {
534                 sscanf(buf, "left=%d", &left);
535                 if (left > 0 && left <= 100)
536                         screen->overscan.left = left;
537         } else if (!strncmp(buf, "top", 3)) {
538                 sscanf(buf, "top=%d", &top);
539                 if (top > 0 && top <= 100)
540                         screen->overscan.top = top;
541         } else if (!strncmp(buf, "right", 5)) {
542                 sscanf(buf, "right=%d", &right);
543                 if (right > 0 && right <= 100)
544                         screen->overscan.right = right;
545         } else if (!strncmp(buf, "bottom", 6)) {
546                 sscanf(buf, "bottom=%d", &bottom);
547                 if (bottom > 0 && bottom <= 100)
548                         screen->overscan.bottom = bottom;
549         } else if (!strncmp(buf, "xscale", 6)) {
550                 sscanf(buf, "xscale=%d", &left);
551                 if (left > 0 && left <= 100) {
552                         screen->overscan.left = left;
553                         screen->overscan.right = left;
554                 }
555         } else if (!strncmp(buf, "yscale", 6)) {
556                 sscanf(buf, "yscale=%d", &left);
557                 if (left > 0 && left <= 100) {
558                         screen->overscan.top = left;
559                         screen->overscan.bottom = left;
560                 }
561         } else {
562                 sscanf(buf, "%d", &left);
563                 if (left > 0 && left <= 100) {
564                         screen->overscan.left = left;
565                         screen->overscan.right = left;
566                         screen->overscan.top = left;
567                         screen->overscan.bottom = left;
568                 }
569         }
570
571         if (dev_drv->ops->set_overscan)
572                 dev_drv->ops->set_overscan(dev_drv, &screen->overscan);
573
574         return count;
575 }
576
577 static struct device_attribute rkfb_attrs[] = {
578         __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
579         __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
580         __ATTR(disp_info, S_IRUGO, show_disp_info, NULL),
581         __ATTR(screen_info, S_IRUGO, show_screen_info, NULL),
582         __ATTR(dual_mode, S_IRUGO, show_dual_mode, NULL),
583         __ATTR(enable, S_IRUGO | S_IWUSR, show_fb_state, set_fb_state),
584         __ATTR(overlay, S_IRUGO | S_IWUSR, show_overlay, set_overlay),
585         __ATTR(fps, S_IRUGO | S_IWUSR, show_fps, set_fps),
586         __ATTR(map, S_IRUGO | S_IWUSR, show_fb_win_map, set_fb_win_map),
587         __ATTR(dsp_lut, S_IRUGO | S_IWUSR, show_dsp_lut, set_dsp_lut),
588         __ATTR(hwc_lut, S_IRUGO | S_IWUSR, show_hwc_lut, set_hwc_lut),
589         __ATTR(cabc, S_IRUGO | S_IWUSR, show_dsp_cabc, set_dsp_cabc),
590         __ATTR(bcsh, S_IRUGO | S_IWUSR, show_dsp_bcsh, set_dsp_bcsh),
591         __ATTR(scale, S_IRUGO | S_IWUSR, show_scale, set_scale),
592 };
593
594 int rkfb_create_sysfs(struct fb_info *fbi)
595 {
596         int r, t;
597
598         for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++) {
599                 r = device_create_file(fbi->dev, &rkfb_attrs[t]);
600                 if (r) {
601                         dev_err(fbi->dev, "failed to create sysfs " "file\n");
602                         return r;
603                 }
604         }
605
606         return 0;
607 }
608
609 void rkfb_remove_sysfs(struct rk_fb *rk_fb)
610 {
611         int i, t;
612
613         for (i = 0; i < rk_fb->num_fb; i++) {
614                 for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++)
615                         device_remove_file(rk_fb->fb[i]->dev, &rkfb_attrs[t]);
616         }
617 }