omapfb-main.c (59576B)
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 32static char *def_mode; 33static char *def_vram; 34static bool def_vrfb; 35static int def_rotate; 36static bool def_mirror; 37static bool auto_update; 38static unsigned int auto_update_freq; 39module_param(auto_update, bool, 0); 40module_param(auto_update_freq, uint, 0644); 41 42#ifdef DEBUG 43bool omapfb_debug; 44module_param_named(debug, omapfb_debug, bool, 0644); 45static bool omapfb_test_pattern; 46module_param_named(test, omapfb_test_pattern, bool, 0644); 47#endif 48 49static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi); 50static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev, 51 struct omap_dss_device *dssdev); 52 53#ifdef DEBUG 54static 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 89static 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 150static 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 178static 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 188static 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 196static 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 204static 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 265static 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 272static 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 288static 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 299static 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 372static 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 406static 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 420static 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 434static 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 443static 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 */ 490static 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 575int 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 590void 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 */ 654int 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 */ 750static int omapfb_open(struct fb_info *fbi, int user) 751{ 752 return 0; 753} 754 755static int omapfb_release(struct fb_info *fbi, int user) 756{ 757 return 0; 758} 759 760static 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 771static 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 801static 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 */ 831int 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 920err: 921 DBG("setup_overlay failed\n"); 922 return r; 923} 924 925/* apply var to the overlay */ 926int 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; 991err: 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 */ 998static 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 */ 1015static 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 1038static 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 1066static 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 1075static 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 1084static const struct vm_operations_struct mmap_user_ops = { 1085 .open = mmap_user_open, 1086 .close = mmap_user_close, 1087}; 1088 1089static 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 1121error: 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 */ 1131static 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 1179static 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 1187static 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 1213static 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 1262exit: 1263 omapfb_unlock(fbdev); 1264 1265 return r; 1266} 1267 1268#if 0 1269/* XXX fb_read and fb_write are needed for VRFB */ 1270ssize_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 1279static 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 1297static 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 1330static void clear_fb_info(struct fb_info *fbi) 1331{ 1332 memset(&fbi->var, 0, sizeof(fbi->var)); 1333 memset(&fbi->fix, 0, sizeof(fbi->fix)); 1334 strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id)); 1335} 1336 1337static 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 1352static 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 */ 1416static 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 1463static 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 1522static 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 1566static 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 1580int 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; 1648err: 1649 omapfb_free_fbmem(fbi); 1650 clear_fb_info(fbi); 1651 return r; 1652} 1653 1654static 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 1686void 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 1714void 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 */ 1727static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi) 1728{ 1729 struct fb_var_screeninfo *var = &fbi->var; 1730 struct omap_dss_device *display = fb2display(fbi); 1731 struct omapfb_info *ofbi = FB2OFB(fbi); 1732 int r = 0; 1733 1734 fbi->fbops = &omapfb_ops; 1735 fbi->flags = FBINFO_FLAG_DEFAULT; 1736 fbi->pseudo_palette = fbdev->pseudo_palette; 1737 1738 if (ofbi->region->size == 0) { 1739 clear_fb_info(fbi); 1740 return 0; 1741 } 1742 1743 var->nonstd = 0; 1744 var->bits_per_pixel = 0; 1745 1746 var->rotate = def_rotate; 1747 1748 if (display) { 1749 u16 w, h; 1750 int rotation = (var->rotate + ofbi->rotation[0]) % 4; 1751 1752 display->driver->get_resolution(display, &w, &h); 1753 1754 if (rotation == FB_ROTATE_CW || 1755 rotation == FB_ROTATE_CCW) { 1756 var->xres = h; 1757 var->yres = w; 1758 } else { 1759 var->xres = w; 1760 var->yres = h; 1761 } 1762 1763 var->xres_virtual = var->xres; 1764 var->yres_virtual = var->yres; 1765 1766 if (!var->bits_per_pixel) { 1767 switch (omapfb_get_recommended_bpp(fbdev, display)) { 1768 case 16: 1769 var->bits_per_pixel = 16; 1770 break; 1771 case 24: 1772 var->bits_per_pixel = 32; 1773 break; 1774 default: 1775 dev_err(fbdev->dev, "illegal display " 1776 "bpp\n"); 1777 return -EINVAL; 1778 } 1779 } 1780 } else { 1781 /* if there's no display, let's just guess some basic values */ 1782 var->xres = 320; 1783 var->yres = 240; 1784 var->xres_virtual = var->xres; 1785 var->yres_virtual = var->yres; 1786 if (!var->bits_per_pixel) 1787 var->bits_per_pixel = 16; 1788 } 1789 1790 r = check_fb_var(fbi, var); 1791 if (r) 1792 goto err; 1793 1794 set_fb_fix(fbi); 1795 r = setup_vrfb_rotation(fbi); 1796 if (r) 1797 goto err; 1798 1799 r = fb_alloc_cmap(&fbi->cmap, 256, 0); 1800 if (r) 1801 dev_err(fbdev->dev, "unable to allocate color map memory\n"); 1802 1803err: 1804 return r; 1805} 1806 1807static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi) 1808{ 1809 fb_dealloc_cmap(&fbi->cmap); 1810} 1811 1812 1813static void omapfb_free_resources(struct omapfb2_device *fbdev) 1814{ 1815 int i; 1816 1817 DBG("free_resources\n"); 1818 1819 if (fbdev == NULL) 1820 return; 1821 1822 for (i = 0; i < fbdev->num_overlays; i++) { 1823 struct omap_overlay *ovl = fbdev->overlays[i]; 1824 1825 ovl->disable(ovl); 1826 1827 if (ovl->manager) 1828 ovl->unset_manager(ovl); 1829 } 1830 1831 for (i = 0; i < fbdev->num_fbs; i++) 1832 unregister_framebuffer(fbdev->fbs[i]); 1833 1834 /* free the reserved fbmem */ 1835 omapfb_free_all_fbmem(fbdev); 1836 1837 for (i = 0; i < fbdev->num_fbs; i++) { 1838 fbinfo_cleanup(fbdev, fbdev->fbs[i]); 1839 framebuffer_release(fbdev->fbs[i]); 1840 } 1841 1842 for (i = 0; i < fbdev->num_displays; i++) { 1843 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; 1844 1845 if (fbdev->displays[i].auto_update_work_enabled) 1846 omapfb_stop_auto_update(fbdev, dssdev); 1847 1848 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) 1849 dssdev->driver->disable(dssdev); 1850 1851 dssdev->driver->disconnect(dssdev); 1852 1853 omap_dss_put_device(dssdev); 1854 } 1855 1856 if (fbdev->auto_update_wq != NULL) { 1857 destroy_workqueue(fbdev->auto_update_wq); 1858 fbdev->auto_update_wq = NULL; 1859 } 1860 1861 dev_set_drvdata(fbdev->dev, NULL); 1862} 1863 1864static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) 1865{ 1866 int r, i; 1867 1868 fbdev->num_fbs = 0; 1869 1870 DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS); 1871 1872 /* allocate fb_infos */ 1873 for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) { 1874 struct fb_info *fbi; 1875 struct omapfb_info *ofbi; 1876 1877 fbi = framebuffer_alloc(sizeof(struct omapfb_info), 1878 fbdev->dev); 1879 if (!fbi) 1880 return -ENOMEM; 1881 1882 clear_fb_info(fbi); 1883 1884 fbdev->fbs[i] = fbi; 1885 1886 ofbi = FB2OFB(fbi); 1887 ofbi->fbdev = fbdev; 1888 ofbi->id = i; 1889 1890 ofbi->region = &fbdev->regions[i]; 1891 ofbi->region->id = i; 1892 init_rwsem(&ofbi->region->lock); 1893 1894 /* assign these early, so that fb alloc can use them */ 1895 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : 1896 OMAP_DSS_ROT_DMA; 1897 ofbi->mirror = def_mirror; 1898 1899 fbdev->num_fbs++; 1900 } 1901 1902 DBG("fb_infos allocated\n"); 1903 1904 /* assign overlays for the fbs */ 1905 for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) { 1906 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); 1907 1908 ofbi->overlays[0] = fbdev->overlays[i]; 1909 ofbi->num_overlays = 1; 1910 } 1911 1912 /* allocate fb memories */ 1913 r = omapfb_allocate_all_fbs(fbdev); 1914 if (r) { 1915 dev_err(fbdev->dev, "failed to allocate fbmem\n"); 1916 return r; 1917 } 1918 1919 DBG("fbmems allocated\n"); 1920 1921 /* setup fb_infos */ 1922 for (i = 0; i < fbdev->num_fbs; i++) { 1923 struct fb_info *fbi = fbdev->fbs[i]; 1924 struct omapfb_info *ofbi = FB2OFB(fbi); 1925 1926 omapfb_get_mem_region(ofbi->region); 1927 r = omapfb_fb_init(fbdev, fbi); 1928 omapfb_put_mem_region(ofbi->region); 1929 1930 if (r) { 1931 dev_err(fbdev->dev, "failed to setup fb_info\n"); 1932 return r; 1933 } 1934 } 1935 1936 for (i = 0; i < fbdev->num_fbs; i++) { 1937 struct fb_info *fbi = fbdev->fbs[i]; 1938 struct omapfb_info *ofbi = FB2OFB(fbi); 1939 1940 if (ofbi->region->size == 0) 1941 continue; 1942 1943 omapfb_clear_fb(fbi); 1944 } 1945 1946 DBG("fb_infos initialized\n"); 1947 1948 for (i = 0; i < fbdev->num_fbs; i++) { 1949 r = register_framebuffer(fbdev->fbs[i]); 1950 if (r != 0) { 1951 dev_err(fbdev->dev, 1952 "registering framebuffer %d failed\n", i); 1953 return r; 1954 } 1955 } 1956 1957 DBG("framebuffers registered\n"); 1958 1959 for (i = 0; i < fbdev->num_fbs; i++) { 1960 struct fb_info *fbi = fbdev->fbs[i]; 1961 struct omapfb_info *ofbi = FB2OFB(fbi); 1962 1963 omapfb_get_mem_region(ofbi->region); 1964 r = omapfb_apply_changes(fbi, 1); 1965 omapfb_put_mem_region(ofbi->region); 1966 1967 if (r) { 1968 dev_err(fbdev->dev, "failed to change mode\n"); 1969 return r; 1970 } 1971 } 1972 1973 /* Enable fb0 */ 1974 if (fbdev->num_fbs > 0) { 1975 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); 1976 1977 if (ofbi->num_overlays > 0) { 1978 struct omap_overlay *ovl = ofbi->overlays[0]; 1979 1980 ovl->manager->apply(ovl->manager); 1981 1982 r = omapfb_overlay_enable(ovl, 1); 1983 1984 if (r) { 1985 dev_err(fbdev->dev, 1986 "failed to enable overlay\n"); 1987 return r; 1988 } 1989 } 1990 } 1991 1992 DBG("create_framebuffers done\n"); 1993 1994 return 0; 1995} 1996 1997static int omapfb_mode_to_timings(const char *mode_str, 1998 struct omap_dss_device *display, 1999 struct omap_video_timings *timings, u8 *bpp) 2000{ 2001 struct fb_info *fbi; 2002 struct fb_var_screeninfo *var; 2003 struct fb_ops *fbops; 2004 int r; 2005 2006#ifdef CONFIG_OMAP2_DSS_VENC 2007 if (strcmp(mode_str, "pal") == 0) { 2008 *timings = omap_dss_pal_timings; 2009 *bpp = 24; 2010 return 0; 2011 } else if (strcmp(mode_str, "ntsc") == 0) { 2012 *timings = omap_dss_ntsc_timings; 2013 *bpp = 24; 2014 return 0; 2015 } 2016#endif 2017 2018 /* this is quite a hack, but I wanted to use the modedb and for 2019 * that we need fb_info and var, so we create dummy ones */ 2020 2021 *bpp = 0; 2022 fbi = NULL; 2023 var = NULL; 2024 fbops = NULL; 2025 2026 fbi = kzalloc(sizeof(*fbi), GFP_KERNEL); 2027 if (fbi == NULL) { 2028 r = -ENOMEM; 2029 goto err; 2030 } 2031 2032 var = kzalloc(sizeof(*var), GFP_KERNEL); 2033 if (var == NULL) { 2034 r = -ENOMEM; 2035 goto err; 2036 } 2037 2038 fbops = kzalloc(sizeof(*fbops), GFP_KERNEL); 2039 if (fbops == NULL) { 2040 r = -ENOMEM; 2041 goto err; 2042 } 2043 2044 fbi->fbops = fbops; 2045 2046 r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24); 2047 if (r == 0) { 2048 r = -EINVAL; 2049 goto err; 2050 } 2051 2052 if (display->driver->get_timings) { 2053 display->driver->get_timings(display, timings); 2054 } else { 2055 timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 2056 timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; 2057 timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; 2058 } 2059 2060 timings->pixelclock = PICOS2KHZ(var->pixclock) * 1000; 2061 timings->hbp = var->left_margin; 2062 timings->hfp = var->right_margin; 2063 timings->vbp = var->upper_margin; 2064 timings->vfp = var->lower_margin; 2065 timings->hsw = var->hsync_len; 2066 timings->vsw = var->vsync_len; 2067 timings->x_res = var->xres; 2068 timings->y_res = var->yres; 2069 timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ? 2070 OMAPDSS_SIG_ACTIVE_HIGH : 2071 OMAPDSS_SIG_ACTIVE_LOW; 2072 timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ? 2073 OMAPDSS_SIG_ACTIVE_HIGH : 2074 OMAPDSS_SIG_ACTIVE_LOW; 2075 timings->interlace = var->vmode & FB_VMODE_INTERLACED; 2076 2077 switch (var->bits_per_pixel) { 2078 case 16: 2079 *bpp = 16; 2080 break; 2081 case 24: 2082 case 32: 2083 default: 2084 *bpp = 24; 2085 break; 2086 } 2087 2088 r = 0; 2089 2090err: 2091 kfree(fbi); 2092 kfree(var); 2093 kfree(fbops); 2094 2095 return r; 2096} 2097 2098static int omapfb_set_def_mode(struct omapfb2_device *fbdev, 2099 struct omap_dss_device *display, char *mode_str) 2100{ 2101 int r; 2102 u8 bpp; 2103 struct omap_video_timings timings, temp_timings; 2104 struct omapfb_display_data *d; 2105 2106 r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp); 2107 if (r) 2108 return r; 2109 2110 d = get_display_data(fbdev, display); 2111 d->bpp_override = bpp; 2112 2113 if (display->driver->check_timings) { 2114 r = display->driver->check_timings(display, &timings); 2115 if (r) 2116 return r; 2117 } else { 2118 /* If check_timings is not present compare xres and yres */ 2119 if (display->driver->get_timings) { 2120 display->driver->get_timings(display, &temp_timings); 2121 2122 if (temp_timings.x_res != timings.x_res || 2123 temp_timings.y_res != timings.y_res) 2124 return -EINVAL; 2125 } 2126 } 2127 2128 if (display->driver->set_timings) 2129 display->driver->set_timings(display, &timings); 2130 2131 return 0; 2132} 2133 2134static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev, 2135 struct omap_dss_device *dssdev) 2136{ 2137 struct omapfb_display_data *d; 2138 2139 BUG_ON(dssdev->driver->get_recommended_bpp == NULL); 2140 2141 d = get_display_data(fbdev, dssdev); 2142 2143 if (d->bpp_override != 0) 2144 return d->bpp_override; 2145 2146 return dssdev->driver->get_recommended_bpp(dssdev); 2147} 2148 2149static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) 2150{ 2151 char *str, *options, *this_opt; 2152 int r = 0; 2153 2154 str = kstrdup(def_mode, GFP_KERNEL); 2155 if (!str) 2156 return -ENOMEM; 2157 options = str; 2158 2159 while (!r && (this_opt = strsep(&options, ",")) != NULL) { 2160 char *p, *display_str, *mode_str; 2161 struct omap_dss_device *display; 2162 int i; 2163 2164 p = strchr(this_opt, ':'); 2165 if (!p) { 2166 r = -EINVAL; 2167 break; 2168 } 2169 2170 *p = 0; 2171 display_str = this_opt; 2172 mode_str = p + 1; 2173 2174 display = NULL; 2175 for (i = 0; i < fbdev->num_displays; ++i) { 2176 if (strcmp(fbdev->displays[i].dssdev->name, 2177 display_str) == 0) { 2178 display = fbdev->displays[i].dssdev; 2179 break; 2180 } 2181 } 2182 2183 if (!display) { 2184 r = -EINVAL; 2185 break; 2186 } 2187 2188 r = omapfb_set_def_mode(fbdev, display, mode_str); 2189 if (r) 2190 break; 2191 } 2192 2193 kfree(str); 2194 2195 return r; 2196} 2197 2198static void fb_videomode_to_omap_timings(struct fb_videomode *m, 2199 struct omap_dss_device *display, 2200 struct omap_video_timings *t) 2201{ 2202 if (display->driver->get_timings) { 2203 display->driver->get_timings(display, t); 2204 } else { 2205 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 2206 t->de_level = OMAPDSS_SIG_ACTIVE_HIGH; 2207 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; 2208 } 2209 2210 t->x_res = m->xres; 2211 t->y_res = m->yres; 2212 t->pixelclock = PICOS2KHZ(m->pixclock) * 1000; 2213 t->hsw = m->hsync_len; 2214 t->hfp = m->right_margin; 2215 t->hbp = m->left_margin; 2216 t->vsw = m->vsync_len; 2217 t->vfp = m->lower_margin; 2218 t->vbp = m->upper_margin; 2219 t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ? 2220 OMAPDSS_SIG_ACTIVE_HIGH : 2221 OMAPDSS_SIG_ACTIVE_LOW; 2222 t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ? 2223 OMAPDSS_SIG_ACTIVE_HIGH : 2224 OMAPDSS_SIG_ACTIVE_LOW; 2225 t->interlace = m->vmode & FB_VMODE_INTERLACED; 2226} 2227 2228static int omapfb_find_best_mode(struct omap_dss_device *display, 2229 struct omap_video_timings *timings) 2230{ 2231 struct fb_monspecs *specs; 2232 u8 *edid; 2233 int r, i, best_idx, len; 2234 2235 if (!display->driver->read_edid) 2236 return -ENODEV; 2237 2238 len = 0x80 * 2; 2239 edid = kmalloc(len, GFP_KERNEL); 2240 if (edid == NULL) 2241 return -ENOMEM; 2242 2243 r = display->driver->read_edid(display, edid, len); 2244 if (r < 0) 2245 goto err1; 2246 2247 specs = kzalloc(sizeof(*specs), GFP_KERNEL); 2248 if (specs == NULL) { 2249 r = -ENOMEM; 2250 goto err1; 2251 } 2252 2253 fb_edid_to_monspecs(edid, specs); 2254 2255 best_idx = -1; 2256 2257 for (i = 0; i < specs->modedb_len; ++i) { 2258 struct fb_videomode *m; 2259 struct omap_video_timings t; 2260 2261 m = &specs->modedb[i]; 2262 2263 if (m->pixclock == 0) 2264 continue; 2265 2266 /* skip repeated pixel modes */ 2267 if (m->xres == 2880 || m->xres == 1440) 2268 continue; 2269 2270 if (m->vmode & FB_VMODE_INTERLACED || 2271 m->vmode & FB_VMODE_DOUBLE) 2272 continue; 2273 2274 fb_videomode_to_omap_timings(m, display, &t); 2275 2276 r = display->driver->check_timings(display, &t); 2277 if (r == 0) { 2278 best_idx = i; 2279 break; 2280 } 2281 } 2282 2283 if (best_idx == -1) { 2284 r = -ENOENT; 2285 goto err2; 2286 } 2287 2288 fb_videomode_to_omap_timings(&specs->modedb[best_idx], display, 2289 timings); 2290 2291 r = 0; 2292 2293err2: 2294 fb_destroy_modedb(specs->modedb); 2295 kfree(specs); 2296err1: 2297 kfree(edid); 2298 2299 return r; 2300} 2301 2302static int omapfb_init_display(struct omapfb2_device *fbdev, 2303 struct omap_dss_device *dssdev) 2304{ 2305 struct omap_dss_driver *dssdrv = dssdev->driver; 2306 struct omapfb_display_data *d; 2307 int r; 2308 2309 r = dssdrv->enable(dssdev); 2310 if (r) { 2311 dev_warn(fbdev->dev, "Failed to enable display '%s'\n", 2312 dssdev->name); 2313 return r; 2314 } 2315 2316 d = get_display_data(fbdev, dssdev); 2317 2318 d->fbdev = fbdev; 2319 2320 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { 2321 u16 w, h; 2322 2323 if (auto_update) { 2324 omapfb_start_auto_update(fbdev, dssdev); 2325 d->update_mode = OMAPFB_AUTO_UPDATE; 2326 } else { 2327 d->update_mode = OMAPFB_MANUAL_UPDATE; 2328 } 2329 2330 if (dssdrv->enable_te) { 2331 r = dssdrv->enable_te(dssdev, 1); 2332 if (r) { 2333 dev_err(fbdev->dev, "Failed to set TE\n"); 2334 return r; 2335 } 2336 } 2337 2338 dssdrv->get_resolution(dssdev, &w, &h); 2339 r = dssdrv->update(dssdev, 0, 0, w, h); 2340 if (r) { 2341 dev_err(fbdev->dev, 2342 "Failed to update display\n"); 2343 return r; 2344 } 2345 } else { 2346 d->update_mode = OMAPFB_AUTO_UPDATE; 2347 } 2348 2349 return 0; 2350} 2351 2352static int omapfb_init_connections(struct omapfb2_device *fbdev, 2353 struct omap_dss_device *def_dssdev) 2354{ 2355 int i, r; 2356 struct omap_overlay_manager *mgr; 2357 2358 r = def_dssdev->driver->connect(def_dssdev); 2359 if (r) { 2360 dev_err(fbdev->dev, "failed to connect default display\n"); 2361 return r; 2362 } 2363 2364 for (i = 0; i < fbdev->num_displays; ++i) { 2365 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; 2366 2367 if (dssdev == def_dssdev) 2368 continue; 2369 2370 /* 2371 * We don't care if the connect succeeds or not. We just want to 2372 * connect as many displays as possible. 2373 */ 2374 dssdev->driver->connect(dssdev); 2375 } 2376 2377 mgr = omapdss_find_mgr_from_display(def_dssdev); 2378 2379 if (!mgr) { 2380 dev_err(fbdev->dev, "no ovl manager for the default display\n"); 2381 return -EINVAL; 2382 } 2383 2384 for (i = 0; i < fbdev->num_overlays; i++) { 2385 struct omap_overlay *ovl = fbdev->overlays[i]; 2386 2387 if (ovl->manager) 2388 ovl->unset_manager(ovl); 2389 2390 r = ovl->set_manager(ovl, mgr); 2391 if (r) 2392 dev_warn(fbdev->dev, 2393 "failed to connect overlay %s to manager %s\n", 2394 ovl->name, mgr->name); 2395 } 2396 2397 return 0; 2398} 2399 2400static struct omap_dss_device * 2401omapfb_find_default_display(struct omapfb2_device *fbdev) 2402{ 2403 const char *def_name; 2404 int i; 2405 2406 /* 2407 * Search with the display name from the user or the board file, 2408 * comparing to display names and aliases 2409 */ 2410 2411 def_name = omapdss_get_default_display_name(); 2412 2413 if (def_name) { 2414 for (i = 0; i < fbdev->num_displays; ++i) { 2415 struct omap_dss_device *dssdev; 2416 2417 dssdev = fbdev->displays[i].dssdev; 2418 2419 if (dssdev->name && strcmp(def_name, dssdev->name) == 0) 2420 return dssdev; 2421 2422 if (strcmp(def_name, dssdev->alias) == 0) 2423 return dssdev; 2424 } 2425 2426 /* def_name given but not found */ 2427 return NULL; 2428 } 2429 2430 /* then look for DT alias display0 */ 2431 for (i = 0; i < fbdev->num_displays; ++i) { 2432 struct omap_dss_device *dssdev; 2433 int id; 2434 2435 dssdev = fbdev->displays[i].dssdev; 2436 2437 if (dssdev->dev->of_node == NULL) 2438 continue; 2439 2440 id = of_alias_get_id(dssdev->dev->of_node, "display"); 2441 if (id == 0) 2442 return dssdev; 2443 } 2444 2445 /* return the first display we have in the list */ 2446 return fbdev->displays[0].dssdev; 2447} 2448 2449static int omapfb_probe(struct platform_device *pdev) 2450{ 2451 struct omapfb2_device *fbdev = NULL; 2452 int r = 0; 2453 int i; 2454 struct omap_dss_device *def_display; 2455 struct omap_dss_device *dssdev; 2456 2457 DBG("omapfb_probe\n"); 2458 2459 if (omapdss_is_initialized() == false) 2460 return -EPROBE_DEFER; 2461 2462 if (pdev->num_resources != 0) { 2463 dev_err(&pdev->dev, "probed for an unknown device\n"); 2464 r = -ENODEV; 2465 goto err0; 2466 } 2467 2468 fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device), 2469 GFP_KERNEL); 2470 if (fbdev == NULL) { 2471 r = -ENOMEM; 2472 goto err0; 2473 } 2474 2475 if (def_vrfb && !omap_vrfb_supported()) { 2476 def_vrfb = 0; 2477 dev_warn(&pdev->dev, "VRFB is not supported on this hardware, " 2478 "ignoring the module parameter vrfb=y\n"); 2479 } 2480 2481 r = omapdss_compat_init(); 2482 if (r) 2483 goto err0; 2484 2485 mutex_init(&fbdev->mtx); 2486 2487 fbdev->dev = &pdev->dev; 2488 platform_set_drvdata(pdev, fbdev); 2489 2490 fbdev->num_displays = 0; 2491 dssdev = NULL; 2492 for_each_dss_dev(dssdev) { 2493 struct omapfb_display_data *d; 2494 2495 omap_dss_get_device(dssdev); 2496 2497 if (!dssdev->driver) { 2498 dev_warn(&pdev->dev, "no driver for display: %s\n", 2499 dssdev->name); 2500 omap_dss_put_device(dssdev); 2501 continue; 2502 } 2503 2504 d = &fbdev->displays[fbdev->num_displays++]; 2505 d->dssdev = dssdev; 2506 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) 2507 d->update_mode = OMAPFB_MANUAL_UPDATE; 2508 else 2509 d->update_mode = OMAPFB_AUTO_UPDATE; 2510 } 2511 2512 if (fbdev->num_displays == 0) { 2513 dev_err(&pdev->dev, "no displays\n"); 2514 r = -EPROBE_DEFER; 2515 goto cleanup; 2516 } 2517 2518 fbdev->num_overlays = omap_dss_get_num_overlays(); 2519 for (i = 0; i < fbdev->num_overlays; i++) 2520 fbdev->overlays[i] = omap_dss_get_overlay(i); 2521 2522 fbdev->num_managers = omap_dss_get_num_overlay_managers(); 2523 for (i = 0; i < fbdev->num_managers; i++) 2524 fbdev->managers[i] = omap_dss_get_overlay_manager(i); 2525 2526 def_display = omapfb_find_default_display(fbdev); 2527 if (def_display == NULL) { 2528 dev_err(fbdev->dev, "failed to find default display\n"); 2529 r = -EPROBE_DEFER; 2530 goto cleanup; 2531 } 2532 2533 r = omapfb_init_connections(fbdev, def_display); 2534 if (r) { 2535 dev_err(fbdev->dev, "failed to init overlay connections\n"); 2536 goto cleanup; 2537 } 2538 2539 if (def_mode && strlen(def_mode) > 0) { 2540 if (omapfb_parse_def_modes(fbdev)) 2541 dev_warn(&pdev->dev, "cannot parse default modes\n"); 2542 } else if (def_display && def_display->driver->set_timings && 2543 def_display->driver->check_timings) { 2544 struct omap_video_timings t; 2545 2546 r = omapfb_find_best_mode(def_display, &t); 2547 2548 if (r == 0) 2549 def_display->driver->set_timings(def_display, &t); 2550 } 2551 2552 r = omapfb_create_framebuffers(fbdev); 2553 if (r) 2554 goto cleanup; 2555 2556 for (i = 0; i < fbdev->num_managers; i++) { 2557 struct omap_overlay_manager *mgr; 2558 mgr = fbdev->managers[i]; 2559 r = mgr->apply(mgr); 2560 if (r) 2561 dev_warn(fbdev->dev, "failed to apply dispc config\n"); 2562 } 2563 2564 DBG("mgr->apply'ed\n"); 2565 2566 if (def_display) { 2567 r = omapfb_init_display(fbdev, def_display); 2568 if (r) { 2569 dev_err(fbdev->dev, 2570 "failed to initialize default " 2571 "display\n"); 2572 goto cleanup; 2573 } 2574 } 2575 2576 DBG("create sysfs for fbs\n"); 2577 r = omapfb_create_sysfs(fbdev); 2578 if (r) { 2579 dev_err(fbdev->dev, "failed to create sysfs entries\n"); 2580 goto cleanup; 2581 } 2582 2583 if (def_display) { 2584 u16 w, h; 2585 2586 def_display->driver->get_resolution(def_display, &w, &h); 2587 2588 dev_info(fbdev->dev, "using display '%s' mode %dx%d\n", 2589 def_display->name, w, h); 2590 } 2591 2592 return 0; 2593 2594cleanup: 2595 omapfb_free_resources(fbdev); 2596 omapdss_compat_uninit(); 2597err0: 2598 dev_err(&pdev->dev, "failed to setup omapfb\n"); 2599 return r; 2600} 2601 2602static int omapfb_remove(struct platform_device *pdev) 2603{ 2604 struct omapfb2_device *fbdev = platform_get_drvdata(pdev); 2605 2606 /* FIXME: wait till completion of pending events */ 2607 2608 omapfb_remove_sysfs(fbdev); 2609 2610 omapfb_free_resources(fbdev); 2611 2612 omapdss_compat_uninit(); 2613 2614 return 0; 2615} 2616 2617static struct platform_driver omapfb_driver = { 2618 .probe = omapfb_probe, 2619 .remove = omapfb_remove, 2620 .driver = { 2621 .name = "omapfb", 2622 }, 2623}; 2624 2625module_param_named(mode, def_mode, charp, 0); 2626module_param_named(vram, def_vram, charp, 0); 2627module_param_named(rotate, def_rotate, int, 0); 2628module_param_named(vrfb, def_vrfb, bool, 0); 2629module_param_named(mirror, def_mirror, bool, 0); 2630 2631module_platform_driver(omapfb_driver); 2632 2633MODULE_ALIAS("platform:omapfb"); 2634MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); 2635MODULE_DESCRIPTION("OMAP2/3 Framebuffer"); 2636MODULE_LICENSE("GPL v2");