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