Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
omapfb-main.c
Go to the documentation of this file.
1 /*
2  * linux/drivers/video/omap2/omapfb-main.c
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  * Author: Tomi Valkeinen <[email protected]>
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 {
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 
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 
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 
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 
639 
640  if (var->nonstd)
642  else {
643  switch (var->bits_per_pixel) {
644  case 32:
645  case 24:
646  case 16:
647  case 12:
649  /* 12bpp is stored in 16 bits */
650  break;
651  case 1:
652  case 2:
653  case 4:
654  case 8:
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 ?
739  var->sync |= timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
741  var->vmode = timings.interlace ?
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;
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() */
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;
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) &&
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. */
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]);
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 static void omapfb_clear_fb(struct fb_info *fbi)
1597 {
1598  const struct fb_fillrect rect = {
1599  .dx = 0,
1600  .dy = 0,
1601  .width = fbi->var.xres_virtual,
1602  .height = fbi->var.yres_virtual,
1603  .color = 0,
1604  .rop = ROP_COPY,
1605  };
1606 
1607  cfb_fillrect(fbi, &rect);
1608 }
1609 
1610 int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1611 {
1612  struct omapfb_info *ofbi = FB2OFB(fbi);
1613  struct omapfb2_device *fbdev = ofbi->fbdev;
1614  struct omap_dss_device *display = fb2display(fbi);
1615  struct omapfb2_mem_region *rg = ofbi->region;
1616  unsigned long old_size = rg->size;
1617  unsigned long old_paddr = rg->paddr;
1618  int old_type = rg->type;
1619  int r;
1620 
1621  if (type != OMAPFB_MEMTYPE_SDRAM)
1622  return -EINVAL;
1623 
1624  size = PAGE_ALIGN(size);
1625 
1626  if (old_size == size && old_type == type)
1627  return 0;
1628 
1629  if (display && display->driver->sync)
1630  display->driver->sync(display);
1631 
1632  omapfb_free_fbmem(fbi);
1633 
1634  if (size == 0) {
1635  clear_fb_info(fbi);
1636  return 0;
1637  }
1638 
1639  r = omapfb_alloc_fbmem(fbi, size, 0);
1640 
1641  if (r) {
1642  if (old_size)
1643  omapfb_alloc_fbmem(fbi, old_size, old_paddr);
1644 
1645  if (rg->size == 0)
1646  clear_fb_info(fbi);
1647 
1648  return r;
1649  }
1650 
1651  if (old_size == size)
1652  return 0;
1653 
1654  if (old_size == 0) {
1655  DBG("initializing fb %d\n", ofbi->id);
1656  r = omapfb_fb_init(fbdev, fbi);
1657  if (r) {
1658  DBG("omapfb_fb_init failed\n");
1659  goto err;
1660  }
1661  r = omapfb_apply_changes(fbi, 1);
1662  if (r) {
1663  DBG("omapfb_apply_changes failed\n");
1664  goto err;
1665  }
1666  } else {
1667  struct fb_var_screeninfo new_var;
1668  memcpy(&new_var, &fbi->var, sizeof(new_var));
1669  r = check_fb_var(fbi, &new_var);
1670  if (r)
1671  goto err;
1672  memcpy(&fbi->var, &new_var, sizeof(fbi->var));
1673  set_fb_fix(fbi);
1674  r = setup_vrfb_rotation(fbi);
1675  if (r)
1676  goto err;
1677  }
1678 
1679  omapfb_clear_fb(fbi);
1680 
1681  return 0;
1682 err:
1683  omapfb_free_fbmem(fbi);
1684  clear_fb_info(fbi);
1685  return r;
1686 }
1687 
1688 static void omapfb_auto_update_work(struct work_struct *work)
1689 {
1690  struct omap_dss_device *dssdev;
1691  struct omap_dss_driver *dssdrv;
1692  struct omapfb_display_data *d;
1693  u16 w, h;
1694  unsigned int freq;
1695  struct omapfb2_device *fbdev;
1696 
1697  d = container_of(work, struct omapfb_display_data,
1698  auto_update_work.work);
1699 
1700  dssdev = d->dssdev;
1701  dssdrv = dssdev->driver;
1702  fbdev = d->fbdev;
1703 
1704  if (!dssdrv || !dssdrv->update)
1705  return;
1706 
1707  if (dssdrv->sync)
1708  dssdrv->sync(dssdev);
1709 
1710  dssdrv->get_resolution(dssdev, &w, &h);
1711  dssdrv->update(dssdev, 0, 0, w, h);
1712 
1713  freq = auto_update_freq;
1714  if (freq == 0)
1715  freq = 20;
1717  &d->auto_update_work, HZ / freq);
1718 }
1719 
1721  struct omap_dss_device *display)
1722 {
1723  struct omapfb_display_data *d;
1724 
1725  if (fbdev->auto_update_wq == NULL) {
1726  struct workqueue_struct *wq;
1727 
1728  wq = create_singlethread_workqueue("omapfb_auto_update");
1729 
1730  if (wq == NULL) {
1731  dev_err(fbdev->dev, "Failed to create workqueue for "
1732  "auto-update\n");
1733  return;
1734  }
1735 
1736  fbdev->auto_update_wq = wq;
1737  }
1738 
1739  d = get_display_data(fbdev, display);
1740 
1741  INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
1742 
1743  d->auto_update_work_enabled = true;
1744 
1745  omapfb_auto_update_work(&d->auto_update_work.work);
1746 }
1747 
1749  struct omap_dss_device *display)
1750 {
1751  struct omapfb_display_data *d;
1752 
1753  d = get_display_data(fbdev, display);
1754 
1756 
1757  d->auto_update_work_enabled = false;
1758 }
1759 
1760 /* initialize fb_info, var, fix to something sane based on the display */
1761 static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1762 {
1763  struct fb_var_screeninfo *var = &fbi->var;
1764  struct omap_dss_device *display = fb2display(fbi);
1765  struct omapfb_info *ofbi = FB2OFB(fbi);
1766  int r = 0;
1767 
1768  fbi->fbops = &omapfb_ops;
1769  fbi->flags = FBINFO_FLAG_DEFAULT;
1770  fbi->pseudo_palette = fbdev->pseudo_palette;
1771 
1772  if (ofbi->region->size == 0) {
1773  clear_fb_info(fbi);
1774  return 0;
1775  }
1776 
1777  var->nonstd = 0;
1778  var->bits_per_pixel = 0;
1779 
1780  var->rotate = def_rotate;
1781 
1782  if (display) {
1783  u16 w, h;
1784  int rotation = (var->rotate + ofbi->rotation[0]) % 4;
1785 
1786  display->driver->get_resolution(display, &w, &h);
1787 
1788  if (rotation == FB_ROTATE_CW ||
1789  rotation == FB_ROTATE_CCW) {
1790  var->xres = h;
1791  var->yres = w;
1792  } else {
1793  var->xres = w;
1794  var->yres = h;
1795  }
1796 
1797  var->xres_virtual = var->xres;
1798  var->yres_virtual = var->yres;
1799 
1800  if (!var->bits_per_pixel) {
1801  switch (omapfb_get_recommended_bpp(fbdev, display)) {
1802  case 16:
1803  var->bits_per_pixel = 16;
1804  break;
1805  case 24:
1806  var->bits_per_pixel = 32;
1807  break;
1808  default:
1809  dev_err(fbdev->dev, "illegal display "
1810  "bpp\n");
1811  return -EINVAL;
1812  }
1813  }
1814  } else {
1815  /* if there's no display, let's just guess some basic values */
1816  var->xres = 320;
1817  var->yres = 240;
1818  var->xres_virtual = var->xres;
1819  var->yres_virtual = var->yres;
1820  if (!var->bits_per_pixel)
1821  var->bits_per_pixel = 16;
1822  }
1823 
1824  r = check_fb_var(fbi, var);
1825  if (r)
1826  goto err;
1827 
1828  set_fb_fix(fbi);
1829  r = setup_vrfb_rotation(fbi);
1830  if (r)
1831  goto err;
1832 
1833  r = fb_alloc_cmap(&fbi->cmap, 256, 0);
1834  if (r)
1835  dev_err(fbdev->dev, "unable to allocate color map memory\n");
1836 
1837 err:
1838  return r;
1839 }
1840 
1841 static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
1842 {
1843  fb_dealloc_cmap(&fbi->cmap);
1844 }
1845 
1846 
1847 static void omapfb_free_resources(struct omapfb2_device *fbdev)
1848 {
1849  int i;
1850 
1851  DBG("free_resources\n");
1852 
1853  if (fbdev == NULL)
1854  return;
1855 
1856  for (i = 0; i < fbdev->num_fbs; i++)
1857  unregister_framebuffer(fbdev->fbs[i]);
1858 
1859  /* free the reserved fbmem */
1860  omapfb_free_all_fbmem(fbdev);
1861 
1862  for (i = 0; i < fbdev->num_fbs; i++) {
1863  fbinfo_cleanup(fbdev, fbdev->fbs[i]);
1864  framebuffer_release(fbdev->fbs[i]);
1865  }
1866 
1867  for (i = 0; i < fbdev->num_displays; i++) {
1868  struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
1869 
1870  if (fbdev->displays[i].auto_update_work_enabled)
1871  omapfb_stop_auto_update(fbdev, dssdev);
1872 
1873  if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
1874  dssdev->driver->disable(dssdev);
1875 
1876  omap_dss_put_device(dssdev);
1877  }
1878 
1879  if (fbdev->auto_update_wq != NULL) {
1882  fbdev->auto_update_wq = NULL;
1883  }
1884 
1885  dev_set_drvdata(fbdev->dev, NULL);
1886  kfree(fbdev);
1887 }
1888 
1889 static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1890 {
1891  int r, i;
1892 
1893  fbdev->num_fbs = 0;
1894 
1895  DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
1896 
1897  /* allocate fb_infos */
1898  for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
1899  struct fb_info *fbi;
1900  struct omapfb_info *ofbi;
1901 
1902  fbi = framebuffer_alloc(sizeof(struct omapfb_info),
1903  fbdev->dev);
1904 
1905  if (fbi == NULL) {
1906  dev_err(fbdev->dev,
1907  "unable to allocate memory for plane info\n");
1908  return -ENOMEM;
1909  }
1910 
1911  clear_fb_info(fbi);
1912 
1913  fbdev->fbs[i] = fbi;
1914 
1915  ofbi = FB2OFB(fbi);
1916  ofbi->fbdev = fbdev;
1917  ofbi->id = i;
1918 
1919  ofbi->region = &fbdev->regions[i];
1920  ofbi->region->id = i;
1921  init_rwsem(&ofbi->region->lock);
1922 
1923  /* assign these early, so that fb alloc can use them */
1924  ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1926  ofbi->mirror = def_mirror;
1927 
1928  fbdev->num_fbs++;
1929  }
1930 
1931  DBG("fb_infos allocated\n");
1932 
1933  /* assign overlays for the fbs */
1934  for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
1935  struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1936 
1937  ofbi->overlays[0] = fbdev->overlays[i];
1938  ofbi->num_overlays = 1;
1939  }
1940 
1941  /* allocate fb memories */
1942  r = omapfb_allocate_all_fbs(fbdev);
1943  if (r) {
1944  dev_err(fbdev->dev, "failed to allocate fbmem\n");
1945  return r;
1946  }
1947 
1948  DBG("fbmems allocated\n");
1949 
1950  /* setup fb_infos */
1951  for (i = 0; i < fbdev->num_fbs; i++) {
1952  struct fb_info *fbi = fbdev->fbs[i];
1953  struct omapfb_info *ofbi = FB2OFB(fbi);
1954 
1955  omapfb_get_mem_region(ofbi->region);
1956  r = omapfb_fb_init(fbdev, fbi);
1957  omapfb_put_mem_region(ofbi->region);
1958 
1959  if (r) {
1960  dev_err(fbdev->dev, "failed to setup fb_info\n");
1961  return r;
1962  }
1963  }
1964 
1965  for (i = 0; i < fbdev->num_fbs; i++) {
1966  struct fb_info *fbi = fbdev->fbs[i];
1967  struct omapfb_info *ofbi = FB2OFB(fbi);
1968 
1969  if (ofbi->region->size == 0)
1970  continue;
1971 
1972  omapfb_clear_fb(fbi);
1973  }
1974 
1975  DBG("fb_infos initialized\n");
1976 
1977  for (i = 0; i < fbdev->num_fbs; i++) {
1978  r = register_framebuffer(fbdev->fbs[i]);
1979  if (r != 0) {
1980  dev_err(fbdev->dev,
1981  "registering framebuffer %d failed\n", i);
1982  return r;
1983  }
1984  }
1985 
1986  DBG("framebuffers registered\n");
1987 
1988  for (i = 0; i < fbdev->num_fbs; i++) {
1989  struct fb_info *fbi = fbdev->fbs[i];
1990  struct omapfb_info *ofbi = FB2OFB(fbi);
1991 
1992  omapfb_get_mem_region(ofbi->region);
1993  r = omapfb_apply_changes(fbi, 1);
1994  omapfb_put_mem_region(ofbi->region);
1995 
1996  if (r) {
1997  dev_err(fbdev->dev, "failed to change mode\n");
1998  return r;
1999  }
2000  }
2001 
2002  /* Enable fb0 */
2003  if (fbdev->num_fbs > 0) {
2004  struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
2005 
2006  if (ofbi->num_overlays > 0) {
2007  struct omap_overlay *ovl = ofbi->overlays[0];
2008 
2009  ovl->manager->apply(ovl->manager);
2010 
2011  r = omapfb_overlay_enable(ovl, 1);
2012 
2013  if (r) {
2014  dev_err(fbdev->dev,
2015  "failed to enable overlay\n");
2016  return r;
2017  }
2018  }
2019  }
2020 
2021  DBG("create_framebuffers done\n");
2022 
2023  return 0;
2024 }
2025 
2026 static int omapfb_mode_to_timings(const char *mode_str,
2027  struct omap_dss_device *display,
2028  struct omap_video_timings *timings, u8 *bpp)
2029 {
2030  struct fb_info *fbi;
2031  struct fb_var_screeninfo *var;
2032  struct fb_ops *fbops;
2033  int r;
2034 
2035 #ifdef CONFIG_OMAP2_DSS_VENC
2036  if (strcmp(mode_str, "pal") == 0) {
2037  *timings = omap_dss_pal_timings;
2038  *bpp = 24;
2039  return 0;
2040  } else if (strcmp(mode_str, "ntsc") == 0) {
2041  *timings = omap_dss_ntsc_timings;
2042  *bpp = 24;
2043  return 0;
2044  }
2045 #endif
2046 
2047  /* this is quite a hack, but I wanted to use the modedb and for
2048  * that we need fb_info and var, so we create dummy ones */
2049 
2050  *bpp = 0;
2051  fbi = NULL;
2052  var = NULL;
2053  fbops = NULL;
2054 
2055  fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
2056  if (fbi == NULL) {
2057  r = -ENOMEM;
2058  goto err;
2059  }
2060 
2061  var = kzalloc(sizeof(*var), GFP_KERNEL);
2062  if (var == NULL) {
2063  r = -ENOMEM;
2064  goto err;
2065  }
2066 
2067  fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
2068  if (fbops == NULL) {
2069  r = -ENOMEM;
2070  goto err;
2071  }
2072 
2073  fbi->fbops = fbops;
2074 
2075  r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
2076  if (r == 0) {
2077  r = -EINVAL;
2078  goto err;
2079  }
2080 
2081  if (display->driver->get_timings) {
2082  display->driver->get_timings(display, timings);
2083  } else {
2085  timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2087  }
2088 
2089  timings->pixel_clock = PICOS2KHZ(var->pixclock);
2090  timings->hbp = var->left_margin;
2091  timings->hfp = var->right_margin;
2092  timings->vbp = var->upper_margin;
2093  timings->vfp = var->lower_margin;
2094  timings->hsw = var->hsync_len;
2095  timings->vsw = var->vsync_len;
2096  timings->x_res = var->xres;
2097  timings->y_res = var->yres;
2098  timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ?
2101  timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ?
2104  timings->interlace = var->vmode & FB_VMODE_INTERLACED;
2105 
2106  switch (var->bits_per_pixel) {
2107  case 16:
2108  *bpp = 16;
2109  break;
2110  case 24:
2111  case 32:
2112  default:
2113  *bpp = 24;
2114  break;
2115  }
2116 
2117  r = 0;
2118 
2119 err:
2120  kfree(fbi);
2121  kfree(var);
2122  kfree(fbops);
2123 
2124  return r;
2125 }
2126 
2127 static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2128  struct omap_dss_device *display, char *mode_str)
2129 {
2130  int r;
2131  u8 bpp;
2132  struct omap_video_timings timings, temp_timings;
2133  struct omapfb_display_data *d;
2134 
2135  r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp);
2136  if (r)
2137  return r;
2138 
2139  d = get_display_data(fbdev, display);
2140  d->bpp_override = bpp;
2141 
2142  if (display->driver->check_timings) {
2143  r = display->driver->check_timings(display, &timings);
2144  if (r)
2145  return r;
2146  } else {
2147  /* If check_timings is not present compare xres and yres */
2148  if (display->driver->get_timings) {
2149  display->driver->get_timings(display, &temp_timings);
2150 
2151  if (temp_timings.x_res != timings.x_res ||
2152  temp_timings.y_res != timings.y_res)
2153  return -EINVAL;
2154  }
2155  }
2156 
2157  if (display->driver->set_timings)
2158  display->driver->set_timings(display, &timings);
2159 
2160  return 0;
2161 }
2162 
2163 static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
2164  struct omap_dss_device *dssdev)
2165 {
2166  struct omapfb_display_data *d;
2167 
2168  BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
2169 
2170  d = get_display_data(fbdev, dssdev);
2171 
2172  if (d->bpp_override != 0)
2173  return d->bpp_override;
2174 
2175  return dssdev->driver->get_recommended_bpp(dssdev);
2176 }
2177 
2178 static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2179 {
2180  char *str, *options, *this_opt;
2181  int r = 0;
2182 
2183  str = kstrdup(def_mode, GFP_KERNEL);
2184  if (!str)
2185  return -ENOMEM;
2186  options = str;
2187 
2188  while (!r && (this_opt = strsep(&options, ",")) != NULL) {
2189  char *p, *display_str, *mode_str;
2190  struct omap_dss_device *display;
2191  int i;
2192 
2193  p = strchr(this_opt, ':');
2194  if (!p) {
2195  r = -EINVAL;
2196  break;
2197  }
2198 
2199  *p = 0;
2200  display_str = this_opt;
2201  mode_str = p + 1;
2202 
2203  display = NULL;
2204  for (i = 0; i < fbdev->num_displays; ++i) {
2205  if (strcmp(fbdev->displays[i].dssdev->name,
2206  display_str) == 0) {
2207  display = fbdev->displays[i].dssdev;
2208  break;
2209  }
2210  }
2211 
2212  if (!display) {
2213  r = -EINVAL;
2214  break;
2215  }
2216 
2217  r = omapfb_set_def_mode(fbdev, display, mode_str);
2218  if (r)
2219  break;
2220  }
2221 
2222  kfree(str);
2223 
2224  return r;
2225 }
2226 
2227 static void fb_videomode_to_omap_timings(struct fb_videomode *m,
2228  struct omap_dss_device *display,
2229  struct omap_video_timings *t)
2230 {
2231  if (display->driver->get_timings) {
2232  display->driver->get_timings(display, t);
2233  } else {
2237  }
2238 
2239  t->x_res = m->xres;
2240  t->y_res = m->yres;
2241  t->pixel_clock = PICOS2KHZ(m->pixclock);
2242  t->hsw = m->hsync_len;
2243  t->hfp = m->right_margin;
2244  t->hbp = m->left_margin;
2245  t->vsw = m->vsync_len;
2246  t->vfp = m->lower_margin;
2247  t->vbp = m->upper_margin;
2255 }
2256 
2257 static int omapfb_find_best_mode(struct omap_dss_device *display,
2258  struct omap_video_timings *timings)
2259 {
2260  struct fb_monspecs *specs;
2261  u8 *edid;
2262  int r, i, best_xres, best_idx, len;
2263 
2264  if (!display->driver->read_edid)
2265  return -ENODEV;
2266 
2267  len = 0x80 * 2;
2268  edid = kmalloc(len, GFP_KERNEL);
2269 
2270  r = display->driver->read_edid(display, edid, len);
2271  if (r < 0)
2272  goto err1;
2273 
2274  specs = kzalloc(sizeof(*specs), GFP_KERNEL);
2275 
2276  fb_edid_to_monspecs(edid, specs);
2277 
2278  if (edid[126] > 0)
2279  fb_edid_add_monspecs(edid + 0x80, specs);
2280 
2281  best_xres = 0;
2282  best_idx = -1;
2283 
2284  for (i = 0; i < specs->modedb_len; ++i) {
2285  struct fb_videomode *m;
2286  struct omap_video_timings t;
2287 
2288  m = &specs->modedb[i];
2289 
2290  if (m->pixclock == 0)
2291  continue;
2292 
2293  /* skip repeated pixel modes */
2294  if (m->xres == 2880 || m->xres == 1440)
2295  continue;
2296 
2297  fb_videomode_to_omap_timings(m, display, &t);
2298 
2299  r = display->driver->check_timings(display, &t);
2300  if (r == 0 && best_xres < m->xres) {
2301  best_xres = m->xres;
2302  best_idx = i;
2303  }
2304  }
2305 
2306  if (best_xres == 0) {
2307  r = -ENOENT;
2308  goto err2;
2309  }
2310 
2311  fb_videomode_to_omap_timings(&specs->modedb[best_idx], display,
2312  timings);
2313 
2314  r = 0;
2315 
2316 err2:
2317  fb_destroy_modedb(specs->modedb);
2318  kfree(specs);
2319 err1:
2320  kfree(edid);
2321 
2322  return r;
2323 }
2324 
2325 static int omapfb_init_display(struct omapfb2_device *fbdev,
2326  struct omap_dss_device *dssdev)
2327 {
2328  struct omap_dss_driver *dssdrv = dssdev->driver;
2329  struct omapfb_display_data *d;
2330  int r;
2331 
2332  r = dssdrv->enable(dssdev);
2333  if (r) {
2334  dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
2335  dssdev->name);
2336  return r;
2337  }
2338 
2339  d = get_display_data(fbdev, dssdev);
2340 
2341  d->fbdev = fbdev;
2342 
2343  if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
2344  u16 w, h;
2345 
2346  if (auto_update) {
2347  omapfb_start_auto_update(fbdev, dssdev);
2349  } else {
2351  }
2352 
2353  if (dssdrv->enable_te) {
2354  r = dssdrv->enable_te(dssdev, 1);
2355  if (r) {
2356  dev_err(fbdev->dev, "Failed to set TE\n");
2357  return r;
2358  }
2359  }
2360 
2361  dssdrv->get_resolution(dssdev, &w, &h);
2362  r = dssdrv->update(dssdev, 0, 0, w, h);
2363  if (r) {
2364  dev_err(fbdev->dev,
2365  "Failed to update display\n");
2366  return r;
2367  }
2368  } else {
2370  }
2371 
2372  return 0;
2373 }
2374 
2375 static int __init omapfb_probe(struct platform_device *pdev)
2376 {
2377  struct omapfb2_device *fbdev = NULL;
2378  int r = 0;
2379  int i;
2380  struct omap_overlay *ovl;
2381  struct omap_dss_device *def_display;
2382  struct omap_dss_device *dssdev;
2383  struct omap_dss_device *ovl_device;
2384 
2385  DBG("omapfb_probe\n");
2386 
2387  if (pdev->num_resources != 0) {
2388  dev_err(&pdev->dev, "probed for an unknown device\n");
2389  r = -ENODEV;
2390  goto err0;
2391  }
2392 
2393  fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
2394  if (fbdev == NULL) {
2395  r = -ENOMEM;
2396  goto err0;
2397  }
2398 
2399  /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
2400  * available for OMAP2 and OMAP3
2401  */
2402  if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
2403  def_vrfb = 0;
2404  dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
2405  "ignoring the module parameter vrfb=y\n");
2406  }
2407 
2408 
2409  mutex_init(&fbdev->mtx);
2410 
2411  fbdev->dev = &pdev->dev;
2412  platform_set_drvdata(pdev, fbdev);
2413 
2414  r = 0;
2415  fbdev->num_displays = 0;
2416  dssdev = NULL;
2417  for_each_dss_dev(dssdev) {
2418  struct omapfb_display_data *d;
2419 
2420  omap_dss_get_device(dssdev);
2421 
2422  if (!dssdev->driver) {
2423  dev_warn(&pdev->dev, "no driver for display: %s\n",
2424  dssdev->name);
2425  omap_dss_put_device(dssdev);
2426  continue;
2427  }
2428 
2429  d = &fbdev->displays[fbdev->num_displays++];
2430  d->dssdev = dssdev;
2433  else
2435  }
2436 
2437  if (r)
2438  goto cleanup;
2439 
2440  if (fbdev->num_displays == 0) {
2441  dev_err(&pdev->dev, "no displays\n");
2442  r = -EINVAL;
2443  goto cleanup;
2444  }
2445 
2447  for (i = 0; i < fbdev->num_overlays; i++)
2448  fbdev->overlays[i] = omap_dss_get_overlay(i);
2449 
2451  for (i = 0; i < fbdev->num_managers; i++)
2452  fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2453 
2454  /* gfx overlay should be the default one. find a display
2455  * connected to that, and use it as default display */
2456  ovl = omap_dss_get_overlay(0);
2457  ovl_device = ovl->get_device(ovl);
2458  if (ovl_device) {
2459  def_display = ovl_device;
2460  } else {
2461  dev_warn(&pdev->dev, "cannot find default display\n");
2462  def_display = NULL;
2463  }
2464 
2465  if (def_mode && strlen(def_mode) > 0) {
2466  if (omapfb_parse_def_modes(fbdev))
2467  dev_warn(&pdev->dev, "cannot parse default modes\n");
2468  } else if (def_display && def_display->driver->set_timings &&
2469  def_display->driver->check_timings) {
2470  struct omap_video_timings t;
2471 
2472  r = omapfb_find_best_mode(def_display, &t);
2473 
2474  if (r == 0)
2475  def_display->driver->set_timings(def_display, &t);
2476  }
2477 
2478  r = omapfb_create_framebuffers(fbdev);
2479  if (r)
2480  goto cleanup;
2481 
2482  for (i = 0; i < fbdev->num_managers; i++) {
2483  struct omap_overlay_manager *mgr;
2484  mgr = fbdev->managers[i];
2485  r = mgr->apply(mgr);
2486  if (r)
2487  dev_warn(fbdev->dev, "failed to apply dispc config\n");
2488  }
2489 
2490  DBG("mgr->apply'ed\n");
2491 
2492  if (def_display) {
2493  r = omapfb_init_display(fbdev, def_display);
2494  if (r) {
2495  dev_err(fbdev->dev,
2496  "failed to initialize default "
2497  "display\n");
2498  goto cleanup;
2499  }
2500  }
2501 
2502  DBG("create sysfs for fbs\n");
2503  r = omapfb_create_sysfs(fbdev);
2504  if (r) {
2505  dev_err(fbdev->dev, "failed to create sysfs entries\n");
2506  goto cleanup;
2507  }
2508 
2509  return 0;
2510 
2511 cleanup:
2512  omapfb_free_resources(fbdev);
2513 err0:
2514  dev_err(&pdev->dev, "failed to setup omapfb\n");
2515  return r;
2516 }
2517 
2518 static int __exit omapfb_remove(struct platform_device *pdev)
2519 {
2520  struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
2521 
2522  /* FIXME: wait till completion of pending events */
2523 
2524  omapfb_remove_sysfs(fbdev);
2525 
2526  omapfb_free_resources(fbdev);
2527 
2528  return 0;
2529 }
2530 
2531 static struct platform_driver omapfb_driver = {
2532  .remove = __exit_p(omapfb_remove),
2533  .driver = {
2534  .name = "omapfb",
2535  .owner = THIS_MODULE,
2536  },
2537 };
2538 
2539 static int __init omapfb_init(void)
2540 {
2541  DBG("omapfb_init\n");
2542 
2543  if (platform_driver_probe(&omapfb_driver, omapfb_probe)) {
2544  printk(KERN_ERR "failed to register omapfb driver\n");
2545  return -ENODEV;
2546  }
2547 
2548  return 0;
2549 }
2550 
2551 static void __exit omapfb_exit(void)
2552 {
2553  DBG("omapfb_exit\n");
2554  platform_driver_unregister(&omapfb_driver);
2555 }
2556 
2557 module_param_named(mode, def_mode, charp, 0);
2558 module_param_named(vram, def_vram, charp, 0);
2559 module_param_named(rotate, def_rotate, int, 0);
2560 module_param_named(vrfb, def_vrfb, bool, 0);
2561 module_param_named(mirror, def_mirror, bool, 0);
2562 
2563 /* late_initcall to let panel/ctrl drivers loaded first.
2564  * I guess better option would be a more dynamic approach,
2565  * so that omapfb reacts to new panels when they are loaded */
2566 late_initcall(omapfb_init);
2567 /*module_init(omapfb_init);*/
2568 module_exit(omapfb_exit);
2569 
2570 MODULE_AUTHOR("Tomi Valkeinen <[email protected]>");
2571 MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
2572 MODULE_LICENSE("GPL v2");