mm: kill vma flag VM_RESERVED and mm->reserved_vm counter
[linux-2.6-block.git] / drivers / video / omap2 / omapfb / omapfb-main.c
1 /*
2  * linux/drivers/video/omap2/omapfb-main.c
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6  *
7  * Some code and ideas taken from drivers/video/omap/ driver
8  * by Imre Deak.
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License version 2 as published by
12  * the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17  * more details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include <linux/module.h>
24 #include <linux/delay.h>
25 #include <linux/slab.h>
26 #include <linux/fb.h>
27 #include <linux/dma-mapping.h>
28 #include <linux/vmalloc.h>
29 #include <linux/device.h>
30 #include <linux/platform_device.h>
31 #include <linux/omapfb.h>
32
33 #include <video/omapdss.h>
34 #include <plat/cpu.h>
35 #include <plat/vram.h>
36 #include <plat/vrfb.h>
37
38 #include "omapfb.h"
39
40 #define MODULE_NAME     "omapfb"
41
42 #define OMAPFB_PLANE_XRES_MIN           8
43 #define OMAPFB_PLANE_YRES_MIN           8
44
45 static char *def_mode;
46 static char *def_vram;
47 static bool def_vrfb;
48 static int def_rotate;
49 static bool def_mirror;
50 static bool auto_update;
51 static unsigned int auto_update_freq;
52 module_param(auto_update, bool, 0);
53 module_param(auto_update_freq, uint, 0644);
54
55 #ifdef DEBUG
56 bool omapfb_debug;
57 module_param_named(debug, omapfb_debug, bool, 0644);
58 static bool omapfb_test_pattern;
59 module_param_named(test, omapfb_test_pattern, bool, 0644);
60 #endif
61
62 static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
63 static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
64                 struct omap_dss_device *dssdev);
65
66 #ifdef DEBUG
67 static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
68 {
69         struct fb_var_screeninfo *var = &fbi->var;
70         struct fb_fix_screeninfo *fix = &fbi->fix;
71         void __iomem *addr = fbi->screen_base;
72         const unsigned bytespp = var->bits_per_pixel >> 3;
73         const unsigned line_len = fix->line_length / bytespp;
74
75         int r = (color >> 16) & 0xff;
76         int g = (color >> 8) & 0xff;
77         int b = (color >> 0) & 0xff;
78
79         if (var->bits_per_pixel == 16) {
80                 u16 __iomem *p = (u16 __iomem *)addr;
81                 p += y * line_len + x;
82
83                 r = r * 32 / 256;
84                 g = g * 64 / 256;
85                 b = b * 32 / 256;
86
87                 __raw_writew((r << 11) | (g << 5) | (b << 0), p);
88         } else if (var->bits_per_pixel == 24) {
89                 u8 __iomem *p = (u8 __iomem *)addr;
90                 p += (y * line_len + x) * 3;
91
92                 __raw_writeb(b, p + 0);
93                 __raw_writeb(g, p + 1);
94                 __raw_writeb(r, p + 2);
95         } else if (var->bits_per_pixel == 32) {
96                 u32 __iomem *p = (u32 __iomem *)addr;
97                 p += y * line_len + x;
98                 __raw_writel(color, p);
99         }
100 }
101
102 static void fill_fb(struct fb_info *fbi)
103 {
104         struct fb_var_screeninfo *var = &fbi->var;
105         const short w = var->xres_virtual;
106         const short h = var->yres_virtual;
107         void __iomem *addr = fbi->screen_base;
108         int y, x;
109
110         if (!addr)
111                 return;
112
113         DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
114
115         for (y = 0; y < h; y++) {
116                 for (x = 0; x < w; x++) {
117                         if (x < 20 && y < 20)
118                                 draw_pixel(fbi, x, y, 0xffffff);
119                         else if (x < 20 && (y > 20 && y < h - 20))
120                                 draw_pixel(fbi, x, y, 0xff);
121                         else if (y < 20 && (x > 20 && x < w - 20))
122                                 draw_pixel(fbi, x, y, 0xff00);
123                         else if (x > w - 20 && (y > 20 && y < h - 20))
124                                 draw_pixel(fbi, x, y, 0xff0000);
125                         else if (y > h - 20 && (x > 20 && x < w - 20))
126                                 draw_pixel(fbi, x, y, 0xffff00);
127                         else if (x == 20 || x == w - 20 ||
128                                         y == 20 || y == h - 20)
129                                 draw_pixel(fbi, x, y, 0xffffff);
130                         else if (x == y || w - x == h - y)
131                                 draw_pixel(fbi, x, y, 0xff00ff);
132                         else if (w - x == y || x == h - y)
133                                 draw_pixel(fbi, x, y, 0x00ffff);
134                         else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
135                                 int t = x * 3 / w;
136                                 unsigned r = 0, g = 0, b = 0;
137                                 unsigned c;
138                                 if (var->bits_per_pixel == 16) {
139                                         if (t == 0)
140                                                 b = (y % 32) * 256 / 32;
141                                         else if (t == 1)
142                                                 g = (y % 64) * 256 / 64;
143                                         else if (t == 2)
144                                                 r = (y % 32) * 256 / 32;
145                                 } else {
146                                         if (t == 0)
147                                                 b = (y % 256);
148                                         else if (t == 1)
149                                                 g = (y % 256);
150                                         else if (t == 2)
151                                                 r = (y % 256);
152                                 }
153                                 c = (r << 16) | (g << 8) | (b << 0);
154                                 draw_pixel(fbi, x, y, c);
155                         } else {
156                                 draw_pixel(fbi, x, y, 0);
157                         }
158                 }
159         }
160 }
161 #endif
162
163 static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
164 {
165         const struct vrfb *vrfb = &ofbi->region->vrfb;
166         unsigned offset;
167
168         switch (rot) {
169         case FB_ROTATE_UR:
170                 offset = 0;
171                 break;
172         case FB_ROTATE_CW:
173                 offset = vrfb->yoffset;
174                 break;
175         case FB_ROTATE_UD:
176                 offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
177                 break;
178         case FB_ROTATE_CCW:
179                 offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
180                 break;
181         default:
182                 BUG();
183                 return 0;
184         }
185
186         offset *= vrfb->bytespp;
187
188         return offset;
189 }
190
191 static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
192 {
193         if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
194                 return ofbi->region->vrfb.paddr[rot]
195                         + omapfb_get_vrfb_offset(ofbi, rot);
196         } else {
197                 return ofbi->region->paddr;
198         }
199 }
200
201 static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
202 {
203         if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
204                 return ofbi->region->vrfb.paddr[0];
205         else
206                 return ofbi->region->paddr;
207 }
208
209 static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
210 {
211         if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
212                 return ofbi->region->vrfb.vaddr[0];
213         else
214                 return ofbi->region->vaddr;
215 }
216
217 static struct omapfb_colormode omapfb_colormodes[] = {
218         {
219                 .dssmode = OMAP_DSS_COLOR_UYVY,
220                 .bits_per_pixel = 16,
221                 .nonstd = OMAPFB_COLOR_YUV422,
222         }, {
223                 .dssmode = OMAP_DSS_COLOR_YUV2,
224                 .bits_per_pixel = 16,
225                 .nonstd = OMAPFB_COLOR_YUY422,
226         }, {
227                 .dssmode = OMAP_DSS_COLOR_ARGB16,
228                 .bits_per_pixel = 16,
229                 .red    = { .length = 4, .offset = 8, .msb_right = 0 },
230                 .green  = { .length = 4, .offset = 4, .msb_right = 0 },
231                 .blue   = { .length = 4, .offset = 0, .msb_right = 0 },
232                 .transp = { .length = 4, .offset = 12, .msb_right = 0 },
233         }, {
234                 .dssmode = OMAP_DSS_COLOR_RGB16,
235                 .bits_per_pixel = 16,
236                 .red    = { .length = 5, .offset = 11, .msb_right = 0 },
237                 .green  = { .length = 6, .offset = 5, .msb_right = 0 },
238                 .blue   = { .length = 5, .offset = 0, .msb_right = 0 },
239                 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
240         }, {
241                 .dssmode = OMAP_DSS_COLOR_RGB24P,
242                 .bits_per_pixel = 24,
243                 .red    = { .length = 8, .offset = 16, .msb_right = 0 },
244                 .green  = { .length = 8, .offset = 8, .msb_right = 0 },
245                 .blue   = { .length = 8, .offset = 0, .msb_right = 0 },
246                 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
247         }, {
248                 .dssmode = OMAP_DSS_COLOR_RGB24U,
249                 .bits_per_pixel = 32,
250                 .red    = { .length = 8, .offset = 16, .msb_right = 0 },
251                 .green  = { .length = 8, .offset = 8, .msb_right = 0 },
252                 .blue   = { .length = 8, .offset = 0, .msb_right = 0 },
253                 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
254         }, {
255                 .dssmode = OMAP_DSS_COLOR_ARGB32,
256                 .bits_per_pixel = 32,
257                 .red    = { .length = 8, .offset = 16, .msb_right = 0 },
258                 .green  = { .length = 8, .offset = 8, .msb_right = 0 },
259                 .blue   = { .length = 8, .offset = 0, .msb_right = 0 },
260                 .transp = { .length = 8, .offset = 24, .msb_right = 0 },
261         }, {
262                 .dssmode = OMAP_DSS_COLOR_RGBA32,
263                 .bits_per_pixel = 32,
264                 .red    = { .length = 8, .offset = 24, .msb_right = 0 },
265                 .green  = { .length = 8, .offset = 16, .msb_right = 0 },
266                 .blue   = { .length = 8, .offset = 8, .msb_right = 0 },
267                 .transp = { .length = 8, .offset = 0, .msb_right = 0 },
268         }, {
269                 .dssmode = OMAP_DSS_COLOR_RGBX32,
270                 .bits_per_pixel = 32,
271                 .red    = { .length = 8, .offset = 24, .msb_right = 0 },
272                 .green  = { .length = 8, .offset = 16, .msb_right = 0 },
273                 .blue   = { .length = 8, .offset = 8, .msb_right = 0 },
274                 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
275         },
276 };
277
278 static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
279                 struct omapfb_colormode *color)
280 {
281         bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
282         {
283                 return f1->length == f2->length &&
284                         f1->offset == f2->offset &&
285                         f1->msb_right == f2->msb_right;
286         }
287
288         if (var->bits_per_pixel == 0 ||
289                         var->red.length == 0 ||
290                         var->blue.length == 0 ||
291                         var->green.length == 0)
292                 return 0;
293
294         return var->bits_per_pixel == color->bits_per_pixel &&
295                 cmp_component(&var->red, &color->red) &&
296                 cmp_component(&var->green, &color->green) &&
297                 cmp_component(&var->blue, &color->blue) &&
298                 cmp_component(&var->transp, &color->transp);
299 }
300
301 static void assign_colormode_to_var(struct fb_var_screeninfo *var,
302                 struct omapfb_colormode *color)
303 {
304         var->bits_per_pixel = color->bits_per_pixel;
305         var->nonstd = color->nonstd;
306         var->red = color->red;
307         var->green = color->green;
308         var->blue = color->blue;
309         var->transp = color->transp;
310 }
311
312 static int fb_mode_to_dss_mode(struct fb_var_screeninfo *var,
313                 enum omap_color_mode *mode)
314 {
315         enum omap_color_mode dssmode;
316         int i;
317
318         /* first match with nonstd field */
319         if (var->nonstd) {
320                 for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
321                         struct omapfb_colormode *m = &omapfb_colormodes[i];
322                         if (var->nonstd == m->nonstd) {
323                                 assign_colormode_to_var(var, m);
324                                 *mode = m->dssmode;
325                                 return 0;
326                         }
327                 }
328
329                 return -EINVAL;
330         }
331
332         /* then try exact match of bpp and colors */
333         for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
334                 struct omapfb_colormode *m = &omapfb_colormodes[i];
335                 if (cmp_var_to_colormode(var, m)) {
336                         assign_colormode_to_var(var, m);
337                         *mode = m->dssmode;
338                         return 0;
339                 }
340         }
341
342         /* match with bpp if user has not filled color fields
343          * properly */
344         switch (var->bits_per_pixel) {
345         case 1:
346                 dssmode = OMAP_DSS_COLOR_CLUT1;
347                 break;
348         case 2:
349                 dssmode = OMAP_DSS_COLOR_CLUT2;
350                 break;
351         case 4:
352                 dssmode = OMAP_DSS_COLOR_CLUT4;
353                 break;
354         case 8:
355                 dssmode = OMAP_DSS_COLOR_CLUT8;
356                 break;
357         case 12:
358                 dssmode = OMAP_DSS_COLOR_RGB12U;
359                 break;
360         case 16:
361                 dssmode = OMAP_DSS_COLOR_RGB16;
362                 break;
363         case 24:
364                 dssmode = OMAP_DSS_COLOR_RGB24P;
365                 break;
366         case 32:
367                 dssmode = OMAP_DSS_COLOR_RGB24U;
368                 break;
369         default:
370                 return -EINVAL;
371         }
372
373         for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
374                 struct omapfb_colormode *m = &omapfb_colormodes[i];
375                 if (dssmode == m->dssmode) {
376                         assign_colormode_to_var(var, m);
377                         *mode = m->dssmode;
378                         return 0;
379                 }
380         }
381
382         return -EINVAL;
383 }
384
385 static int check_fb_res_bounds(struct fb_var_screeninfo *var)
386 {
387         int xres_min = OMAPFB_PLANE_XRES_MIN;
388         int xres_max = 2048;
389         int yres_min = OMAPFB_PLANE_YRES_MIN;
390         int yres_max = 2048;
391
392         /* XXX: some applications seem to set virtual res to 0. */
393         if (var->xres_virtual == 0)
394                 var->xres_virtual = var->xres;
395
396         if (var->yres_virtual == 0)
397                 var->yres_virtual = var->yres;
398
399         if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
400                 return -EINVAL;
401
402         if (var->xres < xres_min)
403                 var->xres = xres_min;
404         if (var->yres < yres_min)
405                 var->yres = yres_min;
406         if (var->xres > xres_max)
407                 var->xres = xres_max;
408         if (var->yres > yres_max)
409                 var->yres = yres_max;
410
411         if (var->xres > var->xres_virtual)
412                 var->xres = var->xres_virtual;
413         if (var->yres > var->yres_virtual)
414                 var->yres = var->yres_virtual;
415
416         return 0;
417 }
418
419 static void shrink_height(unsigned long max_frame_size,
420                 struct fb_var_screeninfo *var)
421 {
422         DBG("can't fit FB into memory, reducing y\n");
423         var->yres_virtual = max_frame_size /
424                 (var->xres_virtual * var->bits_per_pixel >> 3);
425
426         if (var->yres_virtual < OMAPFB_PLANE_YRES_MIN)
427                 var->yres_virtual = OMAPFB_PLANE_YRES_MIN;
428
429         if (var->yres > var->yres_virtual)
430                 var->yres = var->yres_virtual;
431 }
432
433 static void shrink_width(unsigned long max_frame_size,
434                 struct fb_var_screeninfo *var)
435 {
436         DBG("can't fit FB into memory, reducing x\n");
437         var->xres_virtual = max_frame_size / var->yres_virtual /
438                 (var->bits_per_pixel >> 3);
439
440         if (var->xres_virtual < OMAPFB_PLANE_XRES_MIN)
441                 var->xres_virtual = OMAPFB_PLANE_XRES_MIN;
442
443         if (var->xres > var->xres_virtual)
444                 var->xres = var->xres_virtual;
445 }
446
447 static int check_vrfb_fb_size(unsigned long region_size,
448                 const struct fb_var_screeninfo *var)
449 {
450         unsigned long min_phys_size = omap_vrfb_min_phys_size(var->xres_virtual,
451                 var->yres_virtual, var->bits_per_pixel >> 3);
452
453         return min_phys_size > region_size ? -EINVAL : 0;
454 }
455
456 static int check_fb_size(const struct omapfb_info *ofbi,
457                 struct fb_var_screeninfo *var)
458 {
459         unsigned long max_frame_size = ofbi->region->size;
460         int bytespp = var->bits_per_pixel >> 3;
461         unsigned long line_size = var->xres_virtual * bytespp;
462
463         if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
464                 /* One needs to check for both VRFB and OMAPFB limitations. */
465                 if (check_vrfb_fb_size(max_frame_size, var))
466                         shrink_height(omap_vrfb_max_height(
467                                 max_frame_size, var->xres_virtual, bytespp) *
468                                 line_size, var);
469
470                 if (check_vrfb_fb_size(max_frame_size, var)) {
471                         DBG("cannot fit FB to memory\n");
472                         return -EINVAL;
473                 }
474
475                 return 0;
476         }
477
478         DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
479
480         if (line_size * var->yres_virtual > max_frame_size)
481                 shrink_height(max_frame_size, var);
482
483         if (line_size * var->yres_virtual > max_frame_size) {
484                 shrink_width(max_frame_size, var);
485                 line_size = var->xres_virtual * bytespp;
486         }
487
488         if (line_size * var->yres_virtual > max_frame_size) {
489                 DBG("cannot fit FB to memory\n");
490                 return -EINVAL;
491         }
492
493         return 0;
494 }
495
496 /*
497  * Consider if VRFB assisted rotation is in use and if the virtual space for
498  * the zero degree view needs to be mapped. The need for mapping also acts as
499  * the trigger for setting up the hardware on the context in question. This
500  * ensures that one does not attempt to access the virtual view before the
501  * hardware is serving the address translations.
502  */
503 static int setup_vrfb_rotation(struct fb_info *fbi)
504 {
505         struct omapfb_info *ofbi = FB2OFB(fbi);
506         struct omapfb2_mem_region *rg = ofbi->region;
507         struct vrfb *vrfb = &rg->vrfb;
508         struct fb_var_screeninfo *var = &fbi->var;
509         struct fb_fix_screeninfo *fix = &fbi->fix;
510         unsigned bytespp;
511         bool yuv_mode;
512         enum omap_color_mode mode;
513         int r;
514         bool reconf;
515
516         if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB)
517                 return 0;
518
519         DBG("setup_vrfb_rotation\n");
520
521         r = fb_mode_to_dss_mode(var, &mode);
522         if (r)
523                 return r;
524
525         bytespp = var->bits_per_pixel >> 3;
526
527         yuv_mode = mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY;
528
529         /* We need to reconfigure VRFB if the resolution changes, if yuv mode
530          * is enabled/disabled, or if bytes per pixel changes */
531
532         /* XXX we shouldn't allow this when framebuffer is mmapped */
533
534         reconf = false;
535
536         if (yuv_mode != vrfb->yuv_mode)
537                 reconf = true;
538         else if (bytespp != vrfb->bytespp)
539                 reconf = true;
540         else if (vrfb->xres != var->xres_virtual ||
541                         vrfb->yres != var->yres_virtual)
542                 reconf = true;
543
544         if (vrfb->vaddr[0] && reconf) {
545                 fbi->screen_base = NULL;
546                 fix->smem_start = 0;
547                 fix->smem_len = 0;
548                 iounmap(vrfb->vaddr[0]);
549                 vrfb->vaddr[0] = NULL;
550                 DBG("setup_vrfb_rotation: reset fb\n");
551         }
552
553         if (vrfb->vaddr[0])
554                 return 0;
555
556         omap_vrfb_setup(&rg->vrfb, rg->paddr,
557                         var->xres_virtual,
558                         var->yres_virtual,
559                         bytespp, yuv_mode);
560
561         /* Now one can ioremap the 0 angle view */
562         r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0);
563         if (r)
564                 return r;
565
566         /* used by open/write in fbmem.c */
567         fbi->screen_base = ofbi->region->vrfb.vaddr[0];
568
569         fix->smem_start = ofbi->region->vrfb.paddr[0];
570
571         switch (var->nonstd) {
572         case OMAPFB_COLOR_YUV422:
573         case OMAPFB_COLOR_YUY422:
574                 fix->line_length =
575                         (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
576                 break;
577         default:
578                 fix->line_length =
579                         (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
580                 break;
581         }
582
583         fix->smem_len = var->yres_virtual * fix->line_length;
584
585         return 0;
586 }
587
588 int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
589                         struct fb_var_screeninfo *var)
590 {
591         int i;
592
593         for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
594                 struct omapfb_colormode *mode = &omapfb_colormodes[i];
595                 if (dssmode == mode->dssmode) {
596                         assign_colormode_to_var(var, mode);
597                         return 0;
598                 }
599         }
600         return -ENOENT;
601 }
602
603 void set_fb_fix(struct fb_info *fbi)
604 {
605         struct fb_fix_screeninfo *fix = &fbi->fix;
606         struct fb_var_screeninfo *var = &fbi->var;
607         struct omapfb_info *ofbi = FB2OFB(fbi);
608         struct omapfb2_mem_region *rg = ofbi->region;
609
610         DBG("set_fb_fix\n");
611
612         /* used by open/write in fbmem.c */
613         fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
614
615         /* used by mmap in fbmem.c */
616         if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
617                 switch (var->nonstd) {
618                 case OMAPFB_COLOR_YUV422:
619                 case OMAPFB_COLOR_YUY422:
620                         fix->line_length =
621                                 (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
622                         break;
623                 default:
624                         fix->line_length =
625                                 (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
626                         break;
627                 }
628
629                 fix->smem_len = var->yres_virtual * fix->line_length;
630         } else {
631                 fix->line_length =
632                         (var->xres_virtual * var->bits_per_pixel) >> 3;
633                 fix->smem_len = rg->size;
634         }
635
636         fix->smem_start = omapfb_get_region_paddr(ofbi);
637
638         fix->type = FB_TYPE_PACKED_PIXELS;
639
640         if (var->nonstd)
641                 fix->visual = FB_VISUAL_PSEUDOCOLOR;
642         else {
643                 switch (var->bits_per_pixel) {
644                 case 32:
645                 case 24:
646                 case 16:
647                 case 12:
648                         fix->visual = FB_VISUAL_TRUECOLOR;
649                         /* 12bpp is stored in 16 bits */
650                         break;
651                 case 1:
652                 case 2:
653                 case 4:
654                 case 8:
655                         fix->visual = FB_VISUAL_PSEUDOCOLOR;
656                         break;
657                 }
658         }
659
660         fix->accel = FB_ACCEL_NONE;
661
662         fix->xpanstep = 1;
663         fix->ypanstep = 1;
664 }
665
666 /* check new var and possibly modify it to be ok */
667 int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
668 {
669         struct omapfb_info *ofbi = FB2OFB(fbi);
670         struct omap_dss_device *display = fb2display(fbi);
671         enum omap_color_mode mode = 0;
672         int i;
673         int r;
674
675         DBG("check_fb_var %d\n", ofbi->id);
676
677         WARN_ON(!atomic_read(&ofbi->region->lock_count));
678
679         r = fb_mode_to_dss_mode(var, &mode);
680         if (r) {
681                 DBG("cannot convert var to omap dss mode\n");
682                 return r;
683         }
684
685         for (i = 0; i < ofbi->num_overlays; ++i) {
686                 if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
687                         DBG("invalid mode\n");
688                         return -EINVAL;
689                 }
690         }
691
692         if (var->rotate > 3)
693                 return -EINVAL;
694
695         if (check_fb_res_bounds(var))
696                 return -EINVAL;
697
698         /* When no memory is allocated ignore the size check */
699         if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
700                 return -EINVAL;
701
702         if (var->xres + var->xoffset > var->xres_virtual)
703                 var->xoffset = var->xres_virtual - var->xres;
704         if (var->yres + var->yoffset > var->yres_virtual)
705                 var->yoffset = var->yres_virtual - var->yres;
706
707         DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
708                         var->xres, var->yres,
709                         var->xres_virtual, var->yres_virtual);
710
711         if (display && display->driver->get_dimensions) {
712                 u32 w, h;
713                 display->driver->get_dimensions(display, &w, &h);
714                 var->width = DIV_ROUND_CLOSEST(w, 1000);
715                 var->height = DIV_ROUND_CLOSEST(h, 1000);
716         } else {
717                 var->height = -1;
718                 var->width = -1;
719         }
720
721         var->grayscale          = 0;
722
723         if (display && display->driver->get_timings) {
724                 struct omap_video_timings timings;
725                 display->driver->get_timings(display, &timings);
726
727                 /* pixclock in ps, the rest in pixclock */
728                 var->pixclock = timings.pixel_clock != 0 ?
729                         KHZ2PICOS(timings.pixel_clock) :
730                         0;
731                 var->left_margin = timings.hbp;
732                 var->right_margin = timings.hfp;
733                 var->upper_margin = timings.vbp;
734                 var->lower_margin = timings.vfp;
735                 var->hsync_len = timings.hsw;
736                 var->vsync_len = timings.vsw;
737                 var->sync |= timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
738                                 FB_SYNC_HOR_HIGH_ACT : 0;
739                 var->sync |= timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
740                                 FB_SYNC_VERT_HIGH_ACT : 0;
741                 var->vmode = timings.interlace ?
742                                 FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
743         } else {
744                 var->pixclock = 0;
745                 var->left_margin = 0;
746                 var->right_margin = 0;
747                 var->upper_margin = 0;
748                 var->lower_margin = 0;
749                 var->hsync_len = 0;
750                 var->vsync_len = 0;
751                 var->sync = 0;
752                 var->vmode = FB_VMODE_NONINTERLACED;
753         }
754
755         return 0;
756 }
757
758 /*
759  * ---------------------------------------------------------------------------
760  * fbdev framework callbacks
761  * ---------------------------------------------------------------------------
762  */
763 static int omapfb_open(struct fb_info *fbi, int user)
764 {
765         return 0;
766 }
767
768 static int omapfb_release(struct fb_info *fbi, int user)
769 {
770         return 0;
771 }
772
773 static unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var,
774                 const struct fb_fix_screeninfo *fix, int rotation)
775 {
776         unsigned offset;
777
778         offset = var->yoffset * fix->line_length +
779                 var->xoffset * (var->bits_per_pixel >> 3);
780
781         return offset;
782 }
783
784 static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
785                 const struct fb_fix_screeninfo *fix, int rotation)
786 {
787         unsigned offset;
788
789         if (rotation == FB_ROTATE_UD)
790                 offset = (var->yres_virtual - var->yres) *
791                         fix->line_length;
792         else if (rotation == FB_ROTATE_CW)
793                 offset = (var->yres_virtual - var->yres) *
794                         (var->bits_per_pixel >> 3);
795         else
796                 offset = 0;
797
798         if (rotation == FB_ROTATE_UR)
799                 offset += var->yoffset * fix->line_length +
800                         var->xoffset * (var->bits_per_pixel >> 3);
801         else if (rotation == FB_ROTATE_UD)
802                 offset -= var->yoffset * fix->line_length +
803                         var->xoffset * (var->bits_per_pixel >> 3);
804         else if (rotation == FB_ROTATE_CW)
805                 offset -= var->xoffset * fix->line_length +
806                         var->yoffset * (var->bits_per_pixel >> 3);
807         else if (rotation == FB_ROTATE_CCW)
808                 offset += var->xoffset * fix->line_length +
809                         var->yoffset * (var->bits_per_pixel >> 3);
810
811         return offset;
812 }
813
814 static void omapfb_calc_addr(const struct omapfb_info *ofbi,
815                              const struct fb_var_screeninfo *var,
816                              const struct fb_fix_screeninfo *fix,
817                              int rotation, u32 *paddr)
818 {
819         u32 data_start_p;
820         int offset;
821
822         if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
823                 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
824         else
825                 data_start_p = omapfb_get_region_paddr(ofbi);
826
827         if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
828                 offset = calc_rotation_offset_vrfb(var, fix, rotation);
829         else
830                 offset = calc_rotation_offset_dma(var, fix, rotation);
831
832         data_start_p += offset;
833
834         if (offset)
835                 DBG("offset %d, %d = %d\n",
836                     var->xoffset, var->yoffset, offset);
837
838         DBG("paddr %x\n", data_start_p);
839
840         *paddr = data_start_p;
841 }
842
843 /* setup overlay according to the fb */
844 int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
845                 u16 posx, u16 posy, u16 outw, u16 outh)
846 {
847         int r = 0;
848         struct omapfb_info *ofbi = FB2OFB(fbi);
849         struct fb_var_screeninfo *var = &fbi->var;
850         struct fb_fix_screeninfo *fix = &fbi->fix;
851         enum omap_color_mode mode = 0;
852         u32 data_start_p = 0;
853         struct omap_overlay_info info;
854         int xres, yres;
855         int screen_width;
856         int mirror;
857         int rotation = var->rotate;
858         int i;
859
860         WARN_ON(!atomic_read(&ofbi->region->lock_count));
861
862         for (i = 0; i < ofbi->num_overlays; i++) {
863                 if (ovl != ofbi->overlays[i])
864                         continue;
865
866                 rotation = (rotation + ofbi->rotation[i]) % 4;
867                 break;
868         }
869
870         DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
871                         posx, posy, outw, outh);
872
873         if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
874                 xres = var->yres;
875                 yres = var->xres;
876         } else {
877                 xres = var->xres;
878                 yres = var->yres;
879         }
880
881         if (ofbi->region->size)
882                 omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
883
884         r = fb_mode_to_dss_mode(var, &mode);
885         if (r) {
886                 DBG("fb_mode_to_dss_mode failed");
887                 goto err;
888         }
889
890         switch (var->nonstd) {
891         case OMAPFB_COLOR_YUV422:
892         case OMAPFB_COLOR_YUY422:
893                 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
894                         screen_width = fix->line_length
895                                 / (var->bits_per_pixel >> 2);
896                         break;
897                 }
898         default:
899                 screen_width = fix->line_length / (var->bits_per_pixel >> 3);
900                 break;
901         }
902
903         ovl->get_overlay_info(ovl, &info);
904
905         if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
906                 mirror = 0;
907         else
908                 mirror = ofbi->mirror;
909
910         info.paddr = data_start_p;
911         info.screen_width = screen_width;
912         info.width = xres;
913         info.height = yres;
914         info.color_mode = mode;
915         info.rotation_type = ofbi->rotation_type;
916         info.rotation = rotation;
917         info.mirror = mirror;
918
919         info.pos_x = posx;
920         info.pos_y = posy;
921         info.out_width = outw;
922         info.out_height = outh;
923
924         r = ovl->set_overlay_info(ovl, &info);
925         if (r) {
926                 DBG("ovl->setup_overlay_info failed\n");
927                 goto err;
928         }
929
930         return 0;
931
932 err:
933         DBG("setup_overlay failed\n");
934         return r;
935 }
936
937 /* apply var to the overlay */
938 int omapfb_apply_changes(struct fb_info *fbi, int init)
939 {
940         int r = 0;
941         struct omapfb_info *ofbi = FB2OFB(fbi);
942         struct fb_var_screeninfo *var = &fbi->var;
943         struct omap_overlay *ovl;
944         u16 posx, posy;
945         u16 outw, outh;
946         int i;
947
948 #ifdef DEBUG
949         if (omapfb_test_pattern)
950                 fill_fb(fbi);
951 #endif
952
953         WARN_ON(!atomic_read(&ofbi->region->lock_count));
954
955         for (i = 0; i < ofbi->num_overlays; i++) {
956                 ovl = ofbi->overlays[i];
957
958                 DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
959
960                 if (ofbi->region->size == 0) {
961                         /* the fb is not available. disable the overlay */
962                         omapfb_overlay_enable(ovl, 0);
963                         if (!init && ovl->manager)
964                                 ovl->manager->apply(ovl->manager);
965                         continue;
966                 }
967
968                 if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
969                         int rotation = (var->rotate + ofbi->rotation[i]) % 4;
970                         if (rotation == FB_ROTATE_CW ||
971                                         rotation == FB_ROTATE_CCW) {
972                                 outw = var->yres;
973                                 outh = var->xres;
974                         } else {
975                                 outw = var->xres;
976                                 outh = var->yres;
977                         }
978                 } else {
979                         struct omap_overlay_info info;
980                         ovl->get_overlay_info(ovl, &info);
981                         outw = info.out_width;
982                         outh = info.out_height;
983                 }
984
985                 if (init) {
986                         posx = 0;
987                         posy = 0;
988                 } else {
989                         struct omap_overlay_info info;
990                         ovl->get_overlay_info(ovl, &info);
991                         posx = info.pos_x;
992                         posy = info.pos_y;
993                 }
994
995                 r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
996                 if (r)
997                         goto err;
998
999                 if (!init && ovl->manager)
1000                         ovl->manager->apply(ovl->manager);
1001         }
1002         return 0;
1003 err:
1004         DBG("apply_changes failed\n");
1005         return r;
1006 }
1007
1008 /* checks var and eventually tweaks it to something supported,
1009  * DO NOT MODIFY PAR */
1010 static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
1011 {
1012         struct omapfb_info *ofbi = FB2OFB(fbi);
1013         int r;
1014
1015         DBG("check_var(%d)\n", FB2OFB(fbi)->id);
1016
1017         omapfb_get_mem_region(ofbi->region);
1018
1019         r = check_fb_var(fbi, var);
1020
1021         omapfb_put_mem_region(ofbi->region);
1022
1023         return r;
1024 }
1025
1026 /* set the video mode according to info->var */
1027 static int omapfb_set_par(struct fb_info *fbi)
1028 {
1029         struct omapfb_info *ofbi = FB2OFB(fbi);
1030         int r;
1031
1032         DBG("set_par(%d)\n", FB2OFB(fbi)->id);
1033
1034         omapfb_get_mem_region(ofbi->region);
1035
1036         set_fb_fix(fbi);
1037
1038         r = setup_vrfb_rotation(fbi);
1039         if (r)
1040                 goto out;
1041
1042         r = omapfb_apply_changes(fbi, 0);
1043
1044  out:
1045         omapfb_put_mem_region(ofbi->region);
1046
1047         return r;
1048 }
1049
1050 static int omapfb_pan_display(struct fb_var_screeninfo *var,
1051                 struct fb_info *fbi)
1052 {
1053         struct omapfb_info *ofbi = FB2OFB(fbi);
1054         struct fb_var_screeninfo new_var;
1055         int r;
1056
1057         DBG("pan_display(%d)\n", FB2OFB(fbi)->id);
1058
1059         if (var->xoffset == fbi->var.xoffset &&
1060             var->yoffset == fbi->var.yoffset)
1061                 return 0;
1062
1063         new_var = fbi->var;
1064         new_var.xoffset = var->xoffset;
1065         new_var.yoffset = var->yoffset;
1066
1067         fbi->var = new_var;
1068
1069         omapfb_get_mem_region(ofbi->region);
1070
1071         r = omapfb_apply_changes(fbi, 0);
1072
1073         omapfb_put_mem_region(ofbi->region);
1074
1075         return r;
1076 }
1077
1078 static void mmap_user_open(struct vm_area_struct *vma)
1079 {
1080         struct omapfb2_mem_region *rg = vma->vm_private_data;
1081
1082         omapfb_get_mem_region(rg);
1083         atomic_inc(&rg->map_count);
1084         omapfb_put_mem_region(rg);
1085 }
1086
1087 static void mmap_user_close(struct vm_area_struct *vma)
1088 {
1089         struct omapfb2_mem_region *rg = vma->vm_private_data;
1090
1091         omapfb_get_mem_region(rg);
1092         atomic_dec(&rg->map_count);
1093         omapfb_put_mem_region(rg);
1094 }
1095
1096 static struct vm_operations_struct mmap_user_ops = {
1097         .open = mmap_user_open,
1098         .close = mmap_user_close,
1099 };
1100
1101 static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1102 {
1103         struct omapfb_info *ofbi = FB2OFB(fbi);
1104         struct fb_fix_screeninfo *fix = &fbi->fix;
1105         struct omapfb2_mem_region *rg;
1106         unsigned long off;
1107         unsigned long start;
1108         u32 len;
1109         int r = -EINVAL;
1110
1111         if (vma->vm_end - vma->vm_start == 0)
1112                 return 0;
1113         if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1114                 return -EINVAL;
1115         off = vma->vm_pgoff << PAGE_SHIFT;
1116
1117         rg = omapfb_get_mem_region(ofbi->region);
1118
1119         start = omapfb_get_region_paddr(ofbi);
1120         len = fix->smem_len;
1121         if (off >= len)
1122                 goto error;
1123         if ((vma->vm_end - vma->vm_start + off) > len)
1124                 goto error;
1125
1126         off += start;
1127
1128         DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
1129
1130         vma->vm_pgoff = off >> PAGE_SHIFT;
1131         /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
1132         vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1133         vma->vm_ops = &mmap_user_ops;
1134         vma->vm_private_data = rg;
1135         if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1136                                vma->vm_end - vma->vm_start,
1137                                vma->vm_page_prot)) {
1138                 r = -EAGAIN;
1139                 goto error;
1140         }
1141
1142         /* vm_ops.open won't be called for mmap itself. */
1143         atomic_inc(&rg->map_count);
1144
1145         omapfb_put_mem_region(rg);
1146
1147         return 0;
1148
1149  error:
1150         omapfb_put_mem_region(ofbi->region);
1151
1152         return r;
1153 }
1154
1155 /* Store a single color palette entry into a pseudo palette or the hardware
1156  * palette if one is available. For now we support only 16bpp and thus store
1157  * the entry only to the pseudo palette.
1158  */
1159 static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
1160                 u_int blue, u_int transp, int update_hw_pal)
1161 {
1162         /*struct omapfb_info *ofbi = FB2OFB(fbi);*/
1163         /*struct omapfb2_device *fbdev = ofbi->fbdev;*/
1164         struct fb_var_screeninfo *var = &fbi->var;
1165         int r = 0;
1166
1167         enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
1168
1169         /*switch (plane->color_mode) {*/
1170         switch (mode) {
1171         case OMAPFB_COLOR_YUV422:
1172         case OMAPFB_COLOR_YUV420:
1173         case OMAPFB_COLOR_YUY422:
1174                 r = -EINVAL;
1175                 break;
1176         case OMAPFB_COLOR_CLUT_8BPP:
1177         case OMAPFB_COLOR_CLUT_4BPP:
1178         case OMAPFB_COLOR_CLUT_2BPP:
1179         case OMAPFB_COLOR_CLUT_1BPP:
1180                 /*
1181                    if (fbdev->ctrl->setcolreg)
1182                    r = fbdev->ctrl->setcolreg(regno, red, green, blue,
1183                    transp, update_hw_pal);
1184                    */
1185                 /* Fallthrough */
1186                 r = -EINVAL;
1187                 break;
1188         case OMAPFB_COLOR_RGB565:
1189         case OMAPFB_COLOR_RGB444:
1190         case OMAPFB_COLOR_RGB24P:
1191         case OMAPFB_COLOR_RGB24U:
1192                 if (r != 0)
1193                         break;
1194
1195                 if (regno < 16) {
1196                         u32 pal;
1197                         pal = ((red >> (16 - var->red.length)) <<
1198                                         var->red.offset) |
1199                                 ((green >> (16 - var->green.length)) <<
1200                                  var->green.offset) |
1201                                 (blue >> (16 - var->blue.length));
1202                         ((u32 *)(fbi->pseudo_palette))[regno] = pal;
1203                 }
1204                 break;
1205         default:
1206                 BUG();
1207         }
1208         return r;
1209 }
1210
1211 static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1212                 u_int transp, struct fb_info *info)
1213 {
1214         DBG("setcolreg\n");
1215
1216         return _setcolreg(info, regno, red, green, blue, transp, 1);
1217 }
1218
1219 static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1220 {
1221         int count, index, r;
1222         u16 *red, *green, *blue, *transp;
1223         u16 trans = 0xffff;
1224
1225         DBG("setcmap\n");
1226
1227         red     = cmap->red;
1228         green   = cmap->green;
1229         blue    = cmap->blue;
1230         transp  = cmap->transp;
1231         index   = cmap->start;
1232
1233         for (count = 0; count < cmap->len; count++) {
1234                 if (transp)
1235                         trans = *transp++;
1236                 r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
1237                                 count == cmap->len - 1);
1238                 if (r != 0)
1239                         return r;
1240         }
1241
1242         return 0;
1243 }
1244
1245 static int omapfb_blank(int blank, struct fb_info *fbi)
1246 {
1247         struct omapfb_info *ofbi = FB2OFB(fbi);
1248         struct omapfb2_device *fbdev = ofbi->fbdev;
1249         struct omap_dss_device *display = fb2display(fbi);
1250         struct omapfb_display_data *d;
1251         int r = 0;
1252
1253         if (!display)
1254                 return -EINVAL;
1255
1256         omapfb_lock(fbdev);
1257
1258         d = get_display_data(fbdev, display);
1259
1260         switch (blank) {
1261         case FB_BLANK_UNBLANK:
1262                 if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
1263                         goto exit;
1264
1265                 if (display->driver->resume)
1266                         r = display->driver->resume(display);
1267
1268                 if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
1269                                 d->update_mode == OMAPFB_AUTO_UPDATE &&
1270                                 !d->auto_update_work_enabled)
1271                         omapfb_start_auto_update(fbdev, display);
1272
1273                 break;
1274
1275         case FB_BLANK_NORMAL:
1276                 /* FB_BLANK_NORMAL could be implemented.
1277                  * Needs DSS additions. */
1278         case FB_BLANK_VSYNC_SUSPEND:
1279         case FB_BLANK_HSYNC_SUSPEND:
1280         case FB_BLANK_POWERDOWN:
1281                 if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
1282                         goto exit;
1283
1284                 if (d->auto_update_work_enabled)
1285                         omapfb_stop_auto_update(fbdev, display);
1286
1287                 if (display->driver->suspend)
1288                         r = display->driver->suspend(display);
1289
1290                 break;
1291
1292         default:
1293                 r = -EINVAL;
1294         }
1295
1296 exit:
1297         omapfb_unlock(fbdev);
1298
1299         return r;
1300 }
1301
1302 #if 0
1303 /* XXX fb_read and fb_write are needed for VRFB */
1304 ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
1305                 size_t count, loff_t *ppos)
1306 {
1307         DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
1308         /* XXX needed for VRFB */
1309         return count;
1310 }
1311 #endif
1312
1313 static struct fb_ops omapfb_ops = {
1314         .owner          = THIS_MODULE,
1315         .fb_open        = omapfb_open,
1316         .fb_release     = omapfb_release,
1317         .fb_fillrect    = cfb_fillrect,
1318         .fb_copyarea    = cfb_copyarea,
1319         .fb_imageblit   = cfb_imageblit,
1320         .fb_blank       = omapfb_blank,
1321         .fb_ioctl       = omapfb_ioctl,
1322         .fb_check_var   = omapfb_check_var,
1323         .fb_set_par     = omapfb_set_par,
1324         .fb_pan_display = omapfb_pan_display,
1325         .fb_mmap        = omapfb_mmap,
1326         .fb_setcolreg   = omapfb_setcolreg,
1327         .fb_setcmap     = omapfb_setcmap,
1328         /*.fb_write     = omapfb_write,*/
1329 };
1330
1331 static void omapfb_free_fbmem(struct fb_info *fbi)
1332 {
1333         struct omapfb_info *ofbi = FB2OFB(fbi);
1334         struct omapfb2_device *fbdev = ofbi->fbdev;
1335         struct omapfb2_mem_region *rg;
1336
1337         rg = ofbi->region;
1338
1339         WARN_ON(atomic_read(&rg->map_count));
1340
1341         if (rg->paddr)
1342                 if (omap_vram_free(rg->paddr, rg->size))
1343                         dev_err(fbdev->dev, "VRAM FREE failed\n");
1344
1345         if (rg->vaddr)
1346                 iounmap(rg->vaddr);
1347
1348         if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1349                 /* unmap the 0 angle rotation */
1350                 if (rg->vrfb.vaddr[0]) {
1351                         iounmap(rg->vrfb.vaddr[0]);
1352                         omap_vrfb_release_ctx(&rg->vrfb);
1353                         rg->vrfb.vaddr[0] = NULL;
1354                 }
1355         }
1356
1357         rg->vaddr = NULL;
1358         rg->paddr = 0;
1359         rg->alloc = 0;
1360         rg->size = 0;
1361 }
1362
1363 static void clear_fb_info(struct fb_info *fbi)
1364 {
1365         memset(&fbi->var, 0, sizeof(fbi->var));
1366         memset(&fbi->fix, 0, sizeof(fbi->fix));
1367         strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
1368 }
1369
1370 static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
1371 {
1372         int i;
1373
1374         DBG("free all fbmem\n");
1375
1376         for (i = 0; i < fbdev->num_fbs; i++) {
1377                 struct fb_info *fbi = fbdev->fbs[i];
1378                 omapfb_free_fbmem(fbi);
1379                 clear_fb_info(fbi);
1380         }
1381
1382         return 0;
1383 }
1384
1385 static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1386                 unsigned long paddr)
1387 {
1388         struct omapfb_info *ofbi = FB2OFB(fbi);
1389         struct omapfb2_device *fbdev = ofbi->fbdev;
1390         struct omapfb2_mem_region *rg;
1391         void __iomem *vaddr;
1392         int r;
1393
1394         rg = ofbi->region;
1395
1396         rg->paddr = 0;
1397         rg->vaddr = NULL;
1398         memset(&rg->vrfb, 0, sizeof rg->vrfb);
1399         rg->size = 0;
1400         rg->type = 0;
1401         rg->alloc = false;
1402         rg->map = false;
1403
1404         size = PAGE_ALIGN(size);
1405
1406         if (!paddr) {
1407                 DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
1408                 r = omap_vram_alloc(size, &paddr);
1409         } else {
1410                 DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
1411                                 ofbi->id);
1412                 r = omap_vram_reserve(paddr, size);
1413         }
1414
1415         if (r) {
1416                 dev_err(fbdev->dev, "failed to allocate framebuffer\n");
1417                 return -ENOMEM;
1418         }
1419
1420         if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
1421                 vaddr = ioremap_wc(paddr, size);
1422
1423                 if (!vaddr) {
1424                         dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
1425                         omap_vram_free(paddr, size);
1426                         return -ENOMEM;
1427                 }
1428
1429                 DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
1430         } else {
1431                 r = omap_vrfb_request_ctx(&rg->vrfb);
1432                 if (r) {
1433                         dev_err(fbdev->dev, "vrfb create ctx failed\n");
1434                         return r;
1435                 }
1436
1437                 vaddr = NULL;
1438         }
1439
1440         rg->paddr = paddr;
1441         rg->vaddr = vaddr;
1442         rg->size = size;
1443         rg->alloc = 1;
1444
1445         return 0;
1446 }
1447
1448 /* allocate fbmem using display resolution as reference */
1449 static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
1450                 unsigned long paddr)
1451 {
1452         struct omapfb_info *ofbi = FB2OFB(fbi);
1453         struct omapfb2_device *fbdev = ofbi->fbdev;
1454         struct omap_dss_device *display;
1455         int bytespp;
1456
1457         display =  fb2display(fbi);
1458
1459         if (!display)
1460                 return 0;
1461
1462         switch (omapfb_get_recommended_bpp(fbdev, display)) {
1463         case 16:
1464                 bytespp = 2;
1465                 break;
1466         case 24:
1467                 bytespp = 4;
1468                 break;
1469         default:
1470                 bytespp = 4;
1471                 break;
1472         }
1473
1474         if (!size) {
1475                 u16 w, h;
1476
1477                 display->driver->get_resolution(display, &w, &h);
1478
1479                 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1480                         size = max(omap_vrfb_min_phys_size(w, h, bytespp),
1481                                         omap_vrfb_min_phys_size(h, w, bytespp));
1482
1483                         DBG("adjusting fb mem size for VRFB, %u -> %lu\n",
1484                                         w * h * bytespp, size);
1485                 } else {
1486                         size = w * h * bytespp;
1487                 }
1488         }
1489
1490         if (!size)
1491                 return 0;
1492
1493         return omapfb_alloc_fbmem(fbi, size, paddr);
1494 }
1495
1496 static int omapfb_parse_vram_param(const char *param, int max_entries,
1497                 unsigned long *sizes, unsigned long *paddrs)
1498 {
1499         int fbnum;
1500         unsigned long size;
1501         unsigned long paddr = 0;
1502         char *p, *start;
1503
1504         start = (char *)param;
1505
1506         while (1) {
1507                 p = start;
1508
1509                 fbnum = simple_strtoul(p, &p, 10);
1510
1511                 if (p == start)
1512                         return -EINVAL;
1513
1514                 if (*p != ':')
1515                         return -EINVAL;
1516
1517                 if (fbnum >= max_entries)
1518                         return -EINVAL;
1519
1520                 size = memparse(p + 1, &p);
1521
1522                 if (!size)
1523                         return -EINVAL;
1524
1525                 paddr = 0;
1526
1527                 if (*p == '@') {
1528                         paddr = simple_strtoul(p + 1, &p, 16);
1529
1530                         if (!paddr)
1531                                 return -EINVAL;
1532
1533                 }
1534
1535                 paddrs[fbnum] = paddr;
1536                 sizes[fbnum] = size;
1537
1538                 if (*p == 0)
1539                         break;
1540
1541                 if (*p != ',')
1542                         return -EINVAL;
1543
1544                 ++p;
1545
1546                 start = p;
1547         }
1548
1549         return 0;
1550 }
1551
1552 static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1553 {
1554         int i, r;
1555         unsigned long vram_sizes[10];
1556         unsigned long vram_paddrs[10];
1557
1558         memset(&vram_sizes, 0, sizeof(vram_sizes));
1559         memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1560
1561         if (def_vram && omapfb_parse_vram_param(def_vram, 10,
1562                                 vram_sizes, vram_paddrs)) {
1563                 dev_err(fbdev->dev, "failed to parse vram parameter\n");
1564
1565                 memset(&vram_sizes, 0, sizeof(vram_sizes));
1566                 memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1567         }
1568
1569         for (i = 0; i < fbdev->num_fbs; i++) {
1570                 /* allocate memory automatically only for fb0, or if
1571                  * excplicitly defined with vram or plat data option */
1572                 if (i == 0 || vram_sizes[i] != 0) {
1573                         r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
1574                                         vram_sizes[i], vram_paddrs[i]);
1575
1576                         if (r)
1577                                 return r;
1578                 }
1579         }
1580
1581         for (i = 0; i < fbdev->num_fbs; i++) {
1582                 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1583                 struct omapfb2_mem_region *rg;
1584                 rg = ofbi->region;
1585
1586                 DBG("region%d phys %08x virt %p size=%lu\n",
1587                                 i,
1588                                 rg->paddr,
1589                                 rg->vaddr,
1590                                 rg->size);
1591         }
1592
1593         return 0;
1594 }
1595
1596 int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1597 {
1598         struct omapfb_info *ofbi = FB2OFB(fbi);
1599         struct omapfb2_device *fbdev = ofbi->fbdev;
1600         struct omap_dss_device *display = fb2display(fbi);
1601         struct omapfb2_mem_region *rg = ofbi->region;
1602         unsigned long old_size = rg->size;
1603         unsigned long old_paddr = rg->paddr;
1604         int old_type = rg->type;
1605         int r;
1606
1607         if (type != OMAPFB_MEMTYPE_SDRAM)
1608                 return -EINVAL;
1609
1610         size = PAGE_ALIGN(size);
1611
1612         if (old_size == size && old_type == type)
1613                 return 0;
1614
1615         if (display && display->driver->sync)
1616                         display->driver->sync(display);
1617
1618         omapfb_free_fbmem(fbi);
1619
1620         if (size == 0) {
1621                 clear_fb_info(fbi);
1622                 return 0;
1623         }
1624
1625         r = omapfb_alloc_fbmem(fbi, size, 0);
1626
1627         if (r) {
1628                 if (old_size)
1629                         omapfb_alloc_fbmem(fbi, old_size, old_paddr);
1630
1631                 if (rg->size == 0)
1632                         clear_fb_info(fbi);
1633
1634                 return r;
1635         }
1636
1637         if (old_size == size)
1638                 return 0;
1639
1640         if (old_size == 0) {
1641                 DBG("initializing fb %d\n", ofbi->id);
1642                 r = omapfb_fb_init(fbdev, fbi);
1643                 if (r) {
1644                         DBG("omapfb_fb_init failed\n");
1645                         goto err;
1646                 }
1647                 r = omapfb_apply_changes(fbi, 1);
1648                 if (r) {
1649                         DBG("omapfb_apply_changes failed\n");
1650                         goto err;
1651                 }
1652         } else {
1653                 struct fb_var_screeninfo new_var;
1654                 memcpy(&new_var, &fbi->var, sizeof(new_var));
1655                 r = check_fb_var(fbi, &new_var);
1656                 if (r)
1657                         goto err;
1658                 memcpy(&fbi->var, &new_var, sizeof(fbi->var));
1659                 set_fb_fix(fbi);
1660                 r = setup_vrfb_rotation(fbi);
1661                 if (r)
1662                         goto err;
1663         }
1664
1665         return 0;
1666 err:
1667         omapfb_free_fbmem(fbi);
1668         clear_fb_info(fbi);
1669         return r;
1670 }
1671
1672 static void omapfb_auto_update_work(struct work_struct *work)
1673 {
1674         struct omap_dss_device *dssdev;
1675         struct omap_dss_driver *dssdrv;
1676         struct omapfb_display_data *d;
1677         u16 w, h;
1678         unsigned int freq;
1679         struct omapfb2_device *fbdev;
1680
1681         d = container_of(work, struct omapfb_display_data,
1682                         auto_update_work.work);
1683
1684         dssdev = d->dssdev;
1685         dssdrv = dssdev->driver;
1686         fbdev = d->fbdev;
1687
1688         if (!dssdrv || !dssdrv->update)
1689                 return;
1690
1691         if (dssdrv->sync)
1692                 dssdrv->sync(dssdev);
1693
1694         dssdrv->get_resolution(dssdev, &w, &h);
1695         dssdrv->update(dssdev, 0, 0, w, h);
1696
1697         freq = auto_update_freq;
1698         if (freq == 0)
1699                 freq = 20;
1700         queue_delayed_work(fbdev->auto_update_wq,
1701                         &d->auto_update_work, HZ / freq);
1702 }
1703
1704 void omapfb_start_auto_update(struct omapfb2_device *fbdev,
1705                 struct omap_dss_device *display)
1706 {
1707         struct omapfb_display_data *d;
1708
1709         if (fbdev->auto_update_wq == NULL) {
1710                 struct workqueue_struct *wq;
1711
1712                 wq = create_singlethread_workqueue("omapfb_auto_update");
1713
1714                 if (wq == NULL) {
1715                         dev_err(fbdev->dev, "Failed to create workqueue for "
1716                                         "auto-update\n");
1717                         return;
1718                 }
1719
1720                 fbdev->auto_update_wq = wq;
1721         }
1722
1723         d = get_display_data(fbdev, display);
1724
1725         INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
1726
1727         d->auto_update_work_enabled = true;
1728
1729         omapfb_auto_update_work(&d->auto_update_work.work);
1730 }
1731
1732 void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
1733                 struct omap_dss_device *display)
1734 {
1735         struct omapfb_display_data *d;
1736
1737         d = get_display_data(fbdev, display);
1738
1739         cancel_delayed_work_sync(&d->auto_update_work);
1740
1741         d->auto_update_work_enabled = false;
1742 }
1743
1744 /* initialize fb_info, var, fix to something sane based on the display */
1745 static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1746 {
1747         struct fb_var_screeninfo *var = &fbi->var;
1748         struct omap_dss_device *display = fb2display(fbi);
1749         struct omapfb_info *ofbi = FB2OFB(fbi);
1750         int r = 0;
1751
1752         fbi->fbops = &omapfb_ops;
1753         fbi->flags = FBINFO_FLAG_DEFAULT;
1754         fbi->pseudo_palette = fbdev->pseudo_palette;
1755
1756         if (ofbi->region->size == 0) {
1757                 clear_fb_info(fbi);
1758                 return 0;
1759         }
1760
1761         var->nonstd = 0;
1762         var->bits_per_pixel = 0;
1763
1764         var->rotate = def_rotate;
1765
1766         if (display) {
1767                 u16 w, h;
1768                 int rotation = (var->rotate + ofbi->rotation[0]) % 4;
1769
1770                 display->driver->get_resolution(display, &w, &h);
1771
1772                 if (rotation == FB_ROTATE_CW ||
1773                                 rotation == FB_ROTATE_CCW) {
1774                         var->xres = h;
1775                         var->yres = w;
1776                 } else {
1777                         var->xres = w;
1778                         var->yres = h;
1779                 }
1780
1781                 var->xres_virtual = var->xres;
1782                 var->yres_virtual = var->yres;
1783
1784                 if (!var->bits_per_pixel) {
1785                         switch (omapfb_get_recommended_bpp(fbdev, display)) {
1786                         case 16:
1787                                 var->bits_per_pixel = 16;
1788                                 break;
1789                         case 24:
1790                                 var->bits_per_pixel = 32;
1791                                 break;
1792                         default:
1793                                 dev_err(fbdev->dev, "illegal display "
1794                                                 "bpp\n");
1795                                 return -EINVAL;
1796                         }
1797                 }
1798         } else {
1799                 /* if there's no display, let's just guess some basic values */
1800                 var->xres = 320;
1801                 var->yres = 240;
1802                 var->xres_virtual = var->xres;
1803                 var->yres_virtual = var->yres;
1804                 if (!var->bits_per_pixel)
1805                         var->bits_per_pixel = 16;
1806         }
1807
1808         r = check_fb_var(fbi, var);
1809         if (r)
1810                 goto err;
1811
1812         set_fb_fix(fbi);
1813         r = setup_vrfb_rotation(fbi);
1814         if (r)
1815                 goto err;
1816
1817         r = fb_alloc_cmap(&fbi->cmap, 256, 0);
1818         if (r)
1819                 dev_err(fbdev->dev, "unable to allocate color map memory\n");
1820
1821 err:
1822         return r;
1823 }
1824
1825 static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
1826 {
1827         fb_dealloc_cmap(&fbi->cmap);
1828 }
1829
1830
1831 static void omapfb_free_resources(struct omapfb2_device *fbdev)
1832 {
1833         int i;
1834
1835         DBG("free_resources\n");
1836
1837         if (fbdev == NULL)
1838                 return;
1839
1840         for (i = 0; i < fbdev->num_fbs; i++)
1841                 unregister_framebuffer(fbdev->fbs[i]);
1842
1843         /* free the reserved fbmem */
1844         omapfb_free_all_fbmem(fbdev);
1845
1846         for (i = 0; i < fbdev->num_fbs; i++) {
1847                 fbinfo_cleanup(fbdev, fbdev->fbs[i]);
1848                 framebuffer_release(fbdev->fbs[i]);
1849         }
1850
1851         for (i = 0; i < fbdev->num_displays; i++) {
1852                 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
1853
1854                 if (fbdev->displays[i].auto_update_work_enabled)
1855                         omapfb_stop_auto_update(fbdev, dssdev);
1856
1857                 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
1858                         dssdev->driver->disable(dssdev);
1859
1860                 omap_dss_put_device(dssdev);
1861         }
1862
1863         if (fbdev->auto_update_wq != NULL) {
1864                 flush_workqueue(fbdev->auto_update_wq);
1865                 destroy_workqueue(fbdev->auto_update_wq);
1866                 fbdev->auto_update_wq = NULL;
1867         }
1868
1869         dev_set_drvdata(fbdev->dev, NULL);
1870         kfree(fbdev);
1871 }
1872
1873 static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1874 {
1875         int r, i;
1876
1877         fbdev->num_fbs = 0;
1878
1879         DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
1880
1881         /* allocate fb_infos */
1882         for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
1883                 struct fb_info *fbi;
1884                 struct omapfb_info *ofbi;
1885
1886                 fbi = framebuffer_alloc(sizeof(struct omapfb_info),
1887                                 fbdev->dev);
1888
1889                 if (fbi == NULL) {
1890                         dev_err(fbdev->dev,
1891                                 "unable to allocate memory for plane info\n");
1892                         return -ENOMEM;
1893                 }
1894
1895                 clear_fb_info(fbi);
1896
1897                 fbdev->fbs[i] = fbi;
1898
1899                 ofbi = FB2OFB(fbi);
1900                 ofbi->fbdev = fbdev;
1901                 ofbi->id = i;
1902
1903                 ofbi->region = &fbdev->regions[i];
1904                 ofbi->region->id = i;
1905                 init_rwsem(&ofbi->region->lock);
1906
1907                 /* assign these early, so that fb alloc can use them */
1908                 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1909                         OMAP_DSS_ROT_DMA;
1910                 ofbi->mirror = def_mirror;
1911
1912                 fbdev->num_fbs++;
1913         }
1914
1915         DBG("fb_infos allocated\n");
1916
1917         /* assign overlays for the fbs */
1918         for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
1919                 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1920
1921                 ofbi->overlays[0] = fbdev->overlays[i];
1922                 ofbi->num_overlays = 1;
1923         }
1924
1925         /* allocate fb memories */
1926         r = omapfb_allocate_all_fbs(fbdev);
1927         if (r) {
1928                 dev_err(fbdev->dev, "failed to allocate fbmem\n");
1929                 return r;
1930         }
1931
1932         DBG("fbmems allocated\n");
1933
1934         /* setup fb_infos */
1935         for (i = 0; i < fbdev->num_fbs; i++) {
1936                 struct fb_info *fbi = fbdev->fbs[i];
1937                 struct omapfb_info *ofbi = FB2OFB(fbi);
1938
1939                 omapfb_get_mem_region(ofbi->region);
1940                 r = omapfb_fb_init(fbdev, fbi);
1941                 omapfb_put_mem_region(ofbi->region);
1942
1943                 if (r) {
1944                         dev_err(fbdev->dev, "failed to setup fb_info\n");
1945                         return r;
1946                 }
1947         }
1948
1949         DBG("fb_infos initialized\n");
1950
1951         for (i = 0; i < fbdev->num_fbs; i++) {
1952                 r = register_framebuffer(fbdev->fbs[i]);
1953                 if (r != 0) {
1954                         dev_err(fbdev->dev,
1955                                 "registering framebuffer %d failed\n", i);
1956                         return r;
1957                 }
1958         }
1959
1960         DBG("framebuffers registered\n");
1961
1962         for (i = 0; i < fbdev->num_fbs; i++) {
1963                 struct fb_info *fbi = fbdev->fbs[i];
1964                 struct omapfb_info *ofbi = FB2OFB(fbi);
1965
1966                 omapfb_get_mem_region(ofbi->region);
1967                 r = omapfb_apply_changes(fbi, 1);
1968                 omapfb_put_mem_region(ofbi->region);
1969
1970                 if (r) {
1971                         dev_err(fbdev->dev, "failed to change mode\n");
1972                         return r;
1973                 }
1974         }
1975
1976         /* Enable fb0 */
1977         if (fbdev->num_fbs > 0) {
1978                 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
1979
1980                 if (ofbi->num_overlays > 0) {
1981                         struct omap_overlay *ovl = ofbi->overlays[0];
1982
1983                         ovl->manager->apply(ovl->manager);
1984
1985                         r = omapfb_overlay_enable(ovl, 1);
1986
1987                         if (r) {
1988                                 dev_err(fbdev->dev,
1989                                                 "failed to enable overlay\n");
1990                                 return r;
1991                         }
1992                 }
1993         }
1994
1995         DBG("create_framebuffers done\n");
1996
1997         return 0;
1998 }
1999
2000 static int omapfb_mode_to_timings(const char *mode_str,
2001                 struct omap_dss_device *display,
2002                 struct omap_video_timings *timings, u8 *bpp)
2003 {
2004         struct fb_info *fbi;
2005         struct fb_var_screeninfo *var;
2006         struct fb_ops *fbops;
2007         int r;
2008
2009 #ifdef CONFIG_OMAP2_DSS_VENC
2010         if (strcmp(mode_str, "pal") == 0) {
2011                 *timings = omap_dss_pal_timings;
2012                 *bpp = 24;
2013                 return 0;
2014         } else if (strcmp(mode_str, "ntsc") == 0) {
2015                 *timings = omap_dss_ntsc_timings;
2016                 *bpp = 24;
2017                 return 0;
2018         }
2019 #endif
2020
2021         /* this is quite a hack, but I wanted to use the modedb and for
2022          * that we need fb_info and var, so we create dummy ones */
2023
2024         *bpp = 0;
2025         fbi = NULL;
2026         var = NULL;
2027         fbops = NULL;
2028
2029         fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
2030         if (fbi == NULL) {
2031                 r = -ENOMEM;
2032                 goto err;
2033         }
2034
2035         var = kzalloc(sizeof(*var), GFP_KERNEL);
2036         if (var == NULL) {
2037                 r = -ENOMEM;
2038                 goto err;
2039         }
2040
2041         fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
2042         if (fbops == NULL) {
2043                 r = -ENOMEM;
2044                 goto err;
2045         }
2046
2047         fbi->fbops = fbops;
2048
2049         r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
2050         if (r == 0) {
2051                 r = -EINVAL;
2052                 goto err;
2053         }
2054
2055         if (display->driver->get_timings) {
2056                 display->driver->get_timings(display, timings);
2057         } else {
2058                 timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2059                 timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2060                 timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
2061         }
2062
2063         timings->pixel_clock = PICOS2KHZ(var->pixclock);
2064         timings->hbp = var->left_margin;
2065         timings->hfp = var->right_margin;
2066         timings->vbp = var->upper_margin;
2067         timings->vfp = var->lower_margin;
2068         timings->hsw = var->hsync_len;
2069         timings->vsw = var->vsync_len;
2070         timings->x_res = var->xres;
2071         timings->y_res = var->yres;
2072         timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ?
2073                                 OMAPDSS_SIG_ACTIVE_HIGH :
2074                                 OMAPDSS_SIG_ACTIVE_LOW;
2075         timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ?
2076                                 OMAPDSS_SIG_ACTIVE_HIGH :
2077                                 OMAPDSS_SIG_ACTIVE_LOW;
2078         timings->interlace = var->vmode & FB_VMODE_INTERLACED;
2079
2080         switch (var->bits_per_pixel) {
2081         case 16:
2082                 *bpp = 16;
2083                 break;
2084         case 24:
2085         case 32:
2086         default:
2087                 *bpp = 24;
2088                 break;
2089         }
2090
2091         r = 0;
2092
2093 err:
2094         kfree(fbi);
2095         kfree(var);
2096         kfree(fbops);
2097
2098         return r;
2099 }
2100
2101 static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2102                 struct omap_dss_device *display, char *mode_str)
2103 {
2104         int r;
2105         u8 bpp;
2106         struct omap_video_timings timings, temp_timings;
2107         struct omapfb_display_data *d;
2108
2109         r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp);
2110         if (r)
2111                 return r;
2112
2113         d = get_display_data(fbdev, display);
2114         d->bpp_override = bpp;
2115
2116         if (display->driver->check_timings) {
2117                 r = display->driver->check_timings(display, &timings);
2118                 if (r)
2119                         return r;
2120         } else {
2121                 /* If check_timings is not present compare xres and yres */
2122                 if (display->driver->get_timings) {
2123                         display->driver->get_timings(display, &temp_timings);
2124
2125                         if (temp_timings.x_res != timings.x_res ||
2126                                 temp_timings.y_res != timings.y_res)
2127                                 return -EINVAL;
2128                 }
2129         }
2130
2131         if (display->driver->set_timings)
2132                         display->driver->set_timings(display, &timings);
2133
2134         return 0;
2135 }
2136
2137 static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
2138                 struct omap_dss_device *dssdev)
2139 {
2140         struct omapfb_display_data *d;
2141
2142         BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
2143
2144         d = get_display_data(fbdev, dssdev);
2145
2146         if (d->bpp_override != 0)
2147                 return d->bpp_override;
2148
2149         return dssdev->driver->get_recommended_bpp(dssdev);
2150 }
2151
2152 static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2153 {
2154         char *str, *options, *this_opt;
2155         int r = 0;
2156
2157         str = kstrdup(def_mode, GFP_KERNEL);
2158         if (!str)
2159                 return -ENOMEM;
2160         options = str;
2161
2162         while (!r && (this_opt = strsep(&options, ",")) != NULL) {
2163                 char *p, *display_str, *mode_str;
2164                 struct omap_dss_device *display;
2165                 int i;
2166
2167                 p = strchr(this_opt, ':');
2168                 if (!p) {
2169                         r = -EINVAL;
2170                         break;
2171                 }
2172
2173                 *p = 0;
2174                 display_str = this_opt;
2175                 mode_str = p + 1;
2176
2177                 display = NULL;
2178                 for (i = 0; i < fbdev->num_displays; ++i) {
2179                         if (strcmp(fbdev->displays[i].dssdev->name,
2180                                                 display_str) == 0) {
2181                                 display = fbdev->displays[i].dssdev;
2182                                 break;
2183                         }
2184                 }
2185
2186                 if (!display) {
2187                         r = -EINVAL;
2188                         break;
2189                 }
2190
2191                 r = omapfb_set_def_mode(fbdev, display, mode_str);
2192                 if (r)
2193                         break;
2194         }
2195
2196         kfree(str);
2197
2198         return r;
2199 }
2200
2201 static void fb_videomode_to_omap_timings(struct fb_videomode *m,
2202                 struct omap_dss_device *display,
2203                 struct omap_video_timings *t)
2204 {
2205         if (display->driver->get_timings) {
2206                 display->driver->get_timings(display, t);
2207         } else {
2208                 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2209                 t->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2210                 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
2211         }
2212
2213         t->x_res = m->xres;
2214         t->y_res = m->yres;
2215         t->pixel_clock = PICOS2KHZ(m->pixclock);
2216         t->hsw = m->hsync_len;
2217         t->hfp = m->right_margin;
2218         t->hbp = m->left_margin;
2219         t->vsw = m->vsync_len;
2220         t->vfp = m->lower_margin;
2221         t->vbp = m->upper_margin;
2222         t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ?
2223                                 OMAPDSS_SIG_ACTIVE_HIGH :
2224                                 OMAPDSS_SIG_ACTIVE_LOW;
2225         t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ?
2226                                 OMAPDSS_SIG_ACTIVE_HIGH :
2227                                 OMAPDSS_SIG_ACTIVE_LOW;
2228         t->interlace = m->vmode & FB_VMODE_INTERLACED;
2229 }
2230
2231 static int omapfb_find_best_mode(struct omap_dss_device *display,
2232                 struct omap_video_timings *timings)
2233 {
2234         struct fb_monspecs *specs;
2235         u8 *edid;
2236         int r, i, best_xres, best_idx, len;
2237
2238         if (!display->driver->read_edid)
2239                 return -ENODEV;
2240
2241         len = 0x80 * 2;
2242         edid = kmalloc(len, GFP_KERNEL);
2243
2244         r = display->driver->read_edid(display, edid, len);
2245         if (r < 0)
2246                 goto err1;
2247
2248         specs = kzalloc(sizeof(*specs), GFP_KERNEL);
2249
2250         fb_edid_to_monspecs(edid, specs);
2251
2252         if (edid[126] > 0)
2253                 fb_edid_add_monspecs(edid + 0x80, specs);
2254
2255         best_xres = 0;
2256         best_idx = -1;
2257
2258         for (i = 0; i < specs->modedb_len; ++i) {
2259                 struct fb_videomode *m;
2260                 struct omap_video_timings t;
2261
2262                 m = &specs->modedb[i];
2263
2264                 if (m->pixclock == 0)
2265                         continue;
2266
2267                 /* skip repeated pixel modes */
2268                 if (m->xres == 2880 || m->xres == 1440)
2269                         continue;
2270
2271                 fb_videomode_to_omap_timings(m, display, &t);
2272
2273                 r = display->driver->check_timings(display, &t);
2274                 if (r == 0 && best_xres < m->xres) {
2275                         best_xres = m->xres;
2276                         best_idx = i;
2277                 }
2278         }
2279
2280         if (best_xres == 0) {
2281                 r = -ENOENT;
2282                 goto err2;
2283         }
2284
2285         fb_videomode_to_omap_timings(&specs->modedb[best_idx], display,
2286                 timings);
2287
2288         r = 0;
2289
2290 err2:
2291         fb_destroy_modedb(specs->modedb);
2292         kfree(specs);
2293 err1:
2294         kfree(edid);
2295
2296         return r;
2297 }
2298
2299 static int omapfb_init_display(struct omapfb2_device *fbdev,
2300                 struct omap_dss_device *dssdev)
2301 {
2302         struct omap_dss_driver *dssdrv = dssdev->driver;
2303         struct omapfb_display_data *d;
2304         int r;
2305
2306         r = dssdrv->enable(dssdev);
2307         if (r) {
2308                 dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
2309                                 dssdev->name);
2310                 return r;
2311         }
2312
2313         d = get_display_data(fbdev, dssdev);
2314
2315         d->fbdev = fbdev;
2316
2317         if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
2318                 u16 w, h;
2319
2320                 if (auto_update) {
2321                         omapfb_start_auto_update(fbdev, dssdev);
2322                         d->update_mode = OMAPFB_AUTO_UPDATE;
2323                 } else {
2324                         d->update_mode = OMAPFB_MANUAL_UPDATE;
2325                 }
2326
2327                 if (dssdrv->enable_te) {
2328                         r = dssdrv->enable_te(dssdev, 1);
2329                         if (r) {
2330                                 dev_err(fbdev->dev, "Failed to set TE\n");
2331                                 return r;
2332                         }
2333                 }
2334
2335                 dssdrv->get_resolution(dssdev, &w, &h);
2336                 r = dssdrv->update(dssdev, 0, 0, w, h);
2337                 if (r) {
2338                         dev_err(fbdev->dev,
2339                                         "Failed to update display\n");
2340                         return r;
2341                 }
2342         } else {
2343                 d->update_mode = OMAPFB_AUTO_UPDATE;
2344         }
2345
2346         return 0;
2347 }
2348
2349 static int __init omapfb_probe(struct platform_device *pdev)
2350 {
2351         struct omapfb2_device *fbdev = NULL;
2352         int r = 0;
2353         int i;
2354         struct omap_overlay *ovl;
2355         struct omap_dss_device *def_display;
2356         struct omap_dss_device *dssdev;
2357
2358         DBG("omapfb_probe\n");
2359
2360         if (pdev->num_resources != 0) {
2361                 dev_err(&pdev->dev, "probed for an unknown device\n");
2362                 r = -ENODEV;
2363                 goto err0;
2364         }
2365
2366         fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
2367         if (fbdev == NULL) {
2368                 r = -ENOMEM;
2369                 goto err0;
2370         }
2371
2372         /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
2373         *        available for OMAP2 and OMAP3
2374         */
2375         if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
2376                 def_vrfb = 0;
2377                 dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
2378                                 "ignoring the module parameter vrfb=y\n");
2379         }
2380
2381
2382         mutex_init(&fbdev->mtx);
2383
2384         fbdev->dev = &pdev->dev;
2385         platform_set_drvdata(pdev, fbdev);
2386
2387         r = 0;
2388         fbdev->num_displays = 0;
2389         dssdev = NULL;
2390         for_each_dss_dev(dssdev) {
2391                 struct omapfb_display_data *d;
2392
2393                 omap_dss_get_device(dssdev);
2394
2395                 if (!dssdev->driver) {
2396                         dev_warn(&pdev->dev, "no driver for display: %s\n",
2397                                 dssdev->name);
2398                         omap_dss_put_device(dssdev);
2399                         continue;
2400                 }
2401
2402                 d = &fbdev->displays[fbdev->num_displays++];
2403                 d->dssdev = dssdev;
2404                 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
2405                         d->update_mode = OMAPFB_MANUAL_UPDATE;
2406                 else
2407                         d->update_mode = OMAPFB_AUTO_UPDATE;
2408         }
2409
2410         if (r)
2411                 goto cleanup;
2412
2413         if (fbdev->num_displays == 0) {
2414                 dev_err(&pdev->dev, "no displays\n");
2415                 r = -EINVAL;
2416                 goto cleanup;
2417         }
2418
2419         fbdev->num_overlays = omap_dss_get_num_overlays();
2420         for (i = 0; i < fbdev->num_overlays; i++)
2421                 fbdev->overlays[i] = omap_dss_get_overlay(i);
2422
2423         fbdev->num_managers = omap_dss_get_num_overlay_managers();
2424         for (i = 0; i < fbdev->num_managers; i++)
2425                 fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2426
2427         /* gfx overlay should be the default one. find a display
2428          * connected to that, and use it as default display */
2429         ovl = omap_dss_get_overlay(0);
2430         if (ovl->manager && ovl->manager->device) {
2431                 def_display = ovl->manager->device;
2432         } else {
2433                 dev_warn(&pdev->dev, "cannot find default display\n");
2434                 def_display = NULL;
2435         }
2436
2437         if (def_mode && strlen(def_mode) > 0) {
2438                 if (omapfb_parse_def_modes(fbdev))
2439                         dev_warn(&pdev->dev, "cannot parse default modes\n");
2440         } else if (def_display && def_display->driver->set_timings &&
2441                         def_display->driver->check_timings) {
2442                 struct omap_video_timings t;
2443
2444                 r = omapfb_find_best_mode(def_display, &t);
2445
2446                 if (r == 0)
2447                         def_display->driver->set_timings(def_display, &t);
2448         }
2449
2450         r = omapfb_create_framebuffers(fbdev);
2451         if (r)
2452                 goto cleanup;
2453
2454         for (i = 0; i < fbdev->num_managers; i++) {
2455                 struct omap_overlay_manager *mgr;
2456                 mgr = fbdev->managers[i];
2457                 r = mgr->apply(mgr);
2458                 if (r)
2459                         dev_warn(fbdev->dev, "failed to apply dispc config\n");
2460         }
2461
2462         DBG("mgr->apply'ed\n");
2463
2464         if (def_display) {
2465                 r = omapfb_init_display(fbdev, def_display);
2466                 if (r) {
2467                         dev_err(fbdev->dev,
2468                                         "failed to initialize default "
2469                                         "display\n");
2470                         goto cleanup;
2471                 }
2472         }
2473
2474         DBG("create sysfs for fbs\n");
2475         r = omapfb_create_sysfs(fbdev);
2476         if (r) {
2477                 dev_err(fbdev->dev, "failed to create sysfs entries\n");
2478                 goto cleanup;
2479         }
2480
2481         return 0;
2482
2483 cleanup:
2484         omapfb_free_resources(fbdev);
2485 err0:
2486         dev_err(&pdev->dev, "failed to setup omapfb\n");
2487         return r;
2488 }
2489
2490 static int __exit omapfb_remove(struct platform_device *pdev)
2491 {
2492         struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
2493
2494         /* FIXME: wait till completion of pending events */
2495
2496         omapfb_remove_sysfs(fbdev);
2497
2498         omapfb_free_resources(fbdev);
2499
2500         return 0;
2501 }
2502
2503 static struct platform_driver omapfb_driver = {
2504         .remove         = __exit_p(omapfb_remove),
2505         .driver         = {
2506                 .name   = "omapfb",
2507                 .owner  = THIS_MODULE,
2508         },
2509 };
2510
2511 static int __init omapfb_init(void)
2512 {
2513         DBG("omapfb_init\n");
2514
2515         if (platform_driver_probe(&omapfb_driver, omapfb_probe)) {
2516                 printk(KERN_ERR "failed to register omapfb driver\n");
2517                 return -ENODEV;
2518         }
2519
2520         return 0;
2521 }
2522
2523 static void __exit omapfb_exit(void)
2524 {
2525         DBG("omapfb_exit\n");
2526         platform_driver_unregister(&omapfb_driver);
2527 }
2528
2529 module_param_named(mode, def_mode, charp, 0);
2530 module_param_named(vram, def_vram, charp, 0);
2531 module_param_named(rotate, def_rotate, int, 0);
2532 module_param_named(vrfb, def_vrfb, bool, 0);
2533 module_param_named(mirror, def_mirror, bool, 0);
2534
2535 /* late_initcall to let panel/ctrl drivers loaded first.
2536  * I guess better option would be a more dynamic approach,
2537  * so that omapfb reacts to new panels when they are loaded */
2538 late_initcall(omapfb_init);
2539 /*module_init(omapfb_init);*/
2540 module_exit(omapfb_exit);
2541
2542 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
2543 MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
2544 MODULE_LICENSE("GPL v2");