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 /* Fallthrough */ 1158 r = -EINVAL; 1159 break; 1160 case OMAPFB_COLOR_RGB565: 1161 case OMAPFB_COLOR_RGB444: 1162 case OMAPFB_COLOR_RGB24P: 1163 case OMAPFB_COLOR_RGB24U: 1164 if (r != 0) 1165 break; 1166 1167 if (regno < 16) { 1168 u32 pal; 1169 pal = ((red >> (16 - var->red.length)) << 1170 var->red.offset) | 1171 ((green >> (16 - var->green.length)) << 1172 var->green.offset) | 1173 (blue >> (16 - var->blue.length)); 1174 ((u32 *)(fbi->pseudo_palette))[regno] = pal; 1175 } 1176 break; 1177 default: 1178 BUG(); 1179 } 1180 return r; 1181 } 1182 1183 static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 1184 u_int transp, struct fb_info *info) 1185 { 1186 DBG("setcolreg\n"); 1187 1188 return _setcolreg(info, regno, red, green, blue, transp, 1); 1189 } 1190 1191 static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) 1192 { 1193 int count, index, r; 1194 u16 *red, *green, *blue, *transp; 1195 u16 trans = 0xffff; 1196 1197 DBG("setcmap\n"); 1198 1199 red = cmap->red; 1200 green = cmap->green; 1201 blue = cmap->blue; 1202 transp = cmap->transp; 1203 index = cmap->start; 1204 1205 for (count = 0; count < cmap->len; count++) { 1206 if (transp) 1207 trans = *transp++; 1208 r = _setcolreg(info, index++, *red++, *green++, *blue++, trans, 1209 count == cmap->len - 1); 1210 if (r != 0) 1211 return r; 1212 } 1213 1214 return 0; 1215 } 1216 1217 static int omapfb_blank(int blank, struct fb_info *fbi) 1218 { 1219 struct omapfb_info *ofbi = FB2OFB(fbi); 1220 struct omapfb2_device *fbdev = ofbi->fbdev; 1221 struct omap_dss_device *display = fb2display(fbi); 1222 struct omapfb_display_data *d; 1223 int r = 0; 1224 1225 if (!display) 1226 return -EINVAL; 1227 1228 omapfb_lock(fbdev); 1229 1230 d = get_display_data(fbdev, display); 1231 1232 switch (blank) { 1233 case FB_BLANK_UNBLANK: 1234 if (display->state == OMAP_DSS_DISPLAY_ACTIVE) 1235 goto exit; 1236 1237 r = display->driver->enable(display); 1238 1239 if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) && 1240 d->update_mode == OMAPFB_AUTO_UPDATE && 1241 !d->auto_update_work_enabled) 1242 omapfb_start_auto_update(fbdev, display); 1243 1244 break; 1245 1246 case FB_BLANK_NORMAL: 1247 /* FB_BLANK_NORMAL could be implemented. 1248 * Needs DSS additions. */ 1249 case FB_BLANK_VSYNC_SUSPEND: 1250 case FB_BLANK_HSYNC_SUSPEND: 1251 case FB_BLANK_POWERDOWN: 1252 if (display->state != OMAP_DSS_DISPLAY_ACTIVE) 1253 goto exit; 1254 1255 if (d->auto_update_work_enabled) 1256 omapfb_stop_auto_update(fbdev, display); 1257 1258 display->driver->disable(display); 1259 1260 break; 1261 1262 default: 1263 r = -EINVAL; 1264 } 1265 1266 exit: 1267 omapfb_unlock(fbdev); 1268 1269 return r; 1270 } 1271 1272 #if 0 1273 /* XXX fb_read and fb_write are needed for VRFB */ 1274 ssize_t omapfb_write(struct fb_info *info, const char __user *buf, 1275 size_t count, loff_t *ppos) 1276 { 1277 DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos); 1278 /* XXX needed for VRFB */ 1279 return count; 1280 } 1281 #endif 1282 1283 static const struct fb_ops omapfb_ops = { 1284 .owner = THIS_MODULE, 1285 .fb_open = omapfb_open, 1286 .fb_release = omapfb_release, 1287 .fb_fillrect = cfb_fillrect, 1288 .fb_copyarea = cfb_copyarea, 1289 .fb_imageblit = cfb_imageblit, 1290 .fb_blank = omapfb_blank, 1291 .fb_ioctl = omapfb_ioctl, 1292 .fb_check_var = omapfb_check_var, 1293 .fb_set_par = omapfb_set_par, 1294 .fb_pan_display = omapfb_pan_display, 1295 .fb_mmap = omapfb_mmap, 1296 .fb_setcolreg = omapfb_setcolreg, 1297 .fb_setcmap = omapfb_setcmap, 1298 /*.fb_write = omapfb_write,*/ 1299 }; 1300 1301 static void omapfb_free_fbmem(struct fb_info *fbi) 1302 { 1303 struct omapfb_info *ofbi = FB2OFB(fbi); 1304 struct omapfb2_device *fbdev = ofbi->fbdev; 1305 struct omapfb2_mem_region *rg; 1306 1307 rg = ofbi->region; 1308 1309 if (rg->token == NULL) 1310 return; 1311 1312 WARN_ON(atomic_read(&rg->map_count)); 1313 1314 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 1315 /* unmap the 0 angle rotation */ 1316 if (rg->vrfb.vaddr[0]) { 1317 iounmap(rg->vrfb.vaddr[0]); 1318 rg->vrfb.vaddr[0] = NULL; 1319 } 1320 1321 omap_vrfb_release_ctx(&rg->vrfb); 1322 } 1323 1324 dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle, 1325 rg->attrs); 1326 1327 rg->token = NULL; 1328 rg->vaddr = NULL; 1329 rg->paddr = 0; 1330 rg->alloc = 0; 1331 rg->size = 0; 1332 } 1333 1334 static void clear_fb_info(struct fb_info *fbi) 1335 { 1336 memset(&fbi->var, 0, sizeof(fbi->var)); 1337 memset(&fbi->fix, 0, sizeof(fbi->fix)); 1338 strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id)); 1339 } 1340 1341 static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev) 1342 { 1343 int i; 1344 1345 DBG("free all fbmem\n"); 1346 1347 for (i = 0; i < fbdev->num_fbs; i++) { 1348 struct fb_info *fbi = fbdev->fbs[i]; 1349 omapfb_free_fbmem(fbi); 1350 clear_fb_info(fbi); 1351 } 1352 1353 return 0; 1354 } 1355 1356 static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, 1357 unsigned long paddr) 1358 { 1359 struct omapfb_info *ofbi = FB2OFB(fbi); 1360 struct omapfb2_device *fbdev = ofbi->fbdev; 1361 struct omapfb2_mem_region *rg; 1362 void *token; 1363 unsigned long attrs; 1364 dma_addr_t dma_handle; 1365 int r; 1366 1367 rg = ofbi->region; 1368 1369 rg->paddr = 0; 1370 rg->vaddr = NULL; 1371 memset(&rg->vrfb, 0, sizeof rg->vrfb); 1372 rg->size = 0; 1373 rg->type = 0; 1374 rg->alloc = false; 1375 rg->map = false; 1376 1377 size = PAGE_ALIGN(size); 1378 1379 attrs = DMA_ATTR_WRITE_COMBINE; 1380 1381 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 1382 attrs |= DMA_ATTR_NO_KERNEL_MAPPING; 1383 1384 DBG("allocating %lu bytes for fb %d\n", size, ofbi->id); 1385 1386 token = dma_alloc_attrs(fbdev->dev, size, &dma_handle, 1387 GFP_KERNEL, attrs); 1388 1389 if (token == NULL) { 1390 dev_err(fbdev->dev, "failed to allocate framebuffer\n"); 1391 return -ENOMEM; 1392 } 1393 1394 DBG("allocated VRAM paddr %lx, vaddr %p\n", 1395 (unsigned long)dma_handle, token); 1396 1397 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 1398 r = omap_vrfb_request_ctx(&rg->vrfb); 1399 if (r) { 1400 dma_free_attrs(fbdev->dev, size, token, dma_handle, 1401 attrs); 1402 dev_err(fbdev->dev, "vrfb create ctx failed\n"); 1403 return r; 1404 } 1405 } 1406 1407 rg->attrs = attrs; 1408 rg->token = token; 1409 rg->dma_handle = dma_handle; 1410 1411 rg->paddr = (unsigned long)dma_handle; 1412 rg->vaddr = (void __iomem *)token; 1413 rg->size = size; 1414 rg->alloc = 1; 1415 1416 return 0; 1417 } 1418 1419 /* allocate fbmem using display resolution as reference */ 1420 static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size, 1421 unsigned long paddr) 1422 { 1423 struct omapfb_info *ofbi = FB2OFB(fbi); 1424 struct omapfb2_device *fbdev = ofbi->fbdev; 1425 struct omap_dss_device *display; 1426 int bytespp; 1427 1428 display = fb2display(fbi); 1429 1430 if (!display) 1431 return 0; 1432 1433 switch (omapfb_get_recommended_bpp(fbdev, display)) { 1434 case 16: 1435 bytespp = 2; 1436 break; 1437 case 24: 1438 bytespp = 4; 1439 break; 1440 default: 1441 bytespp = 4; 1442 break; 1443 } 1444 1445 if (!size) { 1446 u16 w, h; 1447 1448 display->driver->get_resolution(display, &w, &h); 1449 1450 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 1451 size = max(omap_vrfb_min_phys_size(w, h, bytespp), 1452 omap_vrfb_min_phys_size(h, w, bytespp)); 1453 1454 DBG("adjusting fb mem size for VRFB, %u -> %lu\n", 1455 w * h * bytespp, size); 1456 } else { 1457 size = w * h * bytespp; 1458 } 1459 } 1460 1461 if (!size) 1462 return 0; 1463 1464 return omapfb_alloc_fbmem(fbi, size, paddr); 1465 } 1466 1467 static int omapfb_parse_vram_param(const char *param, int max_entries, 1468 unsigned long *sizes, unsigned long *paddrs) 1469 { 1470 unsigned int fbnum; 1471 unsigned long size; 1472 unsigned long paddr = 0; 1473 char *p, *start; 1474 1475 start = (char *)param; 1476 1477 while (1) { 1478 p = start; 1479 1480 fbnum = simple_strtoul(p, &p, 10); 1481 1482 if (p == start) 1483 return -EINVAL; 1484 1485 if (*p != ':') 1486 return -EINVAL; 1487 1488 if (fbnum >= max_entries) 1489 return -EINVAL; 1490 1491 size = memparse(p + 1, &p); 1492 1493 if (!size) 1494 return -EINVAL; 1495 1496 paddr = 0; 1497 1498 if (*p == '@') { 1499 paddr = simple_strtoul(p + 1, &p, 16); 1500 1501 if (!paddr) 1502 return -EINVAL; 1503 1504 } 1505 1506 WARN_ONCE(paddr, 1507 "reserving memory at predefined address not supported\n"); 1508 1509 paddrs[fbnum] = paddr; 1510 sizes[fbnum] = size; 1511 1512 if (*p == 0) 1513 break; 1514 1515 if (*p != ',') 1516 return -EINVAL; 1517 1518 ++p; 1519 1520 start = p; 1521 } 1522 1523 return 0; 1524 } 1525 1526 static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev) 1527 { 1528 int i, r; 1529 unsigned long vram_sizes[10]; 1530 unsigned long vram_paddrs[10]; 1531 1532 memset(&vram_sizes, 0, sizeof(vram_sizes)); 1533 memset(&vram_paddrs, 0, sizeof(vram_paddrs)); 1534 1535 if (def_vram && omapfb_parse_vram_param(def_vram, 10, 1536 vram_sizes, vram_paddrs)) { 1537 dev_err(fbdev->dev, "failed to parse vram parameter\n"); 1538 1539 memset(&vram_sizes, 0, sizeof(vram_sizes)); 1540 memset(&vram_paddrs, 0, sizeof(vram_paddrs)); 1541 } 1542 1543 for (i = 0; i < fbdev->num_fbs; i++) { 1544 /* allocate memory automatically only for fb0, or if 1545 * excplicitly defined with vram or plat data option */ 1546 if (i == 0 || vram_sizes[i] != 0) { 1547 r = omapfb_alloc_fbmem_display(fbdev->fbs[i], 1548 vram_sizes[i], vram_paddrs[i]); 1549 1550 if (r) 1551 return r; 1552 } 1553 } 1554 1555 for (i = 0; i < fbdev->num_fbs; i++) { 1556 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); 1557 struct omapfb2_mem_region *rg; 1558 rg = ofbi->region; 1559 1560 DBG("region%d phys %08x virt %p size=%lu\n", 1561 i, 1562 rg->paddr, 1563 rg->vaddr, 1564 rg->size); 1565 } 1566 1567 return 0; 1568 } 1569 1570 static void omapfb_clear_fb(struct fb_info *fbi) 1571 { 1572 const struct fb_fillrect rect = { 1573 .dx = 0, 1574 .dy = 0, 1575 .width = fbi->var.xres_virtual, 1576 .height = fbi->var.yres_virtual, 1577 .color = 0, 1578 .rop = ROP_COPY, 1579 }; 1580 1581 cfb_fillrect(fbi, &rect); 1582 } 1583 1584 int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) 1585 { 1586 struct omapfb_info *ofbi = FB2OFB(fbi); 1587 struct omapfb2_device *fbdev = ofbi->fbdev; 1588 struct omapfb2_mem_region *rg = ofbi->region; 1589 unsigned long old_size = rg->size; 1590 unsigned long old_paddr = rg->paddr; 1591 int old_type = rg->type; 1592 int r; 1593 1594 if (type != OMAPFB_MEMTYPE_SDRAM) 1595 return -EINVAL; 1596 1597 size = PAGE_ALIGN(size); 1598 1599 if (old_size == size && old_type == type) 1600 return 0; 1601 1602 omapfb_free_fbmem(fbi); 1603 1604 if (size == 0) { 1605 clear_fb_info(fbi); 1606 return 0; 1607 } 1608 1609 r = omapfb_alloc_fbmem(fbi, size, 0); 1610 1611 if (r) { 1612 if (old_size) 1613 omapfb_alloc_fbmem(fbi, old_size, old_paddr); 1614 1615 if (rg->size == 0) 1616 clear_fb_info(fbi); 1617 1618 return r; 1619 } 1620 1621 if (old_size == size) 1622 return 0; 1623 1624 if (old_size == 0) { 1625 DBG("initializing fb %d\n", ofbi->id); 1626 r = omapfb_fb_init(fbdev, fbi); 1627 if (r) { 1628 DBG("omapfb_fb_init failed\n"); 1629 goto err; 1630 } 1631 r = omapfb_apply_changes(fbi, 1); 1632 if (r) { 1633 DBG("omapfb_apply_changes failed\n"); 1634 goto err; 1635 } 1636 } else { 1637 struct fb_var_screeninfo new_var; 1638 memcpy(&new_var, &fbi->var, sizeof(new_var)); 1639 r = check_fb_var(fbi, &new_var); 1640 if (r) 1641 goto err; 1642 memcpy(&fbi->var, &new_var, sizeof(fbi->var)); 1643 set_fb_fix(fbi); 1644 r = setup_vrfb_rotation(fbi); 1645 if (r) 1646 goto err; 1647 } 1648 1649 omapfb_clear_fb(fbi); 1650 1651 return 0; 1652 err: 1653 omapfb_free_fbmem(fbi); 1654 clear_fb_info(fbi); 1655 return r; 1656 } 1657 1658 static void omapfb_auto_update_work(struct work_struct *work) 1659 { 1660 struct omap_dss_device *dssdev; 1661 struct omap_dss_driver *dssdrv; 1662 struct omapfb_display_data *d; 1663 u16 w, h; 1664 unsigned int freq; 1665 struct omapfb2_device *fbdev; 1666 1667 d = container_of(work, struct omapfb_display_data, 1668 auto_update_work.work); 1669 1670 dssdev = d->dssdev; 1671 dssdrv = dssdev->driver; 1672 fbdev = d->fbdev; 1673 1674 if (!dssdrv || !dssdrv->update) 1675 return; 1676 1677 if (dssdrv->sync) 1678 dssdrv->sync(dssdev); 1679 1680 dssdrv->get_resolution(dssdev, &w, &h); 1681 dssdrv->update(dssdev, 0, 0, w, h); 1682 1683 freq = auto_update_freq; 1684 if (freq == 0) 1685 freq = 20; 1686 queue_delayed_work(fbdev->auto_update_wq, 1687 &d->auto_update_work, HZ / freq); 1688 } 1689 1690 void omapfb_start_auto_update(struct omapfb2_device *fbdev, 1691 struct omap_dss_device *display) 1692 { 1693 struct omapfb_display_data *d; 1694 1695 if (fbdev->auto_update_wq == NULL) { 1696 struct workqueue_struct *wq; 1697 1698 wq = create_singlethread_workqueue("omapfb_auto_update"); 1699 1700 if (wq == NULL) { 1701 dev_err(fbdev->dev, "Failed to create workqueue for " 1702 "auto-update\n"); 1703 return; 1704 } 1705 1706 fbdev->auto_update_wq = wq; 1707 } 1708 1709 d = get_display_data(fbdev, display); 1710 1711 INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work); 1712 1713 d->auto_update_work_enabled = true; 1714 1715 omapfb_auto_update_work(&d->auto_update_work.work); 1716 } 1717 1718 void omapfb_stop_auto_update(struct omapfb2_device *fbdev, 1719 struct omap_dss_device *display) 1720 { 1721 struct omapfb_display_data *d; 1722 1723 d = get_display_data(fbdev, display); 1724 1725 cancel_delayed_work_sync(&d->auto_update_work); 1726 1727 d->auto_update_work_enabled = false; 1728 } 1729 1730 /* initialize fb_info, var, fix to something sane based on the display */ 1731 static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi) 1732 { 1733 struct fb_var_screeninfo *var = &fbi->var; 1734 struct omap_dss_device *display = fb2display(fbi); 1735 struct omapfb_info *ofbi = FB2OFB(fbi); 1736 int r = 0; 1737 1738 fbi->fbops = &omapfb_ops; 1739 fbi->flags = FBINFO_FLAG_DEFAULT; 1740 fbi->pseudo_palette = fbdev->pseudo_palette; 1741 1742 if (ofbi->region->size == 0) { 1743 clear_fb_info(fbi); 1744 return 0; 1745 } 1746 1747 var->nonstd = 0; 1748 var->bits_per_pixel = 0; 1749 1750 var->rotate = def_rotate; 1751 1752 if (display) { 1753 u16 w, h; 1754 int rotation = (var->rotate + ofbi->rotation[0]) % 4; 1755 1756 display->driver->get_resolution(display, &w, &h); 1757 1758 if (rotation == FB_ROTATE_CW || 1759 rotation == FB_ROTATE_CCW) { 1760 var->xres = h; 1761 var->yres = w; 1762 } else { 1763 var->xres = w; 1764 var->yres = h; 1765 } 1766 1767 var->xres_virtual = var->xres; 1768 var->yres_virtual = var->yres; 1769 1770 if (!var->bits_per_pixel) { 1771 switch (omapfb_get_recommended_bpp(fbdev, display)) { 1772 case 16: 1773 var->bits_per_pixel = 16; 1774 break; 1775 case 24: 1776 var->bits_per_pixel = 32; 1777 break; 1778 default: 1779 dev_err(fbdev->dev, "illegal display " 1780 "bpp\n"); 1781 return -EINVAL; 1782 } 1783 } 1784 } else { 1785 /* if there's no display, let's just guess some basic values */ 1786 var->xres = 320; 1787 var->yres = 240; 1788 var->xres_virtual = var->xres; 1789 var->yres_virtual = var->yres; 1790 if (!var->bits_per_pixel) 1791 var->bits_per_pixel = 16; 1792 } 1793 1794 r = check_fb_var(fbi, var); 1795 if (r) 1796 goto err; 1797 1798 set_fb_fix(fbi); 1799 r = setup_vrfb_rotation(fbi); 1800 if (r) 1801 goto err; 1802 1803 r = fb_alloc_cmap(&fbi->cmap, 256, 0); 1804 if (r) 1805 dev_err(fbdev->dev, "unable to allocate color map memory\n"); 1806 1807 err: 1808 return r; 1809 } 1810 1811 static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi) 1812 { 1813 fb_dealloc_cmap(&fbi->cmap); 1814 } 1815 1816 1817 static void omapfb_free_resources(struct omapfb2_device *fbdev) 1818 { 1819 int i; 1820 1821 DBG("free_resources\n"); 1822 1823 if (fbdev == NULL) 1824 return; 1825 1826 for (i = 0; i < fbdev->num_overlays; i++) { 1827 struct omap_overlay *ovl = fbdev->overlays[i]; 1828 1829 ovl->disable(ovl); 1830 1831 if (ovl->manager) 1832 ovl->unset_manager(ovl); 1833 } 1834 1835 for (i = 0; i < fbdev->num_fbs; i++) 1836 unregister_framebuffer(fbdev->fbs[i]); 1837 1838 /* free the reserved fbmem */ 1839 omapfb_free_all_fbmem(fbdev); 1840 1841 for (i = 0; i < fbdev->num_fbs; i++) { 1842 fbinfo_cleanup(fbdev, fbdev->fbs[i]); 1843 framebuffer_release(fbdev->fbs[i]); 1844 } 1845 1846 for (i = 0; i < fbdev->num_displays; i++) { 1847 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; 1848 1849 if (fbdev->displays[i].auto_update_work_enabled) 1850 omapfb_stop_auto_update(fbdev, dssdev); 1851 1852 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) 1853 dssdev->driver->disable(dssdev); 1854 1855 dssdev->driver->disconnect(dssdev); 1856 1857 omap_dss_put_device(dssdev); 1858 } 1859 1860 if (fbdev->auto_update_wq != NULL) { 1861 flush_workqueue(fbdev->auto_update_wq); 1862 destroy_workqueue(fbdev->auto_update_wq); 1863 fbdev->auto_update_wq = NULL; 1864 } 1865 1866 dev_set_drvdata(fbdev->dev, NULL); 1867 } 1868 1869 static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) 1870 { 1871 int r, i; 1872 1873 fbdev->num_fbs = 0; 1874 1875 DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS); 1876 1877 /* allocate fb_infos */ 1878 for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) { 1879 struct fb_info *fbi; 1880 struct omapfb_info *ofbi; 1881 1882 fbi = framebuffer_alloc(sizeof(struct omapfb_info), 1883 fbdev->dev); 1884 if (!fbi) 1885 return -ENOMEM; 1886 1887 clear_fb_info(fbi); 1888 1889 fbdev->fbs[i] = fbi; 1890 1891 ofbi = FB2OFB(fbi); 1892 ofbi->fbdev = fbdev; 1893 ofbi->id = i; 1894 1895 ofbi->region = &fbdev->regions[i]; 1896 ofbi->region->id = i; 1897 init_rwsem(&ofbi->region->lock); 1898 1899 /* assign these early, so that fb alloc can use them */ 1900 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : 1901 OMAP_DSS_ROT_DMA; 1902 ofbi->mirror = def_mirror; 1903 1904 fbdev->num_fbs++; 1905 } 1906 1907 DBG("fb_infos allocated\n"); 1908 1909 /* assign overlays for the fbs */ 1910 for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) { 1911 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); 1912 1913 ofbi->overlays[0] = fbdev->overlays[i]; 1914 ofbi->num_overlays = 1; 1915 } 1916 1917 /* allocate fb memories */ 1918 r = omapfb_allocate_all_fbs(fbdev); 1919 if (r) { 1920 dev_err(fbdev->dev, "failed to allocate fbmem\n"); 1921 return r; 1922 } 1923 1924 DBG("fbmems allocated\n"); 1925 1926 /* setup fb_infos */ 1927 for (i = 0; i < fbdev->num_fbs; i++) { 1928 struct fb_info *fbi = fbdev->fbs[i]; 1929 struct omapfb_info *ofbi = FB2OFB(fbi); 1930 1931 omapfb_get_mem_region(ofbi->region); 1932 r = omapfb_fb_init(fbdev, fbi); 1933 omapfb_put_mem_region(ofbi->region); 1934 1935 if (r) { 1936 dev_err(fbdev->dev, "failed to setup fb_info\n"); 1937 return r; 1938 } 1939 } 1940 1941 for (i = 0; i < fbdev->num_fbs; i++) { 1942 struct fb_info *fbi = fbdev->fbs[i]; 1943 struct omapfb_info *ofbi = FB2OFB(fbi); 1944 1945 if (ofbi->region->size == 0) 1946 continue; 1947 1948 omapfb_clear_fb(fbi); 1949 } 1950 1951 DBG("fb_infos initialized\n"); 1952 1953 for (i = 0; i < fbdev->num_fbs; i++) { 1954 r = register_framebuffer(fbdev->fbs[i]); 1955 if (r != 0) { 1956 dev_err(fbdev->dev, 1957 "registering framebuffer %d failed\n", i); 1958 return r; 1959 } 1960 } 1961 1962 DBG("framebuffers registered\n"); 1963 1964 for (i = 0; i < fbdev->num_fbs; i++) { 1965 struct fb_info *fbi = fbdev->fbs[i]; 1966 struct omapfb_info *ofbi = FB2OFB(fbi); 1967 1968 omapfb_get_mem_region(ofbi->region); 1969 r = omapfb_apply_changes(fbi, 1); 1970 omapfb_put_mem_region(ofbi->region); 1971 1972 if (r) { 1973 dev_err(fbdev->dev, "failed to change mode\n"); 1974 return r; 1975 } 1976 } 1977 1978 /* Enable fb0 */ 1979 if (fbdev->num_fbs > 0) { 1980 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); 1981 1982 if (ofbi->num_overlays > 0) { 1983 struct omap_overlay *ovl = ofbi->overlays[0]; 1984 1985 ovl->manager->apply(ovl->manager); 1986 1987 r = omapfb_overlay_enable(ovl, 1); 1988 1989 if (r) { 1990 dev_err(fbdev->dev, 1991 "failed to enable overlay\n"); 1992 return r; 1993 } 1994 } 1995 } 1996 1997 DBG("create_framebuffers done\n"); 1998 1999 return 0; 2000 } 2001 2002 static int omapfb_mode_to_timings(const char *mode_str, 2003 struct omap_dss_device *display, 2004 struct omap_video_timings *timings, u8 *bpp) 2005 { 2006 struct fb_info *fbi; 2007 struct fb_var_screeninfo *var; 2008 struct fb_ops *fbops; 2009 int r; 2010 2011 #ifdef CONFIG_OMAP2_DSS_VENC 2012 if (strcmp(mode_str, "pal") == 0) { 2013 *timings = omap_dss_pal_timings; 2014 *bpp = 24; 2015 return 0; 2016 } else if (strcmp(mode_str, "ntsc") == 0) { 2017 *timings = omap_dss_ntsc_timings; 2018 *bpp = 24; 2019 return 0; 2020 } 2021 #endif 2022 2023 /* this is quite a hack, but I wanted to use the modedb and for 2024 * that we need fb_info and var, so we create dummy ones */ 2025 2026 *bpp = 0; 2027 fbi = NULL; 2028 var = NULL; 2029 fbops = NULL; 2030 2031 fbi = kzalloc(sizeof(*fbi), GFP_KERNEL); 2032 if (fbi == NULL) { 2033 r = -ENOMEM; 2034 goto err; 2035 } 2036 2037 var = kzalloc(sizeof(*var), GFP_KERNEL); 2038 if (var == NULL) { 2039 r = -ENOMEM; 2040 goto err; 2041 } 2042 2043 fbops = kzalloc(sizeof(*fbops), GFP_KERNEL); 2044 if (fbops == NULL) { 2045 r = -ENOMEM; 2046 goto err; 2047 } 2048 2049 fbi->fbops = fbops; 2050 2051 r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24); 2052 if (r == 0) { 2053 r = -EINVAL; 2054 goto err; 2055 } 2056 2057 if (display->driver->get_timings) { 2058 display->driver->get_timings(display, timings); 2059 } else { 2060 timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 2061 timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; 2062 timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; 2063 } 2064 2065 timings->pixelclock = PICOS2KHZ(var->pixclock) * 1000; 2066 timings->hbp = var->left_margin; 2067 timings->hfp = var->right_margin; 2068 timings->vbp = var->upper_margin; 2069 timings->vfp = var->lower_margin; 2070 timings->hsw = var->hsync_len; 2071 timings->vsw = var->vsync_len; 2072 timings->x_res = var->xres; 2073 timings->y_res = var->yres; 2074 timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ? 2075 OMAPDSS_SIG_ACTIVE_HIGH : 2076 OMAPDSS_SIG_ACTIVE_LOW; 2077 timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ? 2078 OMAPDSS_SIG_ACTIVE_HIGH : 2079 OMAPDSS_SIG_ACTIVE_LOW; 2080 timings->interlace = var->vmode & FB_VMODE_INTERLACED; 2081 2082 switch (var->bits_per_pixel) { 2083 case 16: 2084 *bpp = 16; 2085 break; 2086 case 24: 2087 case 32: 2088 default: 2089 *bpp = 24; 2090 break; 2091 } 2092 2093 r = 0; 2094 2095 err: 2096 kfree(fbi); 2097 kfree(var); 2098 kfree(fbops); 2099 2100 return r; 2101 } 2102 2103 static int omapfb_set_def_mode(struct omapfb2_device *fbdev, 2104 struct omap_dss_device *display, char *mode_str) 2105 { 2106 int r; 2107 u8 bpp; 2108 struct omap_video_timings timings, temp_timings; 2109 struct omapfb_display_data *d; 2110 2111 r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp); 2112 if (r) 2113 return r; 2114 2115 d = get_display_data(fbdev, display); 2116 d->bpp_override = bpp; 2117 2118 if (display->driver->check_timings) { 2119 r = display->driver->check_timings(display, &timings); 2120 if (r) 2121 return r; 2122 } else { 2123 /* If check_timings is not present compare xres and yres */ 2124 if (display->driver->get_timings) { 2125 display->driver->get_timings(display, &temp_timings); 2126 2127 if (temp_timings.x_res != timings.x_res || 2128 temp_timings.y_res != timings.y_res) 2129 return -EINVAL; 2130 } 2131 } 2132 2133 if (display->driver->set_timings) 2134 display->driver->set_timings(display, &timings); 2135 2136 return 0; 2137 } 2138 2139 static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev, 2140 struct omap_dss_device *dssdev) 2141 { 2142 struct omapfb_display_data *d; 2143 2144 BUG_ON(dssdev->driver->get_recommended_bpp == NULL); 2145 2146 d = get_display_data(fbdev, dssdev); 2147 2148 if (d->bpp_override != 0) 2149 return d->bpp_override; 2150 2151 return dssdev->driver->get_recommended_bpp(dssdev); 2152 } 2153 2154 static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) 2155 { 2156 char *str, *options, *this_opt; 2157 int r = 0; 2158 2159 str = kstrdup(def_mode, GFP_KERNEL); 2160 if (!str) 2161 return -ENOMEM; 2162 options = str; 2163 2164 while (!r && (this_opt = strsep(&options, ",")) != NULL) { 2165 char *p, *display_str, *mode_str; 2166 struct omap_dss_device *display; 2167 int i; 2168 2169 p = strchr(this_opt, ':'); 2170 if (!p) { 2171 r = -EINVAL; 2172 break; 2173 } 2174 2175 *p = 0; 2176 display_str = this_opt; 2177 mode_str = p + 1; 2178 2179 display = NULL; 2180 for (i = 0; i < fbdev->num_displays; ++i) { 2181 if (strcmp(fbdev->displays[i].dssdev->name, 2182 display_str) == 0) { 2183 display = fbdev->displays[i].dssdev; 2184 break; 2185 } 2186 } 2187 2188 if (!display) { 2189 r = -EINVAL; 2190 break; 2191 } 2192 2193 r = omapfb_set_def_mode(fbdev, display, mode_str); 2194 if (r) 2195 break; 2196 } 2197 2198 kfree(str); 2199 2200 return r; 2201 } 2202 2203 static void fb_videomode_to_omap_timings(struct fb_videomode *m, 2204 struct omap_dss_device *display, 2205 struct omap_video_timings *t) 2206 { 2207 if (display->driver->get_timings) { 2208 display->driver->get_timings(display, t); 2209 } else { 2210 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 2211 t->de_level = OMAPDSS_SIG_ACTIVE_HIGH; 2212 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; 2213 } 2214 2215 t->x_res = m->xres; 2216 t->y_res = m->yres; 2217 t->pixelclock = PICOS2KHZ(m->pixclock) * 1000; 2218 t->hsw = m->hsync_len; 2219 t->hfp = m->right_margin; 2220 t->hbp = m->left_margin; 2221 t->vsw = m->vsync_len; 2222 t->vfp = m->lower_margin; 2223 t->vbp = m->upper_margin; 2224 t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ? 2225 OMAPDSS_SIG_ACTIVE_HIGH : 2226 OMAPDSS_SIG_ACTIVE_LOW; 2227 t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ? 2228 OMAPDSS_SIG_ACTIVE_HIGH : 2229 OMAPDSS_SIG_ACTIVE_LOW; 2230 t->interlace = m->vmode & FB_VMODE_INTERLACED; 2231 } 2232 2233 static int omapfb_find_best_mode(struct omap_dss_device *display, 2234 struct omap_video_timings *timings) 2235 { 2236 struct fb_monspecs *specs; 2237 u8 *edid; 2238 int r, i, best_idx, len; 2239 2240 if (!display->driver->read_edid) 2241 return -ENODEV; 2242 2243 len = 0x80 * 2; 2244 edid = kmalloc(len, GFP_KERNEL); 2245 if (edid == NULL) 2246 return -ENOMEM; 2247 2248 r = display->driver->read_edid(display, edid, len); 2249 if (r < 0) 2250 goto err1; 2251 2252 specs = kzalloc(sizeof(*specs), GFP_KERNEL); 2253 if (specs == NULL) { 2254 r = -ENOMEM; 2255 goto err1; 2256 } 2257 2258 fb_edid_to_monspecs(edid, specs); 2259 2260 best_idx = -1; 2261 2262 for (i = 0; i < specs->modedb_len; ++i) { 2263 struct fb_videomode *m; 2264 struct omap_video_timings t; 2265 2266 m = &specs->modedb[i]; 2267 2268 if (m->pixclock == 0) 2269 continue; 2270 2271 /* skip repeated pixel modes */ 2272 if (m->xres == 2880 || m->xres == 1440) 2273 continue; 2274 2275 if (m->vmode & FB_VMODE_INTERLACED || 2276 m->vmode & FB_VMODE_DOUBLE) 2277 continue; 2278 2279 fb_videomode_to_omap_timings(m, display, &t); 2280 2281 r = display->driver->check_timings(display, &t); 2282 if (r == 0) { 2283 best_idx = i; 2284 break; 2285 } 2286 } 2287 2288 if (best_idx == -1) { 2289 r = -ENOENT; 2290 goto err2; 2291 } 2292 2293 fb_videomode_to_omap_timings(&specs->modedb[best_idx], display, 2294 timings); 2295 2296 r = 0; 2297 2298 err2: 2299 fb_destroy_modedb(specs->modedb); 2300 kfree(specs); 2301 err1: 2302 kfree(edid); 2303 2304 return r; 2305 } 2306 2307 static int omapfb_init_display(struct omapfb2_device *fbdev, 2308 struct omap_dss_device *dssdev) 2309 { 2310 struct omap_dss_driver *dssdrv = dssdev->driver; 2311 struct omapfb_display_data *d; 2312 int r; 2313 2314 r = dssdrv->enable(dssdev); 2315 if (r) { 2316 dev_warn(fbdev->dev, "Failed to enable display '%s'\n", 2317 dssdev->name); 2318 return r; 2319 } 2320 2321 d = get_display_data(fbdev, dssdev); 2322 2323 d->fbdev = fbdev; 2324 2325 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { 2326 u16 w, h; 2327 2328 if (auto_update) { 2329 omapfb_start_auto_update(fbdev, dssdev); 2330 d->update_mode = OMAPFB_AUTO_UPDATE; 2331 } else { 2332 d->update_mode = OMAPFB_MANUAL_UPDATE; 2333 } 2334 2335 if (dssdrv->enable_te) { 2336 r = dssdrv->enable_te(dssdev, 1); 2337 if (r) { 2338 dev_err(fbdev->dev, "Failed to set TE\n"); 2339 return r; 2340 } 2341 } 2342 2343 dssdrv->get_resolution(dssdev, &w, &h); 2344 r = dssdrv->update(dssdev, 0, 0, w, h); 2345 if (r) { 2346 dev_err(fbdev->dev, 2347 "Failed to update display\n"); 2348 return r; 2349 } 2350 } else { 2351 d->update_mode = OMAPFB_AUTO_UPDATE; 2352 } 2353 2354 return 0; 2355 } 2356 2357 static int omapfb_init_connections(struct omapfb2_device *fbdev, 2358 struct omap_dss_device *def_dssdev) 2359 { 2360 int i, r; 2361 struct omap_overlay_manager *mgr; 2362 2363 r = def_dssdev->driver->connect(def_dssdev); 2364 if (r) { 2365 dev_err(fbdev->dev, "failed to connect default display\n"); 2366 return r; 2367 } 2368 2369 for (i = 0; i < fbdev->num_displays; ++i) { 2370 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; 2371 2372 if (dssdev == def_dssdev) 2373 continue; 2374 2375 /* 2376 * We don't care if the connect succeeds or not. We just want to 2377 * connect as many displays as possible. 2378 */ 2379 dssdev->driver->connect(dssdev); 2380 } 2381 2382 mgr = omapdss_find_mgr_from_display(def_dssdev); 2383 2384 if (!mgr) { 2385 dev_err(fbdev->dev, "no ovl manager for the default display\n"); 2386 return -EINVAL; 2387 } 2388 2389 for (i = 0; i < fbdev->num_overlays; i++) { 2390 struct omap_overlay *ovl = fbdev->overlays[i]; 2391 2392 if (ovl->manager) 2393 ovl->unset_manager(ovl); 2394 2395 r = ovl->set_manager(ovl, mgr); 2396 if (r) 2397 dev_warn(fbdev->dev, 2398 "failed to connect overlay %s to manager %s\n", 2399 ovl->name, mgr->name); 2400 } 2401 2402 return 0; 2403 } 2404 2405 static struct omap_dss_device * 2406 omapfb_find_default_display(struct omapfb2_device *fbdev) 2407 { 2408 const char *def_name; 2409 int i; 2410 2411 /* 2412 * Search with the display name from the user or the board file, 2413 * comparing to display names and aliases 2414 */ 2415 2416 def_name = omapdss_get_default_display_name(); 2417 2418 if (def_name) { 2419 for (i = 0; i < fbdev->num_displays; ++i) { 2420 struct omap_dss_device *dssdev; 2421 2422 dssdev = fbdev->displays[i].dssdev; 2423 2424 if (dssdev->name && strcmp(def_name, dssdev->name) == 0) 2425 return dssdev; 2426 2427 if (strcmp(def_name, dssdev->alias) == 0) 2428 return dssdev; 2429 } 2430 2431 /* def_name given but not found */ 2432 return NULL; 2433 } 2434 2435 /* then look for DT alias display0 */ 2436 for (i = 0; i < fbdev->num_displays; ++i) { 2437 struct omap_dss_device *dssdev; 2438 int id; 2439 2440 dssdev = fbdev->displays[i].dssdev; 2441 2442 if (dssdev->dev->of_node == NULL) 2443 continue; 2444 2445 id = of_alias_get_id(dssdev->dev->of_node, "display"); 2446 if (id == 0) 2447 return dssdev; 2448 } 2449 2450 /* return the first display we have in the list */ 2451 return fbdev->displays[0].dssdev; 2452 } 2453 2454 static int omapfb_probe(struct platform_device *pdev) 2455 { 2456 struct omapfb2_device *fbdev = NULL; 2457 int r = 0; 2458 int i; 2459 struct omap_dss_device *def_display; 2460 struct omap_dss_device *dssdev; 2461 2462 DBG("omapfb_probe\n"); 2463 2464 if (omapdss_is_initialized() == false) 2465 return -EPROBE_DEFER; 2466 2467 if (pdev->num_resources != 0) { 2468 dev_err(&pdev->dev, "probed for an unknown device\n"); 2469 r = -ENODEV; 2470 goto err0; 2471 } 2472 2473 fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device), 2474 GFP_KERNEL); 2475 if (fbdev == NULL) { 2476 r = -ENOMEM; 2477 goto err0; 2478 } 2479 2480 if (def_vrfb && !omap_vrfb_supported()) { 2481 def_vrfb = 0; 2482 dev_warn(&pdev->dev, "VRFB is not supported on this hardware, " 2483 "ignoring the module parameter vrfb=y\n"); 2484 } 2485 2486 r = omapdss_compat_init(); 2487 if (r) 2488 goto err0; 2489 2490 mutex_init(&fbdev->mtx); 2491 2492 fbdev->dev = &pdev->dev; 2493 platform_set_drvdata(pdev, fbdev); 2494 2495 fbdev->num_displays = 0; 2496 dssdev = NULL; 2497 for_each_dss_dev(dssdev) { 2498 struct omapfb_display_data *d; 2499 2500 omap_dss_get_device(dssdev); 2501 2502 if (!dssdev->driver) { 2503 dev_warn(&pdev->dev, "no driver for display: %s\n", 2504 dssdev->name); 2505 omap_dss_put_device(dssdev); 2506 continue; 2507 } 2508 2509 d = &fbdev->displays[fbdev->num_displays++]; 2510 d->dssdev = dssdev; 2511 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) 2512 d->update_mode = OMAPFB_MANUAL_UPDATE; 2513 else 2514 d->update_mode = OMAPFB_AUTO_UPDATE; 2515 } 2516 2517 if (fbdev->num_displays == 0) { 2518 dev_err(&pdev->dev, "no displays\n"); 2519 r = -EPROBE_DEFER; 2520 goto cleanup; 2521 } 2522 2523 fbdev->num_overlays = omap_dss_get_num_overlays(); 2524 for (i = 0; i < fbdev->num_overlays; i++) 2525 fbdev->overlays[i] = omap_dss_get_overlay(i); 2526 2527 fbdev->num_managers = omap_dss_get_num_overlay_managers(); 2528 for (i = 0; i < fbdev->num_managers; i++) 2529 fbdev->managers[i] = omap_dss_get_overlay_manager(i); 2530 2531 def_display = omapfb_find_default_display(fbdev); 2532 if (def_display == NULL) { 2533 dev_err(fbdev->dev, "failed to find default display\n"); 2534 r = -EPROBE_DEFER; 2535 goto cleanup; 2536 } 2537 2538 r = omapfb_init_connections(fbdev, def_display); 2539 if (r) { 2540 dev_err(fbdev->dev, "failed to init overlay connections\n"); 2541 goto cleanup; 2542 } 2543 2544 if (def_mode && strlen(def_mode) > 0) { 2545 if (omapfb_parse_def_modes(fbdev)) 2546 dev_warn(&pdev->dev, "cannot parse default modes\n"); 2547 } else if (def_display && def_display->driver->set_timings && 2548 def_display->driver->check_timings) { 2549 struct omap_video_timings t; 2550 2551 r = omapfb_find_best_mode(def_display, &t); 2552 2553 if (r == 0) 2554 def_display->driver->set_timings(def_display, &t); 2555 } 2556 2557 r = omapfb_create_framebuffers(fbdev); 2558 if (r) 2559 goto cleanup; 2560 2561 for (i = 0; i < fbdev->num_managers; i++) { 2562 struct omap_overlay_manager *mgr; 2563 mgr = fbdev->managers[i]; 2564 r = mgr->apply(mgr); 2565 if (r) 2566 dev_warn(fbdev->dev, "failed to apply dispc config\n"); 2567 } 2568 2569 DBG("mgr->apply'ed\n"); 2570 2571 if (def_display) { 2572 r = omapfb_init_display(fbdev, def_display); 2573 if (r) { 2574 dev_err(fbdev->dev, 2575 "failed to initialize default " 2576 "display\n"); 2577 goto cleanup; 2578 } 2579 } 2580 2581 DBG("create sysfs for fbs\n"); 2582 r = omapfb_create_sysfs(fbdev); 2583 if (r) { 2584 dev_err(fbdev->dev, "failed to create sysfs entries\n"); 2585 goto cleanup; 2586 } 2587 2588 if (def_display) { 2589 u16 w, h; 2590 2591 def_display->driver->get_resolution(def_display, &w, &h); 2592 2593 dev_info(fbdev->dev, "using display '%s' mode %dx%d\n", 2594 def_display->name, w, h); 2595 } 2596 2597 return 0; 2598 2599 cleanup: 2600 omapfb_free_resources(fbdev); 2601 omapdss_compat_uninit(); 2602 err0: 2603 dev_err(&pdev->dev, "failed to setup omapfb\n"); 2604 return r; 2605 } 2606 2607 static int omapfb_remove(struct platform_device *pdev) 2608 { 2609 struct omapfb2_device *fbdev = platform_get_drvdata(pdev); 2610 2611 /* FIXME: wait till completion of pending events */ 2612 2613 omapfb_remove_sysfs(fbdev); 2614 2615 omapfb_free_resources(fbdev); 2616 2617 omapdss_compat_uninit(); 2618 2619 return 0; 2620 } 2621 2622 static struct platform_driver omapfb_driver = { 2623 .probe = omapfb_probe, 2624 .remove = omapfb_remove, 2625 .driver = { 2626 .name = "omapfb", 2627 }, 2628 }; 2629 2630 module_param_named(mode, def_mode, charp, 0); 2631 module_param_named(vram, def_vram, charp, 0); 2632 module_param_named(rotate, def_rotate, int, 0); 2633 module_param_named(vrfb, def_vrfb, bool, 0); 2634 module_param_named(mirror, def_mirror, bool, 0); 2635 2636 module_platform_driver(omapfb_driver); 2637 2638 MODULE_ALIAS("platform:omapfb"); 2639 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); 2640 MODULE_DESCRIPTION("OMAP2/3 Framebuffer"); 2641 MODULE_LICENSE("GPL v2"); 2642