Merge remote-tracking branch 'origin/upstream/linux-linaro-lsk-v3.10-android+android...
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / rkfb_sysfs.c
1 /*
2  * linux/drivers/video/rockchip/rkfb-sysfs.c
3  *
4  * Copyright (C) 2012 Rockchip Corporation
5  * Author: yxj<yxj@rock-chips.com>
6  *
7  * Some code and ideas taken from 
8  *drivers/video/omap2/omapfb/omapfb-sys.c
9  *driver by Tomi Valkeinen.
10  *
11  *
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License version 2 as published by
14  * the Free Software Foundation.
15  *
16  * This program is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19  * more details.
20  *
21  * You should have received a copy of the GNU General Public License along with
22  * this program.  If not, see <http://www.gnu.org/licenses/>.
23  */
24
25 #include <linux/fb.h>
26 #include <linux/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
37 static ssize_t show_screen_info(struct device *dev,
38                 struct device_attribute *attr, char *buf)
39 {
40         struct fb_info *fbi = dev_get_drvdata(dev);
41         struct rk_lcdc_device_driver * dev_drv = 
42                 (struct rk_lcdc_device_driver * )fbi->par;
43         rk_screen * screen = dev_drv->screen0;
44         int fps;
45         u64 ft = (u64)(screen->upper_margin + screen->lower_margin + screen->y_res +screen->vsync_len)*
46                 (screen->left_margin + screen->right_margin + screen->x_res + screen->hsync_len)*
47                 (dev_drv->pixclock);       // one frame time ,(pico seconds)
48         fps = div64_u64(1000000000000llu,ft);
49         return snprintf(buf, PAGE_SIZE,"xres:%d\nyres:%d\nfps:%d\n",
50                 screen->x_res,screen->y_res,fps);
51 }
52
53 static ssize_t show_disp_info(struct device *dev,
54                 struct device_attribute *attr, char *buf)
55 {
56         struct fb_info *fbi = dev_get_drvdata(dev);
57         struct rk_lcdc_device_driver * dev_drv = 
58                 (struct rk_lcdc_device_driver * )fbi->par;
59         int layer_id = dev_drv->fb_get_layer(dev_drv,fbi->fix.id);
60         if(dev_drv->get_disp_info)
61                 return dev_drv->get_disp_info(dev_drv,buf,layer_id);
62
63         return 0;
64 }
65
66 static ssize_t show_phys(struct device *dev,
67                 struct device_attribute *attr, char *buf)
68 {
69         struct fb_info *fbi = dev_get_drvdata(dev);
70         return snprintf(buf, PAGE_SIZE, "0x%lx-----0x%x\n",
71                 fbi->fix.smem_start,fbi->fix.smem_len);
72 }
73
74 static ssize_t show_virt(struct device *dev,
75                 struct device_attribute *attr, char *buf)
76 {
77         struct fb_info *fbi = dev_get_drvdata(dev);
78
79         return snprintf(buf, PAGE_SIZE, "0x%p-----0x%x\n",
80                 fbi->screen_base,fbi->fix.smem_len);
81 }
82
83 static ssize_t show_fb_state(struct device *dev,
84                 struct device_attribute *attr, char *buf)
85 {
86         struct fb_info *fbi = dev_get_drvdata(dev);
87         struct rk_lcdc_device_driver * dev_drv = 
88                 (struct rk_lcdc_device_driver * )fbi->par;
89         int layer_id = dev_drv->fb_get_layer(dev_drv,fbi->fix.id);
90         int state = dev_drv->get_layer_state(dev_drv,layer_id);
91         return snprintf(buf, PAGE_SIZE, "%s\n",state?"enabled":"disabled");
92         
93 }
94
95 static ssize_t show_dual_mode(struct device *dev,
96                 struct device_attribute *attr, char *buf)
97 {
98         int mode=0;
99 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
100         mode = 1;
101 #elif defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL)
102         mode = 2;
103 #else
104         mode = 0;
105 #endif
106         return snprintf(buf, PAGE_SIZE, "%d\n",mode);
107         
108 }
109
110 static ssize_t set_fb_state(struct device *dev,struct device_attribute *attr,
111         const char *buf, size_t count)
112 {
113         struct fb_info *fbi = dev_get_drvdata(dev);
114         struct rk_lcdc_device_driver * dev_drv = 
115                 (struct rk_lcdc_device_driver * )fbi->par;
116         int layer_id = dev_drv->fb_get_layer(dev_drv,fbi->fix.id);
117         int state;
118         int ret;
119         ret = kstrtoint(buf, 0, &state);
120         if(ret)
121         {
122                 return ret;
123         }
124         dev_drv->open(dev_drv,layer_id,state);
125         return count;
126 }
127
128 static ssize_t show_overlay(struct device *dev,
129                 struct device_attribute *attr, char *buf)
130 {
131         struct fb_info *fbi = dev_get_drvdata(dev);
132         struct rk_lcdc_device_driver * dev_drv = 
133                 (struct rk_lcdc_device_driver * )fbi->par;
134         int ovl;
135         ovl =  dev_drv->ovl_mgr(dev_drv,0,0);
136         if(ovl < 0)
137         {
138                 return ovl;
139         }
140
141         return snprintf(buf, PAGE_SIZE, "%s\n",
142                 ovl?"win0 on the top of win1":"win1 on the top of win0");
143         
144 }
145 static ssize_t set_overlay(struct device *dev,struct device_attribute *attr,
146         const char *buf, size_t count)
147 {
148         struct fb_info *fbi = dev_get_drvdata(dev);
149         struct rk_lcdc_device_driver * dev_drv = 
150                 (struct rk_lcdc_device_driver * )fbi->par;
151         int ovl;
152         int ret;
153         ret = kstrtoint(buf, 0, &ovl);
154         if(ret)
155         {
156                 return ret;
157         }
158         ret = dev_drv->ovl_mgr(dev_drv,ovl,1);
159         if(ret < 0)
160         {
161                 return ret;
162         }
163
164         return count;
165 }
166
167
168 static ssize_t show_fps(struct device *dev,
169                 struct device_attribute *attr, char *buf)
170 {
171         struct fb_info *fbi = dev_get_drvdata(dev);
172         struct rk_lcdc_device_driver * dev_drv = 
173                 (struct rk_lcdc_device_driver * )fbi->par;
174         int fps;
175         fps =  dev_drv->fps_mgr(dev_drv,0,0);
176         if(fps < 0)
177         {
178                 return fps;
179         }
180
181         return snprintf(buf, PAGE_SIZE, "fps:%d\n",fps);
182         
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_device_driver * dev_drv = 
190                 (struct rk_lcdc_device_driver * )fbi->par;
191         int fps;
192         int ret;
193         ret = kstrtoint(buf, 0, &fps);
194         if(ret)
195         {
196                 return ret;
197         }
198         ret = dev_drv->fps_mgr(dev_drv,fps,1);
199         if(ret < 0)
200         {
201                 return ret;
202         }
203
204         return count;
205 }
206
207 static ssize_t show_fb_win_map(struct device *dev,
208                 struct device_attribute *attr, char *buf)
209 {
210         int ret;
211         struct fb_info *fbi = dev_get_drvdata(dev);
212         struct rk_lcdc_device_driver * dev_drv = 
213                 (struct rk_lcdc_device_driver * )fbi->par;
214
215         mutex_lock(&dev_drv->fb_win_id_mutex);
216         ret = snprintf(buf, PAGE_SIZE,"fb0:win%d\nfb1:win%d\nfb2:win%d\n",dev_drv->fb0_win_id,dev_drv->fb1_win_id,
217                 dev_drv->fb2_win_id);
218         mutex_unlock(&dev_drv->fb_win_id_mutex);
219
220         return ret;
221         
222 }
223
224 static ssize_t set_fb_win_map(struct device *dev,struct device_attribute *attr,
225         const char *buf, size_t count)
226 {
227         struct fb_info *fbi = dev_get_drvdata(dev);
228         struct rk_lcdc_device_driver * dev_drv = 
229                 (struct rk_lcdc_device_driver * )fbi->par;
230         int order;
231         int ret;
232         ret = kstrtoint(buf, 0, &order);
233         if((order != FB0_WIN2_FB1_WIN1_FB2_WIN0) && (order != FB0_WIN1_FB1_WIN2_FB2_WIN0 ) &&
234            (order != FB0_WIN2_FB1_WIN0_FB2_WIN1) && (order != FB0_WIN0_FB1_WIN2_FB2_WIN1 ) &&
235            (order != FB0_WIN0_FB1_WIN1_FB2_WIN2) && (order != FB0_WIN1_FB1_WIN0_FB2_WIN2 ))
236         {
237                 printk(KERN_ERR "un supported map\n"
238                                 "you can use the following order:\n"
239                                 "201:\n"
240                                 "fb0-win1\n"
241                                 "fb1-win0\n"
242                                 "fb2-win2\n"
243                                 "210:\n"
244                                 "fb0-win0\n"
245                                 "fb1-win1\n"
246                                 "fb2-win2\n"                      
247                                 "120:\n"
248                                 "fb0-win0\n"
249                                 "fb1-win2\n"
250                                 "fb2-win1\n"                      
251                                 "102:\n"
252                                 "fb0-win2\n"
253                                 "fb1-win0\n"
254                                 "fb2-win1\n"                       
255                                 "021:\n"
256                                 "fb0-win1\n"
257                                 "fb1-win2\n"
258                                 "fb2-win0\n"                       
259                                 "012:\n"
260                                 "fb0-win2\n"
261                                 "fb1-win1\n"
262                                 "fb2-win0\n");
263                 return count;
264         }
265         else
266         {
267                 dev_drv->fb_layer_remap(dev_drv,order);
268         }
269
270         return count;
271         
272         
273 }
274
275 static ssize_t show_dsp_lut(struct device *dev,
276                 struct device_attribute *attr, char *buf)
277 {
278
279         return 0;       
280 }
281 static ssize_t set_dsp_lut(struct device *dev,struct device_attribute *attr,
282         const char *buf, size_t count)
283 {
284         int dsp_lut[256];
285         const char *start = buf;
286         int i=256,j,temp;
287         int space_max = 10;
288
289         struct fb_info *fbi = dev_get_drvdata(dev);
290         struct rk_lcdc_device_driver * dev_drv = 
291                 (struct rk_lcdc_device_driver * )fbi->par;
292         
293         for(i=0;i<256;i++)
294         {
295                 temp = i;
296                 dsp_lut[i] = temp + (temp<<8) + (temp<<16);  //init by default value
297         }
298         //printk("count:%d\n>>%s\n\n",count,start);
299         for(i=0;i<256;i++)
300         {
301                 space_max = 10;  //max space number 10;
302                 temp = simple_strtoul(start,NULL,10);
303                 dsp_lut[i] = temp;
304                 do
305                 {
306                         start++;
307                         space_max--;
308                 }while ((*start != ' ')&&space_max);
309                 
310                 if(!space_max)
311                         break;
312                 else
313                         start++;
314         }
315 #if 0
316         for(i=0;i<16;i++)
317         {
318                 for(j=0;j<16;j++)
319                         printk("0x%08x ",dsp_lut[i*16+j]);
320                 printk("\n");
321         }
322 #endif
323         dev_drv->set_dsp_lut(dev_drv,dsp_lut);
324
325         return count;
326         
327 }
328
329 static struct device_attribute rkfb_attrs[] = {
330         __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
331         __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
332         __ATTR(disp_info, S_IRUGO, show_disp_info, NULL),
333         __ATTR(screen_info, S_IRUGO, show_screen_info, NULL),
334         __ATTR(dual_mode, S_IRUGO, show_dual_mode, NULL),
335         __ATTR(enable, S_IRUGO | S_IWUSR, show_fb_state, set_fb_state),
336         __ATTR(overlay, S_IRUGO | S_IWUSR, show_overlay, set_overlay),
337         __ATTR(fps, S_IRUGO | S_IWUSR, show_fps, set_fps),
338         __ATTR(map, S_IRUGO | S_IWUSR, show_fb_win_map, set_fb_win_map),
339         __ATTR(dsp_lut, S_IRUGO | S_IWUSR, show_dsp_lut, set_dsp_lut),
340 };
341
342 int rkfb_create_sysfs(struct fb_info *fbi)
343 {
344         int r;
345         int t;
346         for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++)
347         {
348                 r = device_create_file(fbi->dev,&rkfb_attrs[t]);
349                 if (r)
350                 {
351                         dev_err(fbi->dev, "failed to create sysfs "
352                                         "file\n");
353                         return r;
354                 }
355         }
356         
357
358         return 0;
359 }
360
361 void rkfb_remove_sysfs(struct rk_fb_inf *inf)
362 {
363         int i, t;
364
365         for (i = 0; i < inf->num_fb; i++) {
366                 for (t = 0; t < ARRAY_SIZE(rkfb_attrs); t++)
367                         device_remove_file(inf->fb[i]->dev,
368                                         &rkfb_attrs[t]);
369         }
370 }
371