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