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