Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]

Diff markup

Differences between /linux/drivers/video/omap/omapfb_main.c (Version 2.6.31.13) and /linux/drivers/video/omap/omapfb_main.c (Version 2.6.11.8)


  1 /*                                                  1 
  2  * Framebuffer driver for TI OMAP boards          
  3  *                                                
  4  * Copyright (C) 2004 Nokia Corporation           
  5  * Author: Imre Deak <imre.deak@nokia.com>        
  6  *                                                
  7  * Acknowledgements:                              
  8  *   Alex McMains <aam@ridgerun.com>       - O    
  9  *   Juha Yrjola <juha.yrjola@nokia.com>   - O    
 10  *   Dirk Behme <dirk.behme@de.bosch.com>  - c    
 11  *   Texas Instruments                     - H    
 12  *                                                
 13  * This program is free software; you can redi    
 14  * under the terms of the GNU General Public L    
 15  * Free Software Foundation; either version 2     
 16  * option) any later version.                     
 17  *                                                
 18  * This program is distributed in the hope tha    
 19  * WITHOUT ANY WARRANTY; without even the impl    
 20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR    
 21  * General Public License for more details.       
 22  *                                                
 23  * You should have received a copy of the GNU     
 24  * with this program; if not, write to the Fre    
 25  * 59 Temple Place - Suite 330, Boston, MA  02    
 26  */                                               
 27 #include <linux/platform_device.h>                
 28 #include <linux/mm.h>                             
 29 #include <linux/uaccess.h>                        
 30                                                   
 31 #include <mach/dma.h>                             
 32 #include <mach/omapfb.h>                          
 33                                                   
 34 #include "lcdc.h"                                 
 35 #include "dispc.h"                                
 36                                                   
 37 #define MODULE_NAME     "omapfb"                  
 38                                                   
 39 static unsigned int     def_accel;                
 40 static unsigned long    def_vram[OMAPFB_PLANE_    
 41 static unsigned int     def_vram_cnt;             
 42 static unsigned long    def_vxres;                
 43 static unsigned long    def_vyres;                
 44 static unsigned int     def_rotate;               
 45 static unsigned int     def_mirror;               
 46                                                   
 47 #ifdef CONFIG_FB_OMAP_MANUAL_UPDATE               
 48 static int              manual_update = 1;        
 49 #else                                             
 50 static int              manual_update;            
 51 #endif                                            
 52                                                   
 53 static struct platform_device   *fbdev_pdev;      
 54 static struct lcd_panel         *fbdev_panel;     
 55 static struct omapfb_device     *omapfb_dev;      
 56                                                   
 57 struct caps_table_struct {                        
 58         unsigned long flag;                       
 59         const char *name;                         
 60 };                                                
 61                                                   
 62 static struct caps_table_struct ctrl_caps[] =     
 63         { OMAPFB_CAPS_MANUAL_UPDATE,  "manual     
 64         { OMAPFB_CAPS_TEARSYNC,       "tearing    
 65         { OMAPFB_CAPS_PLANE_RELOCATE_MEM, "rel    
 66         { OMAPFB_CAPS_PLANE_SCALE,    "scale p    
 67         { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pi    
 68         { OMAPFB_CAPS_WINDOW_SCALE,   "scale w    
 69         { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay    
 70         { OMAPFB_CAPS_SET_BACKLIGHT,  "backlig    
 71 };                                                
 72                                                   
 73 static struct caps_table_struct color_caps[] =    
 74         { 1 << OMAPFB_COLOR_RGB565,     "RGB56    
 75         { 1 << OMAPFB_COLOR_YUV422,     "YUV42    
 76         { 1 << OMAPFB_COLOR_YUV420,     "YUV42    
 77         { 1 << OMAPFB_COLOR_CLUT_8BPP,  "CLUT8    
 78         { 1 << OMAPFB_COLOR_CLUT_4BPP,  "CLUT4    
 79         { 1 << OMAPFB_COLOR_CLUT_2BPP,  "CLUT2    
 80         { 1 << OMAPFB_COLOR_CLUT_1BPP,  "CLUT1    
 81         { 1 << OMAPFB_COLOR_RGB444,     "RGB44    
 82         { 1 << OMAPFB_COLOR_YUY422,     "YUY42    
 83 };                                                
 84                                                   
 85 /*                                                
 86  * -------------------------------------------    
 87  * LCD panel                                      
 88  * -------------------------------------------    
 89  */                                               
 90 extern struct lcd_ctrl hwa742_ctrl;               
 91 extern struct lcd_ctrl blizzard_ctrl;             
 92                                                   
 93 static const struct lcd_ctrl *ctrls[] = {         
 94 #ifdef CONFIG_ARCH_OMAP1                          
 95         &omap1_int_ctrl,                          
 96 #else                                             
 97         &omap2_int_ctrl,                          
 98 #endif                                            
 99                                                   
100 #ifdef CONFIG_FB_OMAP_LCDC_HWA742                 
101         &hwa742_ctrl,                             
102 #endif                                            
103 #ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD               
104         &blizzard_ctrl,                           
105 #endif                                            
106 };                                                
107                                                   
108 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL               
109 #ifdef CONFIG_ARCH_OMAP1                          
110 extern struct lcd_ctrl_extif omap1_ext_if;        
111 #else                                             
112 extern struct lcd_ctrl_extif omap2_ext_if;        
113 #endif                                            
114 #endif                                            
115                                                   
116 static void omapfb_rqueue_lock(struct omapfb_d    
117 {                                                 
118         mutex_lock(&fbdev->rqueue_mutex);         
119 }                                                 
120                                                   
121 static void omapfb_rqueue_unlock(struct omapfb    
122 {                                                 
123         mutex_unlock(&fbdev->rqueue_mutex);       
124 }                                                 
125                                                   
126 /*                                                
127  * -------------------------------------------    
128  * LCD controller and LCD DMA                     
129  * -------------------------------------------    
130  */                                               
131 /* Lookup table to map elem size to elem type.    
132 static const int dma_elem_type[] = {              
133         0,                                        
134         OMAP_DMA_DATA_TYPE_S8,                    
135         OMAP_DMA_DATA_TYPE_S16,                   
136         0,                                        
137         OMAP_DMA_DATA_TYPE_S32,                   
138 };                                                
139                                                   
140 /*                                                
141  * Allocate resources needed for LCD controlle    
142  * memory is allocated from system memory acco    
143  * size, except if a bigger memory size is spe    
144  * parameter.                                     
145  */                                               
146 static int ctrl_init(struct omapfb_device *fbd    
147 {                                                 
148         int r;                                    
149         int i;                                    
150                                                   
151         /* kernel/module vram parameters overr    
152         if (def_vram_cnt) {                       
153                 for (i = 0; i < def_vram_cnt;     
154                         fbdev->mem_desc.region    
155                                 PAGE_ALIGN(def    
156                 fbdev->mem_desc.region_cnt = i    
157         } else {                                  
158                 struct omapfb_platform_data *c    
159                                                   
160                 conf = fbdev->dev->platform_da    
161                 fbdev->mem_desc = conf->mem_de    
162         }                                         
163                                                   
164         if (!fbdev->mem_desc.region_cnt) {        
165                 struct lcd_panel *panel = fbde    
166                 int def_size;                     
167                 int bpp = panel->bpp;             
168                                                   
169                 /* 12 bpp is packed in 16 bits    
170                 if (bpp == 12)                    
171                         bpp = 16;                 
172                 def_size = def_vxres * def_vyr    
173                 fbdev->mem_desc.region_cnt = 1    
174                 fbdev->mem_desc.region[0].size    
175         }                                         
176         r = fbdev->ctrl->init(fbdev, 0, &fbdev    
177         if (r < 0) {                              
178                 dev_err(fbdev->dev, "controlle    
179                         r);                       
180                 return r;                         
181         }                                         
182                                                   
183 #ifdef DEBUG                                      
184         for (i = 0; i < fbdev->mem_desc.region    
185                 dev_dbg(fbdev->dev, "region%d     
186                          i,                       
187                          fbdev->mem_desc.regio    
188                          fbdev->mem_desc.regio    
189                          fbdev->mem_desc.regio    
190         }                                         
191 #endif                                            
192         return 0;                                 
193 }                                                 
194                                                   
195 static void ctrl_cleanup(struct omapfb_device     
196 {                                                 
197         fbdev->ctrl->cleanup();                   
198 }                                                 
199                                                   
200 /* Must be called with fbdev->rqueue_mutex hel    
201 static int ctrl_change_mode(struct fb_info *fb    
202 {                                                 
203         int r;                                    
204         unsigned long offset;                     
205         struct omapfb_plane_struct *plane = fb    
206         struct omapfb_device *fbdev = plane->f    
207         struct fb_var_screeninfo *var = &fbi->    
208                                                   
209         offset = var->yoffset * fbi->fix.line_    
210                  var->xoffset * var->bits_per_    
211                                                   
212         if (fbdev->ctrl->sync)                    
213                 fbdev->ctrl->sync();              
214         r = fbdev->ctrl->setup_plane(plane->id    
215                                  offset, var->    
216                                  plane->info.p    
217                                  var->xres, va    
218         if (fbdev->ctrl->set_scale != NULL)       
219                 r = fbdev->ctrl->set_scale(pla    
220                                    var->xres,     
221                                    plane->info    
222                                    plane->info    
223                                                   
224         return r;                                 
225 }                                                 
226                                                   
227 /*                                                
228  * -------------------------------------------    
229  * fbdev framework callbacks and the ioctl int    
230  * -------------------------------------------    
231  */                                               
232 /* Called each time the omapfb device is opene    
233 static int omapfb_open(struct fb_info *info, i    
234 {                                                 
235         return 0;                                 
236 }                                                 
237                                                   
238 static void omapfb_sync(struct fb_info *info);    
239                                                   
240 /* Called when the omapfb device is closed. We    
241  * gfx DMA operations are ended, before we ret    
242 static int omapfb_release(struct fb_info *info    
243 {                                                 
244         omapfb_sync(info);                        
245         return 0;                                 
246 }                                                 
247                                                   
248 /* Store a single color palette entry into a p    
249  * palette if one is available. For now we sup    
250  * the entry only to the pseudo palette.          
251  */                                               
252 static int _setcolreg(struct fb_info *info, u_    
253                         u_int blue, u_int tran    
254 {                                                 
255         struct omapfb_plane_struct *plane = in    
256         struct omapfb_device *fbdev = plane->f    
257         struct fb_var_screeninfo *var = &info-    
258         int r = 0;                                
259                                                   
260         switch (plane->color_mode) {              
261         case OMAPFB_COLOR_YUV422:                 
262         case OMAPFB_COLOR_YUV420:                 
263         case OMAPFB_COLOR_YUY422:                 
264                 r = -EINVAL;                      
265                 break;                            
266         case OMAPFB_COLOR_CLUT_8BPP:              
267         case OMAPFB_COLOR_CLUT_4BPP:              
268         case OMAPFB_COLOR_CLUT_2BPP:              
269         case OMAPFB_COLOR_CLUT_1BPP:              
270                 if (fbdev->ctrl->setcolreg)       
271                         r = fbdev->ctrl->setco    
272                                                   
273                 /* Fallthrough */                 
274         case OMAPFB_COLOR_RGB565:                 
275         case OMAPFB_COLOR_RGB444:                 
276                 if (r != 0)                       
277                         break;                    
278                                                   
279                 if (regno < 0) {                  
280                         r = -EINVAL;              
281                         break;                    
282                 }                                 
283                                                   
284                 if (regno < 16) {                 
285                         u16 pal;                  
286                         pal = ((red >> (16 - v    
287                                         var->r    
288                               ((green >> (16 -    
289                                         var->g    
290                               (blue >> (16 - v    
291                         ((u32 *)(info->pseudo_    
292                 }                                 
293                 break;                            
294         default:                                  
295                 BUG();                            
296         }                                         
297         return r;                                 
298 }                                                 
299                                                   
300 static int omapfb_setcolreg(u_int regno, u_int    
301                             u_int transp, stru    
302 {                                                 
303         return _setcolreg(info, regno, red, gr    
304 }                                                 
305                                                   
306 static int omapfb_setcmap(struct fb_cmap *cmap    
307 {                                                 
308         int count, index, r;                      
309         u16 *red, *green, *blue, *transp;         
310         u16 trans = 0xffff;                       
311                                                   
312         red     = cmap->red;                      
313         green   = cmap->green;                    
314         blue    = cmap->blue;                     
315         transp  = cmap->transp;                   
316         index   = cmap->start;                    
317                                                   
318         for (count = 0; count < cmap->len; cou    
319                 if (transp)                       
320                         trans = *transp++;        
321                 r = _setcolreg(info, index++,     
322                                 count == cmap-    
323                 if (r != 0)                       
324                         return r;                 
325         }                                         
326                                                   
327         return 0;                                 
328 }                                                 
329                                                   
330 static int omapfb_update_full_screen(struct fb    
331                                                   
332 static int omapfb_blank(int blank, struct fb_i    
333 {                                                 
334         struct omapfb_plane_struct *plane = fb    
335         struct omapfb_device *fbdev = plane->f    
336         int do_update = 0;                        
337         int r = 0;                                
338                                                   
339         omapfb_rqueue_lock(fbdev);                
340         switch (blank) {                          
341         case FB_BLANK_UNBLANK:                    
342                 if (fbdev->state == OMAPFB_SUS    
343                         if (fbdev->ctrl->resum    
344                                 fbdev->ctrl->r    
345                         fbdev->panel->enable(f    
346                         fbdev->state = OMAPFB_    
347                         if (fbdev->ctrl->get_u    
348                                         OMAPFB    
349                                 do_update = 1;    
350                 }                                 
351                 break;                            
352         case FB_BLANK_POWERDOWN:                  
353                 if (fbdev->state == OMAPFB_ACT    
354                         fbdev->panel->disable(    
355                         if (fbdev->ctrl->suspe    
356                                 fbdev->ctrl->s    
357                         fbdev->state = OMAPFB_    
358                 }                                 
359                 break;                            
360         default:                                  
361                 r = -EINVAL;                      
362         }                                         
363         omapfb_rqueue_unlock(fbdev);              
364                                                   
365         if (r == 0 && do_update)                  
366                 r = omapfb_update_full_screen(    
367                                                   
368         return r;                                 
369 }                                                 
370                                                   
371 static void omapfb_sync(struct fb_info *fbi)      
372 {                                                 
373         struct omapfb_plane_struct *plane = fb    
374         struct omapfb_device *fbdev = plane->f    
375                                                   
376         omapfb_rqueue_lock(fbdev);                
377         if (fbdev->ctrl->sync)                    
378                 fbdev->ctrl->sync();              
379         omapfb_rqueue_unlock(fbdev);              
380 }                                                 
381                                                   
382 /*                                                
383  * Set fb_info.fix fields and also updates fbd    
384  * When calling this fb_info.var must be set u    
385  */                                               
386 static void set_fb_fix(struct fb_info *fbi)       
387 {                                                 
388         struct fb_fix_screeninfo *fix = &fbi->    
389         struct fb_var_screeninfo *var = &fbi->    
390         struct omapfb_plane_struct *plane = fb    
391         struct omapfb_mem_region *rg;             
392         int bpp;                                  
393                                                   
394         rg = &plane->fbdev->mem_desc.region[pl    
395         fbi->screen_base        = rg->vaddr;      
396         mutex_lock(&fbi->mm_lock);                
397         fix->smem_start         = rg->paddr;      
398         fix->smem_len           = rg->size;       
399         mutex_unlock(&fbi->mm_lock);              
400                                                   
401         fix->type = FB_TYPE_PACKED_PIXELS;        
402         bpp = var->bits_per_pixel;                
403         if (var->nonstd)                          
404                 fix->visual = FB_VISUAL_PSEUDO    
405         else switch (var->bits_per_pixel) {       
406         case 16:                                  
407         case 12:                                  
408                 fix->visual = FB_VISUAL_TRUECO    
409                 /* 12bpp is stored in 16 bits     
410                 bpp = 16;                         
411                 break;                            
412         case 1:                                   
413         case 2:                                   
414         case 4:                                   
415         case 8:                                   
416                 fix->visual = FB_VISUAL_PSEUDO    
417                 break;                            
418         }                                         
419         fix->accel              = FB_ACCEL_OMA    
420         fix->line_length        = var->xres_vi    
421 }                                                 
422                                                   
423 static int set_color_mode(struct omapfb_plane_    
424                           struct fb_var_screen    
425 {                                                 
426         switch (var->nonstd) {                    
427         case 0:                                   
428                 break;                            
429         case OMAPFB_COLOR_YUV422:                 
430                 var->bits_per_pixel = 16;         
431                 plane->color_mode = var->nonst    
432                 return 0;                         
433         case OMAPFB_COLOR_YUV420:                 
434                 var->bits_per_pixel = 12;         
435                 plane->color_mode = var->nonst    
436                 return 0;                         
437         case OMAPFB_COLOR_YUY422:                 
438                 var->bits_per_pixel = 16;         
439                 plane->color_mode = var->nonst    
440                 return 0;                         
441         default:                                  
442                 return -EINVAL;                   
443         }                                         
444                                                   
445         switch (var->bits_per_pixel) {            
446         case 1:                                   
447                 plane->color_mode = OMAPFB_COL    
448                 return 0;                         
449         case 2:                                   
450                 plane->color_mode = OMAPFB_COL    
451                 return 0;                         
452         case 4:                                   
453                 plane->color_mode = OMAPFB_COL    
454                 return 0;                         
455         case 8:                                   
456                 plane->color_mode = OMAPFB_COL    
457                 return 0;                         
458         case 12:                                  
459                 var->bits_per_pixel = 16;         
460                 plane->color_mode = OMAPFB_COL    
461                 return 0;                         
462         case 16:                                  
463                 plane->color_mode = OMAPFB_COL    
464                 return 0;                         
465         default:                                  
466                 return -EINVAL;                   
467         }                                         
468 }                                                 
469                                                   
470 /*                                                
471  * Check the values in var against our capabil    
472  * bound values try to adjust them.               
473  */                                               
474 static int set_fb_var(struct fb_info *fbi,        
475                       struct fb_var_screeninfo    
476 {                                                 
477         int             bpp;                      
478         unsigned long   max_frame_size;           
479         unsigned long   line_size;                
480         int             xres_min, xres_max;       
481         int             yres_min, yres_max;       
482         struct omapfb_plane_struct *plane = fb    
483         struct omapfb_device *fbdev = plane->f    
484         struct lcd_panel *panel = fbdev->panel    
485                                                   
486         if (set_color_mode(plane, var) < 0)       
487                 return -EINVAL;                   
488                                                   
489         bpp = var->bits_per_pixel;                
490         if (plane->color_mode == OMAPFB_COLOR_    
491                 bpp = 16;                         
492                                                   
493         switch (var->rotate) {                    
494         case 0:                                   
495         case 180:                                 
496                 xres_min = OMAPFB_PLANE_XRES_M    
497                 xres_max = panel->x_res;          
498                 yres_min = OMAPFB_PLANE_YRES_M    
499                 yres_max = panel->y_res;          
500                 if (cpu_is_omap15xx()) {          
501                         var->xres = panel->x_r    
502                         var->yres = panel->y_r    
503                 }                                 
504                 break;                            
505         case 90:                                  
506         case 270:                                 
507                 xres_min = OMAPFB_PLANE_YRES_M    
508                 xres_max = panel->y_res;          
509                 yres_min = OMAPFB_PLANE_XRES_M    
510                 yres_max = panel->x_res;          
511                 if (cpu_is_omap15xx()) {          
512                         var->xres = panel->y_r    
513                         var->yres = panel->x_r    
514                 }                                 
515                 break;                            
516         default:                                  
517                 return -EINVAL;                   
518         }                                         
519                                                   
520         if (var->xres < xres_min)                 
521                 var->xres = xres_min;             
522         if (var->yres < yres_min)                 
523                 var->yres = yres_min;             
524         if (var->xres > xres_max)                 
525                 var->xres = xres_max;             
526         if (var->yres > yres_max)                 
527                 var->yres = yres_max;             
528                                                   
529         if (var->xres_virtual < var->xres)        
530                 var->xres_virtual = var->xres;    
531         if (var->yres_virtual < var->yres)        
532                 var->yres_virtual = var->yres;    
533         max_frame_size = fbdev->mem_desc.regio    
534         line_size = var->xres_virtual * bpp /     
535         if (line_size * var->yres_virtual > ma    
536                 /* Try to keep yres_virtual fi    
537                 line_size = max_frame_size / v    
538                 var->xres_virtual = line_size     
539                 if (var->xres_virtual < var->x    
540                         /* Still doesn't fit.     
541                         var->xres_virtual = va    
542                         line_size = var->xres     
543                         var->yres_virtual = ma    
544                 }                                 
545                 /* Recheck this, as the virtua    
546                 if (var->xres_virtual < var->x    
547                         var->xres = var->xres_    
548                 if (var->yres_virtual < var->y    
549                         var->yres = var->yres_    
550                 if (var->xres < xres_min || va    
551                         return -EINVAL;           
552         }                                         
553         if (var->xres + var->xoffset > var->xr    
554                 var->xoffset = var->xres_virtu    
555         if (var->yres + var->yoffset > var->yr    
556                 var->yoffset = var->yres_virtu    
557         line_size = var->xres * bpp / 8;          
558                                                   
559         if (plane->color_mode == OMAPFB_COLOR_    
560                 var->red.offset   = 8; var->re    
561                                                   
562                 var->green.offset = 4; var->gr    
563                                                   
564                 var->blue.offset  = 0; var->bl    
565                                                   
566         } else {                                  
567                 var->red.offset  = 11; var->re    
568                                                   
569                 var->green.offset = 5;  var->g    
570                                                   
571                 var->blue.offset = 0;  var->bl    
572                                                   
573         }                                         
574                                                   
575         var->height             = -1;             
576         var->width              = -1;             
577         var->grayscale          = 0;              
578                                                   
579         /* pixclock in ps, the rest in pixcloc    
580         var->pixclock           = 10000000 / (    
581         var->left_margin        = panel->hfp;     
582         var->right_margin       = panel->hbp;     
583         var->upper_margin       = panel->vfp;     
584         var->lower_margin       = panel->vbp;     
585         var->hsync_len          = panel->hsw;     
586         var->vsync_len          = panel->vsw;     
587                                                   
588         /* TODO: get these from panel->config     
589         var->vmode              = FB_VMODE_NON    
590         var->sync               = 0;              
591                                                   
592         return 0;                                 
593 }                                                 
594                                                   
595                                                   
596 /* Set rotation (0, 90, 180, 270 degree), and     
597 static void omapfb_rotate(struct fb_info *fbi,    
598 {                                                 
599         struct omapfb_plane_struct *plane = fb    
600         struct omapfb_device *fbdev = plane->f    
601                                                   
602         omapfb_rqueue_lock(fbdev);                
603         if (cpu_is_omap15xx() && rotate != fbi    
604                 struct fb_var_screeninfo *new_    
605                                                   
606                 memcpy(new_var, &fbi->var, siz    
607                 new_var->rotate = rotate;         
608                 if (set_fb_var(fbi, new_var) =    
609                     memcmp(new_var, &fbi->var,    
610                         memcpy(&fbi->var, new_    
611                         ctrl_change_mode(fbi);    
612                 }                                 
613         }                                         
614         omapfb_rqueue_unlock(fbdev);              
615 }                                                 
616                                                   
617 /*                                                
618  * Set new x,y offsets in the virtual display     
619  * to the new mode.                               
620  */                                               
621 static int omapfb_pan_display(struct fb_var_sc    
622                                struct fb_info     
623 {                                                 
624         struct omapfb_plane_struct *plane = fb    
625         struct omapfb_device *fbdev = plane->f    
626         int r = 0;                                
627                                                   
628         omapfb_rqueue_lock(fbdev);                
629         if (var->xoffset != fbi->var.xoffset |    
630             var->yoffset != fbi->var.yoffset)     
631                 struct fb_var_screeninfo *new_    
632                                                   
633                 memcpy(new_var, &fbi->var, siz    
634                 new_var->xoffset = var->xoffse    
635                 new_var->yoffset = var->yoffse    
636                 if (set_fb_var(fbi, new_var))     
637                         r = -EINVAL;              
638                 else {                            
639                         memcpy(&fbi->var, new_    
640                         ctrl_change_mode(fbi);    
641                 }                                 
642         }                                         
643         omapfb_rqueue_unlock(fbdev);              
644                                                   
645         return r;                                 
646 }                                                 
647                                                   
648 /* Set mirror to vertical axis and switch to t    
649 static int omapfb_mirror(struct fb_info *fbi,     
650 {                                                 
651         struct omapfb_plane_struct *plane = fb    
652         struct omapfb_device *fbdev = plane->f    
653         int r = 0;                                
654                                                   
655         omapfb_rqueue_lock(fbdev);                
656         mirror = mirror ? 1 : 0;                  
657         if (cpu_is_omap15xx())                    
658                 r = -EINVAL;                      
659         else if (mirror != plane->info.mirror)    
660                 plane->info.mirror = mirror;      
661                 r = ctrl_change_mode(fbi);        
662         }                                         
663         omapfb_rqueue_unlock(fbdev);              
664                                                   
665         return r;                                 
666 }                                                 
667                                                   
668 /*                                                
669  * Check values in var, try to adjust them in     
670  * possible, or return error.                     
671  */                                               
672 static int omapfb_check_var(struct fb_var_scre    
673 {                                                 
674         struct omapfb_plane_struct *plane = fb    
675         struct omapfb_device *fbdev = plane->f    
676         int r;                                    
677                                                   
678         omapfb_rqueue_lock(fbdev);                
679         if (fbdev->ctrl->sync != NULL)            
680                 fbdev->ctrl->sync();              
681         r = set_fb_var(fbi, var);                 
682         omapfb_rqueue_unlock(fbdev);              
683                                                   
684         return r;                                 
685 }                                                 
686                                                   
687 /*                                                
688  * Switch to a new mode. The parameters for it    
689  * omapfb_check_var.                              
690  */                                               
691 static int omapfb_set_par(struct fb_info *fbi)    
692 {                                                 
693         struct omapfb_plane_struct *plane = fb    
694         struct omapfb_device *fbdev = plane->f    
695         int r = 0;                                
696                                                   
697         omapfb_rqueue_lock(fbdev);                
698         set_fb_fix(fbi);                          
699         r = ctrl_change_mode(fbi);                
700         omapfb_rqueue_unlock(fbdev);              
701                                                   
702         return r;                                 
703 }                                                 
704                                                   
705 int omapfb_update_window_async(struct fb_info     
706                                 struct omapfb_    
707                                 void (*callbac    
708                                 void *callback    
709 {                                                 
710         struct omapfb_plane_struct *plane = fb    
711         struct omapfb_device *fbdev = plane->f    
712         struct fb_var_screeninfo *var;            
713                                                   
714         var = &fbi->var;                          
715         if (win->x >= var->xres || win->y >= v    
716             win->out_x > var->xres || win->out    
717                 return -EINVAL;                   
718                                                   
719         if (!fbdev->ctrl->update_window ||        
720             fbdev->ctrl->get_update_mode() !=     
721                 return -ENODEV;                   
722                                                   
723         if (win->x + win->width >= var->xres)     
724                 win->width = var->xres - win->    
725         if (win->y + win->height >= var->yres)    
726                 win->height = var->yres - win-    
727         /* The out sizes should be cropped to     
728         if (win->out_x + win->out_width > fbde    
729                 win->out_width = fbdev->panel-    
730         if (win->out_y + win->out_height > fbd    
731                 win->out_height = fbdev->panel    
732         if (!win->width || !win->height || !wi    
733                 return 0;                         
734                                                   
735         return fbdev->ctrl->update_window(fbi,    
736 }                                                 
737 EXPORT_SYMBOL(omapfb_update_window_async);        
738                                                   
739 static int omapfb_update_win(struct fb_info *f    
740                                 struct omapfb_    
741 {                                                 
742         struct omapfb_plane_struct *plane = fb    
743         int ret;                                  
744                                                   
745         omapfb_rqueue_lock(plane->fbdev);         
746         ret = omapfb_update_window_async(fbi,     
747         omapfb_rqueue_unlock(plane->fbdev);       
748                                                   
749         return ret;                               
750 }                                                 
751                                                   
752 static int omapfb_update_full_screen(struct fb    
753 {                                                 
754         struct omapfb_plane_struct *plane = fb    
755         struct omapfb_device *fbdev = plane->f    
756         struct omapfb_update_window win;          
757         int r;                                    
758                                                   
759         if (!fbdev->ctrl->update_window ||        
760             fbdev->ctrl->get_update_mode() !=     
761                 return -ENODEV;                   
762                                                   
763         win.x = 0;                                
764         win.y = 0;                                
765         win.width = fbi->var.xres;                
766         win.height = fbi->var.yres;               
767         win.out_x = 0;                            
768         win.out_y = 0;                            
769         win.out_width = fbi->var.xres;            
770         win.out_height = fbi->var.yres;           
771         win.format = 0;                           
772                                                   
773         omapfb_rqueue_lock(fbdev);                
774         r = fbdev->ctrl->update_window(fbi, &w    
775         omapfb_rqueue_unlock(fbdev);              
776                                                   
777         return r;                                 
778 }                                                 
779                                                   
780 static int omapfb_setup_plane(struct fb_info *    
781 {                                                 
782         struct omapfb_plane_struct *plane = fb    
783         struct omapfb_device *fbdev = plane->f    
784         struct lcd_panel *panel = fbdev->panel    
785         struct omapfb_plane_info old_info;        
786         int r = 0;                                
787                                                   
788         if (pi->pos_x + pi->out_width > panel-    
789             pi->pos_y + pi->out_height > panel    
790                 return -EINVAL;                   
791                                                   
792         omapfb_rqueue_lock(fbdev);                
793         if (pi->enabled && !fbdev->mem_desc.re    
794                 /*                                
795                  * This plane's memory was fre    
796                  * until it's reallocated.        
797                  */                               
798                 r = -EINVAL;                      
799                 goto out;                         
800         }                                         
801         old_info = plane->info;                   
802         plane->info = *pi;                        
803         if (pi->enabled) {                        
804                 r = ctrl_change_mode(fbi);        
805                 if (r < 0) {                      
806                         plane->info = old_info    
807                         goto out;                 
808                 }                                 
809         }                                         
810         r = fbdev->ctrl->enable_plane(plane->i    
811         if (r < 0) {                              
812                 plane->info = old_info;           
813                 goto out;                         
814         }                                         
815 out:                                              
816         omapfb_rqueue_unlock(fbdev);              
817         return r;                                 
818 }                                                 
819                                                   
820 static int omapfb_query_plane(struct fb_info *    
821 {                                                 
822         struct omapfb_plane_struct *plane = fb    
823                                                   
824         *pi = plane->info;                        
825         return 0;                                 
826 }                                                 
827                                                   
828 static int omapfb_setup_mem(struct fb_info *fb    
829 {                                                 
830         struct omapfb_plane_struct *plane = fb    
831         struct omapfb_device *fbdev = plane->f    
832         struct omapfb_mem_region *rg = &fbdev-    
833         size_t size;                              
834         int r = 0;                                
835                                                   
836         if (fbdev->ctrl->setup_mem == NULL)       
837                 return -ENODEV;                   
838         if (mi->type > OMAPFB_MEMTYPE_MAX)        
839                 return -EINVAL;                   
840                                                   
841         size = PAGE_ALIGN(mi->size);              
842         omapfb_rqueue_lock(fbdev);                
843         if (plane->info.enabled) {                
844                 r = -EBUSY;                       
845                 goto out;                         
846         }                                         
847         if (rg->size != size || rg->type != mi    
848                 struct fb_var_screeninfo *new_    
849                 unsigned long old_size = rg->s    
850                 u8            old_type = rg->t    
851                 unsigned long paddr;              
852                                                   
853                 rg->size = size;                  
854                 rg->type = mi->type;              
855                 /*                                
856                  * size == 0 is a special case    
857                  * don't check / adjust the sc    
858                  * This isn't a problem since     
859                  * be reenabled unless its siz    
860                  */                               
861                 if (old_size != size && size)     
862                         if (size) {               
863                                 memcpy(new_var    
864                                 r = set_fb_var    
865                                 if (r < 0)        
866                                         goto o    
867                         }                         
868                 }                                 
869                                                   
870                 if (fbdev->ctrl->sync)            
871                         fbdev->ctrl->sync();      
872                 r = fbdev->ctrl->setup_mem(pla    
873                 if (r < 0) {                      
874                         /* Revert changes. */     
875                         rg->size = old_size;      
876                         rg->type = old_type;      
877                         goto out;                 
878                 }                                 
879                 rg->paddr = paddr;                
880                                                   
881                 if (old_size != size) {           
882                         if (size) {               
883                                 memcpy(&fbi->v    
884                                 set_fb_fix(fbi    
885                         } else {                  
886                                 /*                
887                                  * Set these e    
888                                  * plane memor    
889                                  * screen para    
890                                  */               
891                                 mutex_lock(&fb    
892                                 fbi->fix.smem_    
893                                 fbi->fix.smem_    
894                                 mutex_unlock(&    
895                         }                         
896                 }                                 
897         }                                         
898 out:                                              
899         omapfb_rqueue_unlock(fbdev);              
900                                                   
901         return r;                                 
902 }                                                 
903                                                   
904 static int omapfb_query_mem(struct fb_info *fb    
905 {                                                 
906         struct omapfb_plane_struct *plane = fb    
907         struct omapfb_device *fbdev = plane->f    
908         struct omapfb_mem_region *rg;             
909                                                   
910         rg = &fbdev->mem_desc.region[plane->id    
911         memset(mi, 0, sizeof(*mi));               
912         mi->size = rg->size;                      
913         mi->type = rg->type;                      
914                                                   
915         return 0;                                 
916 }                                                 
917                                                   
918 static int omapfb_set_color_key(struct omapfb_    
919                                 struct omapfb_    
920 {                                                 
921         int r;                                    
922                                                   
923         if (!fbdev->ctrl->set_color_key)          
924                 return -ENODEV;                   
925                                                   
926         omapfb_rqueue_lock(fbdev);                
927         r = fbdev->ctrl->set_color_key(ck);       
928         omapfb_rqueue_unlock(fbdev);              
929                                                   
930         return r;                                 
931 }                                                 
932                                                   
933 static int omapfb_get_color_key(struct omapfb_    
934                                 struct omapfb_    
935 {                                                 
936         int r;                                    
937                                                   
938         if (!fbdev->ctrl->get_color_key)          
939                 return -ENODEV;                   
940                                                   
941         omapfb_rqueue_lock(fbdev);                
942         r = fbdev->ctrl->get_color_key(ck);       
943         omapfb_rqueue_unlock(fbdev);              
944                                                   
945         return r;                                 
946 }                                                 
947                                                   
948 static struct blocking_notifier_head omapfb_cl    
949 static int notifier_inited;                       
950                                                   
951 static void omapfb_init_notifier(void)            
952 {                                                 
953         int i;                                    
954                                                   
955         for (i = 0; i < OMAPFB_PLANE_NUM; i++)    
956                 BLOCKING_INIT_NOTIFIER_HEAD(&o    
957 }                                                 
958                                                   
959 int omapfb_register_client(struct omapfb_notif    
960                                 omapfb_notifie    
961                                 void *callback    
962 {                                                 
963         int r;                                    
964                                                   
965         if ((unsigned)omapfb_nb->plane_idx > O    
966                 return -EINVAL;                   
967                                                   
968         if (!notifier_inited) {                   
969                 omapfb_init_notifier();           
970                 notifier_inited = 1;              
971         }                                         
972                                                   
973         omapfb_nb->nb.notifier_call = (int (*)    
974                                         unsign    
975         omapfb_nb->data = callback_data;          
976         r = blocking_notifier_chain_register(     
977                                 &omapfb_client    
978                                 &omapfb_nb->nb    
979         if (r)                                    
980                 return r;                         
981         if (omapfb_dev != NULL &&                 
982             omapfb_dev->ctrl && omapfb_dev->ct    
983                 omapfb_dev->ctrl->bind_client(    
984         }                                         
985                                                   
986         return 0;                                 
987 }                                                 
988 EXPORT_SYMBOL(omapfb_register_client);            
989                                                   
990 int omapfb_unregister_client(struct omapfb_not    
991 {                                                 
992         return blocking_notifier_chain_unregis    
993                 &omapfb_client_list[omapfb_nb-    
994 }                                                 
995 EXPORT_SYMBOL(omapfb_unregister_client);          
996                                                   
997 void omapfb_notify_clients(struct omapfb_devic    
998 {                                                 
999         int i;                                    
1000                                                  
1001         if (!notifier_inited)                    
1002                 /* no client registered yet *    
1003                 return;                          
1004                                                  
1005         for (i = 0; i < OMAPFB_PLANE_NUM; i++    
1006                 blocking_notifier_call_chain(    
1007                                     fbdev->fb    
1008 }                                                
1009 EXPORT_SYMBOL(omapfb_notify_clients);            
1010                                                  
1011 static int omapfb_set_update_mode(struct omap    
1012                                    enum omapf    
1013 {                                                
1014         int r;                                   
1015                                                  
1016         omapfb_rqueue_lock(fbdev);               
1017         r = fbdev->ctrl->set_update_mode(mode    
1018         omapfb_rqueue_unlock(fbdev);             
1019                                                  
1020         return r;                                
1021 }                                                
1022                                                  
1023 static enum omapfb_update_mode omapfb_get_upd    
1024 {                                                
1025         int r;                                   
1026                                                  
1027         omapfb_rqueue_lock(fbdev);               
1028         r = fbdev->ctrl->get_update_mode();      
1029         omapfb_rqueue_unlock(fbdev);             
1030                                                  
1031         return r;                                
1032 }                                                
1033                                                  
1034 static void omapfb_get_caps(struct omapfb_dev    
1035                                      struct o    
1036 {                                                
1037         memset(caps, 0, sizeof(*caps));          
1038         fbdev->ctrl->get_caps(plane, caps);      
1039         caps->ctrl |= fbdev->panel->get_caps(    
1040 }                                                
1041                                                  
1042 /* For lcd testing */                            
1043 void omapfb_write_first_pixel(struct omapfb_d    
1044 {                                                
1045         omapfb_rqueue_lock(fbdev);               
1046         *(u16 *)fbdev->mem_desc.region[0].vad    
1047         if (fbdev->ctrl->get_update_mode() ==    
1048                 struct omapfb_update_window w    
1049                                                  
1050                 memset(&win, 0, sizeof(win));    
1051                 win.width = 2;                   
1052                 win.height = 2;                  
1053                 win.out_width = 2;               
1054                 win.out_height = 2;              
1055                 fbdev->ctrl->update_window(fb    
1056         }                                        
1057         omapfb_rqueue_unlock(fbdev);             
1058 }                                                
1059 EXPORT_SYMBOL(omapfb_write_first_pixel);         
1060                                                  
1061 /*                                               
1062  * Ioctl interface. Part of the kernel mode f    
1063  * here to be accessible by user mode code.      
1064  */                                              
1065 static int omapfb_ioctl(struct fb_info *fbi,     
1066                         unsigned long arg)       
1067 {                                                
1068         struct omapfb_plane_struct *plane = f    
1069         struct omapfb_device    *fbdev = plan    
1070         struct fb_ops           *ops = fbi->f    
1071         union {                                  
1072                 struct omapfb_update_window      
1073                 struct omapfb_plane_info         
1074                 struct omapfb_mem_info           
1075                 struct omapfb_color_key          
1076                 enum omapfb_update_mode          
1077                 struct omapfb_caps               
1078                 unsigned int            mirro    
1079                 int                     plane    
1080                 int                     enabl    
1081         } p;                                     
1082         int r = 0;                               
1083                                                  
1084         BUG_ON(!ops);                            
1085         switch (cmd) {                           
1086         case OMAPFB_MIRROR:                      
1087                 if (get_user(p.mirror, (int _    
1088                         r = -EFAULT;             
1089                 else                             
1090                         omapfb_mirror(fbi, p.    
1091                 break;                           
1092         case OMAPFB_SYNC_GFX:                    
1093                 omapfb_sync(fbi);                
1094                 break;                           
1095         case OMAPFB_VSYNC:                       
1096                 break;                           
1097         case OMAPFB_SET_UPDATE_MODE:             
1098                 if (get_user(p.update_mode, (    
1099                         r = -EFAULT;             
1100                 else                             
1101                         r = omapfb_set_update    
1102                 break;                           
1103         case OMAPFB_GET_UPDATE_MODE:             
1104                 p.update_mode = omapfb_get_up    
1105                 if (put_user(p.update_mode,      
1106                                         (enum    
1107                         r = -EFAULT;             
1108                 break;                           
1109         case OMAPFB_UPDATE_WINDOW_OLD:           
1110                 if (copy_from_user(&p.update_    
1111                                    sizeof(str    
1112                         r = -EFAULT;             
1113                 else {                           
1114                         struct omapfb_update_    
1115                         u->out_x = u->x;         
1116                         u->out_y = u->y;         
1117                         u->out_width = u->wid    
1118                         u->out_height = u->he    
1119                         memset(u->reserved, 0    
1120                         r = omapfb_update_win    
1121                 }                                
1122                 break;                           
1123         case OMAPFB_UPDATE_WINDOW:               
1124                 if (copy_from_user(&p.update_    
1125                                    sizeof(p.u    
1126                         r = -EFAULT;             
1127                 else                             
1128                         r = omapfb_update_win    
1129                 break;                           
1130         case OMAPFB_SETUP_PLANE:                 
1131                 if (copy_from_user(&p.plane_i    
1132                                    sizeof(p.p    
1133                         r = -EFAULT;             
1134                 else                             
1135                         r = omapfb_setup_plan    
1136                 break;                           
1137         case OMAPFB_QUERY_PLANE:                 
1138                 if ((r = omapfb_query_plane(f    
1139                         break;                   
1140                 if (copy_to_user((void __user    
1141                                    sizeof(p.p    
1142                         r = -EFAULT;             
1143                 break;                           
1144         case OMAPFB_SETUP_MEM:                   
1145                 if (copy_from_user(&p.mem_inf    
1146                                    sizeof(p.m    
1147                         r = -EFAULT;             
1148                 else                             
1149                         r = omapfb_setup_mem(    
1150                 break;                           
1151         case OMAPFB_QUERY_MEM:                   
1152                 if ((r = omapfb_query_mem(fbi    
1153                         break;                   
1154                 if (copy_to_user((void __user    
1155                                    sizeof(p.m    
1156                         r = -EFAULT;             
1157                 break;                           
1158         case OMAPFB_SET_COLOR_KEY:               
1159                 if (copy_from_user(&p.color_k    
1160                                    sizeof(p.c    
1161                         r = -EFAULT;             
1162                 else                             
1163                         r = omapfb_set_color_    
1164                 break;                           
1165         case OMAPFB_GET_COLOR_KEY:               
1166                 if ((r = omapfb_get_color_key    
1167                         break;                   
1168                 if (copy_to_user((void __user    
1169                                  sizeof(p.col    
1170                         r = -EFAULT;             
1171                 break;                           
1172         case OMAPFB_GET_CAPS:                    
1173                 omapfb_get_caps(fbdev, plane-    
1174                 if (copy_to_user((void __user    
1175                         r = -EFAULT;             
1176                 break;                           
1177         case OMAPFB_LCD_TEST:                    
1178                 {                                
1179                         int test_num;            
1180                                                  
1181                         if (get_user(test_num    
1182                                 r = -EFAULT;     
1183                                 break;           
1184                         }                        
1185                         if (!fbdev->panel->ru    
1186                                 r = -EINVAL;     
1187                                 break;           
1188                         }                        
1189                         r = fbdev->panel->run    
1190                         break;                   
1191                 }                                
1192         case OMAPFB_CTRL_TEST:                   
1193                 {                                
1194                         int test_num;            
1195                                                  
1196                         if (get_user(test_num    
1197                                 r = -EFAULT;     
1198                                 break;           
1199                         }                        
1200                         if (!fbdev->ctrl->run    
1201                                 r = -EINVAL;     
1202                                 break;           
1203                         }                        
1204                         r = fbdev->ctrl->run_    
1205                         break;                   
1206                 }                                
1207         default:                                 
1208                 r = -EINVAL;                     
1209         }                                        
1210                                                  
1211         return r;                                
1212 }                                                
1213                                                  
1214 static int omapfb_mmap(struct fb_info *info,     
1215 {                                                
1216         struct omapfb_plane_struct *plane = i    
1217         struct omapfb_device *fbdev = plane->    
1218         int r;                                   
1219                                                  
1220         omapfb_rqueue_lock(fbdev);               
1221         r = fbdev->ctrl->mmap(info, vma);        
1222         omapfb_rqueue_unlock(fbdev);             
1223                                                  
1224         return r;                                
1225 }                                                
1226                                                  
1227 /*                                               
1228  * Callback table for the frame buffer framew    
1229  * will be changed according to the current s    
1230  */                                              
1231 static struct fb_ops omapfb_ops = {              
1232         .owner          = THIS_MODULE,           
1233         .fb_open        = omapfb_open,           
1234         .fb_release     = omapfb_release,        
1235         .fb_setcolreg   = omapfb_setcolreg,      
1236         .fb_setcmap     = omapfb_setcmap,        
1237         .fb_fillrect    = cfb_fillrect,          
1238         .fb_copyarea    = cfb_copyarea,          
1239         .fb_imageblit   = cfb_imageblit,         
1240         .fb_blank       = omapfb_blank,          
1241         .fb_ioctl       = omapfb_ioctl,          
1242         .fb_check_var   = omapfb_check_var,      
1243         .fb_set_par     = omapfb_set_par,        
1244         .fb_rotate      = omapfb_rotate,         
1245         .fb_pan_display = omapfb_pan_display,    
1246 };                                               
1247                                                  
1248 /*                                               
1249  * ------------------------------------------    
1250  * Sysfs interface                               
1251  * ------------------------------------------    
1252  */                                              
1253 /* omapfbX sysfs entries */                      
1254 static ssize_t omapfb_show_caps_num(struct de    
1255                                     struct de    
1256 {                                                
1257         struct omapfb_device *fbdev = dev_get    
1258         int plane;                               
1259         size_t size;                             
1260         struct omapfb_caps caps;                 
1261                                                  
1262         plane = 0;                               
1263         size = 0;                                
1264         while (size < PAGE_SIZE && plane < OM    
1265                 omapfb_get_caps(fbdev, plane,    
1266                 size += snprintf(&buf[size],     
1267                         "plane#%d %#010x %#01    
1268                         plane, caps.ctrl, cap    
1269                 plane++;                         
1270         }                                        
1271         return size;                             
1272 }                                                
1273                                                  
1274 static ssize_t omapfb_show_caps_text(struct d    
1275                                      struct d    
1276 {                                                
1277         struct omapfb_device *fbdev = dev_get    
1278         int i;                                   
1279         struct omapfb_caps caps;                 
1280         int plane;                               
1281         size_t size;                             
1282                                                  
1283         plane = 0;                               
1284         size = 0;                                
1285         while (size < PAGE_SIZE && plane < OM    
1286                 omapfb_get_caps(fbdev, plane,    
1287                 size += snprintf(&buf[size],     
1288                                  "plane#%d:\n    
1289                 for (i = 0; i < ARRAY_SIZE(ct    
1290                      size < PAGE_SIZE; i++) {    
1291                         if (ctrl_caps[i].flag    
1292                                 size += snpri    
1293                                         " %s\    
1294                 }                                
1295                 size += snprintf(&buf[size],     
1296                                  " plane colo    
1297                 for (i = 0; i < ARRAY_SIZE(co    
1298                      size < PAGE_SIZE; i++) {    
1299                         if (color_caps[i].fla    
1300                                 size += snpri    
1301                                         "  %s    
1302                 }                                
1303                 size += snprintf(&buf[size],     
1304                                  " window col    
1305                 for (i = 0; i < ARRAY_SIZE(co    
1306                      size < PAGE_SIZE; i++) {    
1307                         if (color_caps[i].fla    
1308                                 size += snpri    
1309                                         "  %s    
1310                 }                                
1311                                                  
1312                 plane++;                         
1313         }                                        
1314         return size;                             
1315 }                                                
1316                                                  
1317 static DEVICE_ATTR(caps_num, 0444, omapfb_sho    
1318 static DEVICE_ATTR(caps_text, 0444, omapfb_sh    
1319                                                  
1320 /* panel sysfs entries */                        
1321 static ssize_t omapfb_show_panel_name(struct     
1322                                       struct     
1323 {                                                
1324         struct omapfb_device *fbdev = dev_get    
1325                                                  
1326         return snprintf(buf, PAGE_SIZE, "%s\n    
1327 }                                                
1328                                                  
1329 static ssize_t omapfb_show_bklight_level(stru    
1330                                          stru    
1331                                          char    
1332 {                                                
1333         struct omapfb_device *fbdev = dev_get    
1334         int r;                                   
1335                                                  
1336         if (fbdev->panel->get_bklight_level)     
1337                 r = snprintf(buf, PAGE_SIZE,     
1338                              fbdev->panel->ge    
1339         } else                                   
1340                 r = -ENODEV;                     
1341         return r;                                
1342 }                                                
1343                                                  
1344 static ssize_t omapfb_store_bklight_level(str    
1345                                           str    
1346                                           con    
1347 {                                                
1348         struct omapfb_device *fbdev = dev_get    
1349         int r;                                   
1350                                                  
1351         if (fbdev->panel->set_bklight_level)     
1352                 unsigned int level;              
1353                                                  
1354                 if (sscanf(buf, "%10d", &leve    
1355                         r = fbdev->panel->set    
1356                                                  
1357                 } else                           
1358                         r = -EINVAL;             
1359         } else                                   
1360                 r = -ENODEV;                     
1361         return r ? r : size;                     
1362 }                                                
1363                                                  
1364 static ssize_t omapfb_show_bklight_max(struct    
1365                                        struct    
1366 {                                                
1367         struct omapfb_device *fbdev = dev_get    
1368         int r;                                   
1369                                                  
1370         if (fbdev->panel->get_bklight_level)     
1371                 r = snprintf(buf, PAGE_SIZE,     
1372                              fbdev->panel->ge    
1373         } else                                   
1374                 r = -ENODEV;                     
1375         return r;                                
1376 }                                                
1377                                                  
1378 static struct device_attribute dev_attr_panel    
1379         __ATTR(name, 0444, omapfb_show_panel_    
1380 static DEVICE_ATTR(backlight_level, 0664,        
1381                    omapfb_show_bklight_level,    
1382 static DEVICE_ATTR(backlight_max, 0444, omapf    
1383                                                  
1384 static struct attribute *panel_attrs[] = {       
1385         &dev_attr_panel_name.attr,               
1386         &dev_attr_backlight_level.attr,          
1387         &dev_attr_backlight_max.attr,            
1388         NULL,                                    
1389 };                                               
1390                                                  
1391 static struct attribute_group panel_attr_grp     
1392         .name  = "panel",                        
1393         .attrs = panel_attrs,                    
1394 };                                               
1395                                                  
1396 /* ctrl sysfs entries */                         
1397 static ssize_t omapfb_show_ctrl_name(struct d    
1398                                      struct d    
1399 {                                                
1400         struct omapfb_device *fbdev = dev_get    
1401                                                  
1402         return snprintf(buf, PAGE_SIZE, "%s\n    
1403 }                                                
1404                                                  
1405 static struct device_attribute dev_attr_ctrl_    
1406         __ATTR(name, 0444, omapfb_show_ctrl_n    
1407                                                  
1408 static struct attribute *ctrl_attrs[] = {        
1409         &dev_attr_ctrl_name.attr,                
1410         NULL,                                    
1411 };                                               
1412                                                  
1413 static struct attribute_group ctrl_attr_grp =    
1414         .name  = "ctrl",                         
1415         .attrs = ctrl_attrs,                     
1416 };                                               
1417                                                  
1418 static int omapfb_register_sysfs(struct omapf    
1419 {                                                
1420         int r;                                   
1421                                                  
1422         if ((r = device_create_file(fbdev->de    
1423                 goto fail0;                      
1424                                                  
1425         if ((r = device_create_file(fbdev->de    
1426                 goto fail1;                      
1427                                                  
1428         if ((r = sysfs_create_group(&fbdev->d    
1429                 goto fail2;                      
1430                                                  
1431         if ((r = sysfs_create_group(&fbdev->d    
1432                 goto fail3;                      
1433                                                  
1434         return 0;                                
1435 fail3:                                           
1436         sysfs_remove_group(&fbdev->dev->kobj,    
1437 fail2:                                           
1438         device_remove_file(fbdev->dev, &dev_a    
1439 fail1:                                           
1440         device_remove_file(fbdev->dev, &dev_a    
1441 fail0:                                           
1442         dev_err(fbdev->dev, "unable to regist    
1443         return r;                                
1444 }                                                
1445                                                  
1446 static void omapfb_unregister_sysfs(struct om    
1447 {                                                
1448         sysfs_remove_group(&fbdev->dev->kobj,    
1449         sysfs_remove_group(&fbdev->dev->kobj,    
1450         device_remove_file(fbdev->dev, &dev_a    
1451         device_remove_file(fbdev->dev, &dev_a    
1452 }                                                
1453                                                  
1454 /*                                               
1455  * ------------------------------------------    
1456  * LDM callbacks                                 
1457  * ------------------------------------------    
1458  */                                              
1459 /* Initialize system fb_info object and set t    
1460  * The frame buffer memory already allocated     
1461  */                                              
1462 static int fbinfo_init(struct omapfb_device *    
1463 {                                                
1464         struct fb_var_screeninfo        *var     
1465         struct fb_fix_screeninfo        *fix     
1466         int                             r = 0    
1467                                                  
1468         info->fbops = &omapfb_ops;               
1469         info->flags = FBINFO_FLAG_DEFAULT;       
1470                                                  
1471         strncpy(fix->id, MODULE_NAME, sizeof(    
1472                                                  
1473         info->pseudo_palette = fbdev->pseudo_    
1474                                                  
1475         var->accel_flags  = def_accel ? FB_AC    
1476         var->xres = def_vxres;                   
1477         var->yres = def_vyres;                   
1478         var->xres_virtual = def_vxres;           
1479         var->yres_virtual = def_vyres;           
1480         var->rotate       = def_rotate;          
1481         var->bits_per_pixel = fbdev->panel->b    
1482                                                  
1483         set_fb_var(info, var);                   
1484         set_fb_fix(info);                        
1485                                                  
1486         r = fb_alloc_cmap(&info->cmap, 16, 0)    
1487         if (r != 0)                              
1488                 dev_err(fbdev->dev, "unable t    
1489                                                  
1490         return r;                                
1491 }                                                
1492                                                  
1493 /* Release the fb_info object */                 
1494 static void fbinfo_cleanup(struct omapfb_devi    
1495 {                                                
1496         fb_dealloc_cmap(&fbi->cmap);             
1497 }                                                
1498                                                  
1499 static void planes_cleanup(struct omapfb_devi    
1500 {                                                
1501         int i;                                   
1502                                                  
1503         for (i = 0; i < fbdev->mem_desc.regio    
1504                 if (fbdev->fb_info[i] == NULL    
1505                         break;                   
1506                 fbinfo_cleanup(fbdev, fbdev->    
1507                 framebuffer_release(fbdev->fb    
1508         }                                        
1509 }                                                
1510                                                  
1511 static int planes_init(struct omapfb_device *    
1512 {                                                
1513         struct fb_info *fbi;                     
1514         int i;                                   
1515         int r;                                   
1516                                                  
1517         for (i = 0; i < fbdev->mem_desc.regio    
1518                 struct omapfb_plane_struct *p    
1519                 fbi = framebuffer_alloc(sizeo    
1520                                         fbdev    
1521                 if (fbi == NULL) {               
1522                         dev_err(fbdev->dev,      
1523                                 "unable to al    
1524                         planes_cleanup(fbdev)    
1525                         return -ENOMEM;          
1526                 }                                
1527                 plane = fbi->par;                
1528                 plane->idx = i;                  
1529                 plane->fbdev = fbdev;            
1530                 plane->info.mirror = def_mirr    
1531                 fbdev->fb_info[i] = fbi;         
1532                                                  
1533                 if ((r = fbinfo_init(fbdev, f    
1534                         framebuffer_release(f    
1535                         planes_cleanup(fbdev)    
1536                         return r;                
1537                 }                                
1538                 plane->info.out_width = fbi->    
1539                 plane->info.out_height = fbi-    
1540         }                                        
1541         return 0;                                
1542 }                                                
1543                                                  
1544 /*                                               
1545  * Free driver resources. Can be called to ro    
1546  * sequence.                                     
1547  */                                              
1548 static void omapfb_free_resources(struct omap    
1549 {                                                
1550         int i;                                   
1551                                                  
1552         switch (state) {                         
1553         case OMAPFB_ACTIVE:                      
1554                 for (i = 0; i < fbdev->mem_de    
1555                         unregister_framebuffe    
1556         case 7:                                  
1557                 omapfb_unregister_sysfs(fbdev    
1558         case 6:                                  
1559                 fbdev->panel->disable(fbdev->    
1560         case 5:                                  
1561                 omapfb_set_update_mode(fbdev,    
1562         case 4:                                  
1563                 planes_cleanup(fbdev);           
1564         case 3:                                  
1565                 ctrl_cleanup(fbdev);             
1566         case 2:                                  
1567                 fbdev->panel->cleanup(fbdev->    
1568         case 1:                                  
1569                 dev_set_drvdata(fbdev->dev, N    
1570                 kfree(fbdev);                    
1571         case 0:                                  
1572                 /* nothing to free */            
1573                 break;                           
1574         default:                                 
1575                 BUG();                           
1576         }                                        
1577 }                                                
1578                                                  
1579 static int omapfb_find_ctrl(struct omapfb_dev    
1580 {                                                
1581         struct omapfb_platform_data *conf;       
1582         char name[17];                           
1583         int i;                                   
1584                                                  
1585         conf = fbdev->dev->platform_data;        
1586                                                  
1587         fbdev->ctrl = NULL;                      
1588                                                  
1589         strncpy(name, conf->lcd.ctrl_name, si    
1590         name[sizeof(name) - 1] = '\0';           
1591                                                  
1592         if (strcmp(name, "internal") == 0) {     
1593                 fbdev->ctrl = fbdev->int_ctrl    
1594                 return 0;                        
1595         }                                        
1596                                                  
1597         for (i = 0; i < ARRAY_SIZE(ctrls); i+    
1598                 dev_dbg(fbdev->dev, "ctrl %s\    
1599                 if (strcmp(ctrls[i]->name, na    
1600                         fbdev->ctrl = ctrls[i    
1601                         break;                   
1602                 }                                
1603         }                                        
1604                                                  
1605         if (fbdev->ctrl == NULL) {               
1606                 dev_dbg(fbdev->dev, "ctrl %s     
1607                 return -1;                       
1608         }                                        
1609                                                  
1610         return 0;                                
1611 }                                                
1612                                                  
1613 static void check_required_callbacks(struct o    
1614 {                                                
1615 #define _C(x) (fbdev->ctrl->x != NULL)           
1616 #define _P(x) (fbdev->panel->x != NULL)          
1617         BUG_ON(fbdev->ctrl == NULL || fbdev->    
1618         BUG_ON(!(_C(init) && _C(cleanup) && _    
1619                  _C(set_update_mode) && _C(se    
1620                  _P(init) && _P(cleanup) && _    
1621                  _P(get_caps)));                 
1622 #undef _P                                        
1623 #undef _C                                        
1624 }                                                
1625                                                  
1626 /*                                               
1627  * Called by LDM binding to probe and attach     
1628  * Initialization sequence:                      
1629  *   1. allocate system omapfb_device structu    
1630  *   2. select controller type according to p    
1631  *      init LCD panel                           
1632  *   3. init LCD controller and LCD DMA          
1633  *   4. init system fb_info structure for all    
1634  *   5. setup video mode for first plane and     
1635  *   6. enable LCD panel                         
1636  *   7. register sysfs attributes                
1637  *   OMAPFB_ACTIVE: register system fb_info s    
1638  */                                              
1639 static int omapfb_do_probe(struct platform_de    
1640                                 struct lcd_pa    
1641 {                                                
1642         struct omapfb_device    *fbdev = NULL    
1643         int                     init_state;      
1644         unsigned long           phz, hhz, vhz    
1645         unsigned long           vram;            
1646         int                     i;               
1647         int                     r = 0;           
1648                                                  
1649         init_state = 0;                          
1650                                                  
1651         if (pdev->num_resources != 0) {          
1652                 dev_err(&pdev->dev, "probed f    
1653                 r = -ENODEV;                     
1654                 goto cleanup;                    
1655         }                                        
1656                                                  
1657         if (pdev->dev.platform_data == NULL)     
1658                 dev_err(&pdev->dev, "missing     
1659                 r = -ENOENT;                     
1660                 goto cleanup;                    
1661         }                                        
1662                                                  
1663         fbdev = kzalloc(sizeof(struct omapfb_    
1664         if (fbdev == NULL) {                     
1665                 dev_err(&pdev->dev,              
1666                         "unable to allocate m    
1667                 r = -ENOMEM;                     
1668                 goto cleanup;                    
1669         }                                        
1670         init_state++;                            
1671                                                  
1672         fbdev->dev = &pdev->dev;                 
1673         fbdev->panel = panel;                    
1674         platform_set_drvdata(pdev, fbdev);       
1675                                                  
1676         mutex_init(&fbdev->rqueue_mutex);        
1677                                                  
1678 #ifdef CONFIG_ARCH_OMAP1                         
1679         fbdev->int_ctrl = &omap1_int_ctrl;       
1680 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL              
1681         fbdev->ext_if = &omap1_ext_if;           
1682 #endif                                           
1683 #else   /* OMAP2 */                              
1684         fbdev->int_ctrl = &omap2_int_ctrl;       
1685 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL              
1686         fbdev->ext_if = &omap2_ext_if;           
1687 #endif                                           
1688 #endif                                           
1689         if (omapfb_find_ctrl(fbdev) < 0) {       
1690                 dev_err(fbdev->dev,              
1691                         "LCD controller not f    
1692                 r = -ENODEV;                     
1693                 goto cleanup;                    
1694         }                                        
1695                                                  
1696         r = fbdev->panel->init(fbdev->panel,     
1697         if (r)                                   
1698                 goto cleanup;                    
1699                                                  
1700         pr_info("omapfb: configured for panel    
1701                                                  
1702         def_vxres = def_vxres ? : fbdev->pane    
1703         def_vyres = def_vyres ? : fbdev->pane    
1704                                                  
1705         init_state++;                            
1706                                                  
1707         r = ctrl_init(fbdev);                    
1708         if (r)                                   
1709                 goto cleanup;                    
1710         if (fbdev->ctrl->mmap != NULL)           
1711                 omapfb_ops.fb_mmap = omapfb_m    
1712         init_state++;                            
1713                                                  
1714         check_required_callbacks(fbdev);         
1715                                                  
1716         r = planes_init(fbdev);                  
1717         if (r)                                   
1718                 goto cleanup;                    
1719         init_state++;                            
1720                                                  
1721 #ifdef CONFIG_FB_OMAP_DMA_TUNE                   
1722         /* Set DMA priority for EMIFF access     
1723         if (cpu_class_is_omap1())                
1724                 omap_set_dma_priority(0, OMAP    
1725 #endif                                           
1726                                                  
1727         r = ctrl_change_mode(fbdev->fb_info[0    
1728         if (r) {                                 
1729                 dev_err(fbdev->dev, "mode set    
1730                 goto cleanup;                    
1731         }                                        
1732                                                  
1733         /* GFX plane is enabled by default */    
1734         r = fbdev->ctrl->enable_plane(OMAPFB_    
1735         if (r)                                   
1736                 goto cleanup;                    
1737                                                  
1738         omapfb_set_update_mode(fbdev, manual_    
1739                                    OMAPFB_MAN    
1740         init_state++;                            
1741                                                  
1742         r = fbdev->panel->enable(fbdev->panel    
1743         if (r)                                   
1744                 goto cleanup;                    
1745         init_state++;                            
1746                                                  
1747         r = omapfb_register_sysfs(fbdev);        
1748         if (r)                                   
1749                 goto cleanup;                    
1750         init_state++;                            
1751                                                  
1752         vram = 0;                                
1753         for (i = 0; i < fbdev->mem_desc.regio    
1754                 r = register_framebuffer(fbde    
1755                 if (r != 0) {                    
1756                         dev_err(fbdev->dev,      
1757                                 "registering     
1758                         goto cleanup;            
1759                 }                                
1760                 vram += fbdev->mem_desc.regio    
1761         }                                        
1762                                                  
1763         fbdev->state = OMAPFB_ACTIVE;            
1764                                                  
1765         panel = fbdev->panel;                    
1766         phz = panel->pixel_clock * 1000;         
1767         hhz = phz * 10 / (panel->hfp + panel-    
1768         vhz = hhz / (panel->vfp + panel->y_re    
1769                                                  
1770         omapfb_dev = fbdev;                      
1771                                                  
1772         pr_info("omapfb: Framebuffer initiali    
1773                         vram, fbdev->mem_desc    
1774         pr_info("omapfb: Pixclock %lu kHz hfr    
1775                         "vfreq %lu.%lu Hz\n",    
1776                         phz / 1000, hhz / 100    
1777                                                  
1778         return 0;                                
1779                                                  
1780 cleanup:                                         
1781         omapfb_free_resources(fbdev, init_sta    
1782                                                  
1783         return r;                                
1784 }                                                
1785                                                  
1786 static int omapfb_probe(struct platform_devic    
1787 {                                                
1788         BUG_ON(fbdev_pdev != NULL);              
1789                                                  
1790         /* Delay actual initialization until     
1791         fbdev_pdev = pdev;                       
1792         if (fbdev_panel != NULL)                 
1793                 omapfb_do_probe(fbdev_pdev, f    
1794         return 0;                                
1795 }                                                
1796                                                  
1797 void omapfb_register_panel(struct lcd_panel *    
1798 {                                                
1799         BUG_ON(fbdev_panel != NULL);             
1800                                                  
1801         fbdev_panel = panel;                     
1802         if (fbdev_pdev != NULL)                  
1803                 omapfb_do_probe(fbdev_pdev, f    
1804 }                                                
1805                                                  
1806 /* Called when the device is being detached f    
1807 static int omapfb_remove(struct platform_devi    
1808 {                                                
1809         struct omapfb_device *fbdev = platfor    
1810         enum omapfb_state saved_state = fbdev    
1811                                                  
1812         /* FIXME: wait till completion of pen    
1813                                                  
1814         fbdev->state = OMAPFB_DISABLED;          
1815         omapfb_free_resources(fbdev, saved_st    
1816                                                  
1817         return 0;                                
1818 }                                                
1819                                                  
1820 /* PM suspend */                                 
1821 static int omapfb_suspend(struct platform_dev    
1822 {                                                
1823         struct omapfb_device *fbdev = platfor    
1824                                                  
1825         omapfb_blank(FB_BLANK_POWERDOWN, fbde    
1826                                                  
1827         return 0;                                
1828 }                                                
1829                                                  
1830 /* PM resume */                                  
1831 static int omapfb_resume(struct platform_devi    
1832 {                                                
1833         struct omapfb_device *fbdev = platfor    
1834                                                  
1835         omapfb_blank(FB_BLANK_UNBLANK, fbdev-    
1836         return 0;                                
1837 }                                                
1838                                                  
1839 static struct platform_driver omapfb_driver =    
1840         .probe          = omapfb_probe,          
1841         .remove         = omapfb_remove,         
1842         .suspend        = omapfb_suspend,        
1843         .resume         = omapfb_resume,         
1844         .driver         = {                      
1845                 .name   = MODULE_NAME,           
1846                 .owner  = THIS_MODULE,           
1847         },                                       
1848 };                                               
1849                                                  
1850 #ifndef MODULE                                   
1851                                                  
1852 /* Process kernel command line parameters */     
1853 static int __init omapfb_setup(char *options)    
1854 {                                                
1855         char *this_opt = NULL;                   
1856         int r = 0;                               
1857                                                  
1858         pr_debug("omapfb: options %s\n", opti    
1859                                                  
1860         if (!options || !*options)               
1861                 return 0;                        
1862                                                  
1863         while (!r && (this_opt = strsep(&opti    
1864                 if (!strncmp(this_opt, "accel    
1865                         def_accel = 1;           
1866                 else if (!strncmp(this_opt, "    
1867                         char *suffix;            
1868                         unsigned long vram;      
1869                         vram = (simple_strtou    
1870                         switch (suffix[0]) {     
1871                         case '\0':               
1872                                 break;           
1873                         case 'm':                
1874                         case 'M':                
1875                                 vram *= 1024;    
1876                                 /* Fall throu    
1877                         case 'k':                
1878                         case 'K':                
1879                                 vram *= 1024;    
1880                                 break;           
1881                         default:                 
1882                                 pr_debug("oma    
1883                                          suff    
1884                                 r = -1;          
1885                         }                        
1886                         def_vram[def_vram_cnt    
1887                 }                                
1888                 else if (!strncmp(this_opt, "    
1889                         def_vxres = simple_st    
1890                 else if (!strncmp(this_opt, "    
1891                         def_vyres = simple_st    
1892                 else if (!strncmp(this_opt, "    
1893                         def_rotate = (simple_    
1894                 else if (!strncmp(this_opt, "    
1895                         def_mirror = (simple_    
1896                 else if (!strncmp(this_opt, "    
1897                         manual_update = 1;       
1898                 else {                           
1899                         pr_debug("omapfb: inv    
1900                         r = -1;                  
1901                 }                                
1902         }                                        
1903                                                  
1904         return r;                                
1905 }                                                
1906                                                  
1907 #endif                                           
1908                                                  
1909 /* Register both the driver and the device */    
1910 static int __init omapfb_init(void)              
1911 {                                                
1912 #ifndef MODULE                                   
1913         char *option;                            
1914                                                  
1915         if (fb_get_options("omapfb", &option)    
1916                 return -ENODEV;                  
1917         omapfb_setup(option);                    
1918 #endif                                           
1919         /* Register the driver with LDM */       
1920         if (platform_driver_register(&omapfb_    
1921                 pr_debug("failed to register     
1922                 return -ENODEV;                  
1923         }                                        
1924                                                  
1925         return 0;                                
1926 }                                                
1927                                                  
1928 static void __exit omapfb_cleanup(void)          
1929 {                                                
1930         platform_driver_unregister(&omapfb_dr    
1931 }                                                
1932                                                  
1933 module_param_named(accel, def_accel, uint, 06    
1934 module_param_array_named(vram, def_vram, ulon    
1935 module_param_named(vxres, def_vxres, long, 06    
1936 module_param_named(vyres, def_vyres, long, 06    
1937 module_param_named(rotate, def_rotate, uint,     
1938 module_param_named(mirror, def_mirror, uint,     
1939 module_param_named(manual_update, manual_upda    
1940                                                  
1941 module_init(omapfb_init);                        
1942 module_exit(omapfb_cleanup);                     
1943                                                  
1944 MODULE_DESCRIPTION("TI OMAP framebuffer drive    
1945 MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com    
1946 MODULE_LICENSE("GPL");                           
1947                                                  
  This page was automatically generated by the LXR engine.