diff options
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-realview/core.c | 214 |
2 files changed, 35 insertions, 180 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b0d55b9f184e..7ee15c2933f8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -241,6 +241,7 @@ config ARCH_REALVIEW | |||
241 | select GENERIC_CLOCKEVENTS | 241 | select GENERIC_CLOCKEVENTS |
242 | select ARCH_WANT_OPTIONAL_GPIOLIB | 242 | select ARCH_WANT_OPTIONAL_GPIOLIB |
243 | select PLAT_VERSATILE | 243 | select PLAT_VERSATILE |
244 | select PLAT_VERSATILE_CLCD | ||
244 | select ARM_TIMER_SP804 | 245 | select ARM_TIMER_SP804 |
245 | select GPIO_PL061 if GPIOLIB | 246 | select GPIO_PL061 if GPIOLIB |
246 | help | 247 | help |
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 1c6602cf50e4..a18a5a66c4c3 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <mach/irqs.h> | 51 | #include <mach/irqs.h> |
52 | #include <asm/hardware/timer-sp.h> | 52 | #include <asm/hardware/timer-sp.h> |
53 | 53 | ||
54 | #include <plat/clcd.h> | ||
54 | #include <plat/sched_clock.h> | 55 | #include <plat/sched_clock.h> |
55 | 56 | ||
56 | #include "core.h" | 57 | #include "core.h" |
@@ -385,157 +386,6 @@ core_initcall(clk_init); | |||
385 | #define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8) | 386 | #define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8) |
386 | #define SYS_CLCD_ID_VGA (0x1f << 8) | 387 | #define SYS_CLCD_ID_VGA (0x1f << 8) |
387 | 388 | ||
388 | static struct clcd_panel vga = { | ||
389 | .mode = { | ||
390 | .name = "VGA", | ||
391 | .refresh = 60, | ||
392 | .xres = 640, | ||
393 | .yres = 480, | ||
394 | .pixclock = 39721, | ||
395 | .left_margin = 40, | ||
396 | .right_margin = 24, | ||
397 | .upper_margin = 32, | ||
398 | .lower_margin = 11, | ||
399 | .hsync_len = 96, | ||
400 | .vsync_len = 2, | ||
401 | .sync = 0, | ||
402 | .vmode = FB_VMODE_NONINTERLACED, | ||
403 | }, | ||
404 | .width = -1, | ||
405 | .height = -1, | ||
406 | .tim2 = TIM2_BCD | TIM2_IPC, | ||
407 | .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), | ||
408 | .bpp = 16, | ||
409 | }; | ||
410 | |||
411 | static struct clcd_panel xvga = { | ||
412 | .mode = { | ||
413 | .name = "XVGA", | ||
414 | .refresh = 60, | ||
415 | .xres = 1024, | ||
416 | .yres = 768, | ||
417 | .pixclock = 15748, | ||
418 | .left_margin = 152, | ||
419 | .right_margin = 48, | ||
420 | .upper_margin = 23, | ||
421 | .lower_margin = 3, | ||
422 | .hsync_len = 104, | ||
423 | .vsync_len = 4, | ||
424 | .sync = 0, | ||
425 | .vmode = FB_VMODE_NONINTERLACED, | ||
426 | }, | ||
427 | .width = -1, | ||
428 | .height = -1, | ||
429 | .tim2 = TIM2_BCD | TIM2_IPC, | ||
430 | .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), | ||
431 | .bpp = 16, | ||
432 | }; | ||
433 | |||
434 | static struct clcd_panel sanyo_3_8_in = { | ||
435 | .mode = { | ||
436 | .name = "Sanyo QVGA", | ||
437 | .refresh = 116, | ||
438 | .xres = 320, | ||
439 | .yres = 240, | ||
440 | .pixclock = 100000, | ||
441 | .left_margin = 6, | ||
442 | .right_margin = 6, | ||
443 | .upper_margin = 5, | ||
444 | .lower_margin = 5, | ||
445 | .hsync_len = 6, | ||
446 | .vsync_len = 6, | ||
447 | .sync = 0, | ||
448 | .vmode = FB_VMODE_NONINTERLACED, | ||
449 | }, | ||
450 | .width = -1, | ||
451 | .height = -1, | ||
452 | .tim2 = TIM2_BCD, | ||
453 | .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), | ||
454 | .bpp = 16, | ||
455 | }; | ||
456 | |||
457 | static struct clcd_panel sanyo_2_5_in = { | ||
458 | .mode = { | ||
459 | .name = "Sanyo QVGA Portrait", | ||
460 | .refresh = 116, | ||
461 | .xres = 240, | ||
462 | .yres = 320, | ||
463 | .pixclock = 100000, | ||
464 | .left_margin = 20, | ||
465 | .right_margin = 10, | ||
466 | .upper_margin = 2, | ||
467 | .lower_margin = 2, | ||
468 | .hsync_len = 10, | ||
469 | .vsync_len = 2, | ||
470 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
471 | .vmode = FB_VMODE_NONINTERLACED, | ||
472 | }, | ||
473 | .width = -1, | ||
474 | .height = -1, | ||
475 | .tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC, | ||
476 | .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), | ||
477 | .bpp = 16, | ||
478 | }; | ||
479 | |||
480 | static struct clcd_panel epson_2_2_in = { | ||
481 | .mode = { | ||
482 | .name = "Epson QCIF", | ||
483 | .refresh = 390, | ||
484 | .xres = 176, | ||
485 | .yres = 220, | ||
486 | .pixclock = 62500, | ||
487 | .left_margin = 3, | ||
488 | .right_margin = 2, | ||
489 | .upper_margin = 1, | ||
490 | .lower_margin = 0, | ||
491 | .hsync_len = 3, | ||
492 | .vsync_len = 2, | ||
493 | .sync = 0, | ||
494 | .vmode = FB_VMODE_NONINTERLACED, | ||
495 | }, | ||
496 | .width = -1, | ||
497 | .height = -1, | ||
498 | .tim2 = TIM2_BCD | TIM2_IPC, | ||
499 | .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), | ||
500 | .bpp = 16, | ||
501 | }; | ||
502 | |||
503 | /* | ||
504 | * Detect which LCD panel is connected, and return the appropriate | ||
505 | * clcd_panel structure. Note: we do not have any information on | ||
506 | * the required timings for the 8.4in panel, so we presently assume | ||
507 | * VGA timings. | ||
508 | */ | ||
509 | static struct clcd_panel *realview_clcd_panel(void) | ||
510 | { | ||
511 | void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET; | ||
512 | struct clcd_panel *vga_panel; | ||
513 | struct clcd_panel *panel; | ||
514 | u32 val; | ||
515 | |||
516 | if (machine_is_realview_eb()) | ||
517 | vga_panel = &vga; | ||
518 | else | ||
519 | vga_panel = &xvga; | ||
520 | |||
521 | val = readl(sys_clcd) & SYS_CLCD_ID_MASK; | ||
522 | if (val == SYS_CLCD_ID_SANYO_3_8) | ||
523 | panel = &sanyo_3_8_in; | ||
524 | else if (val == SYS_CLCD_ID_SANYO_2_5) | ||
525 | panel = &sanyo_2_5_in; | ||
526 | else if (val == SYS_CLCD_ID_EPSON_2_2) | ||
527 | panel = &epson_2_2_in; | ||
528 | else if (val == SYS_CLCD_ID_VGA) | ||
529 | panel = vga_panel; | ||
530 | else { | ||
531 | printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n", | ||
532 | val); | ||
533 | panel = vga_panel; | ||
534 | } | ||
535 | |||
536 | return panel; | ||
537 | } | ||
538 | |||
539 | /* | 389 | /* |
540 | * Disable all display connectors on the interface module. | 390 | * Disable all display connectors on the interface module. |
541 | */ | 391 | */ |
@@ -565,56 +415,60 @@ static void realview_clcd_enable(struct clcd_fb *fb) | |||
565 | writel(val, sys_clcd); | 415 | writel(val, sys_clcd); |
566 | } | 416 | } |
567 | 417 | ||
418 | /* | ||
419 | * Detect which LCD panel is connected, and return the appropriate | ||
420 | * clcd_panel structure. Note: we do not have any information on | ||
421 | * the required timings for the 8.4in panel, so we presently assume | ||
422 | * VGA timings. | ||
423 | */ | ||
568 | static int realview_clcd_setup(struct clcd_fb *fb) | 424 | static int realview_clcd_setup(struct clcd_fb *fb) |
569 | { | 425 | { |
426 | void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET; | ||
427 | const char *panel_name, *vga_panel_name; | ||
570 | unsigned long framesize; | 428 | unsigned long framesize; |
571 | dma_addr_t dma; | 429 | u32 val; |
572 | 430 | ||
573 | if (machine_is_realview_eb()) | 431 | if (machine_is_realview_eb()) { |
574 | /* VGA, 16bpp */ | 432 | /* VGA, 16bpp */ |
575 | framesize = 640 * 480 * 2; | 433 | framesize = 640 * 480 * 2; |
576 | else | 434 | vga_panel_name = "VGA"; |
435 | } else { | ||
577 | /* XVGA, 16bpp */ | 436 | /* XVGA, 16bpp */ |
578 | framesize = 1024 * 768 * 2; | 437 | framesize = 1024 * 768 * 2; |
579 | 438 | vga_panel_name = "XVGA"; | |
580 | fb->panel = realview_clcd_panel(); | ||
581 | |||
582 | fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, | ||
583 | &dma, GFP_KERNEL | GFP_DMA); | ||
584 | if (!fb->fb.screen_base) { | ||
585 | printk(KERN_ERR "CLCD: unable to map framebuffer\n"); | ||
586 | return -ENOMEM; | ||
587 | } | 439 | } |
588 | 440 | ||
589 | fb->fb.fix.smem_start = dma; | 441 | val = readl(sys_clcd) & SYS_CLCD_ID_MASK; |
590 | fb->fb.fix.smem_len = framesize; | 442 | if (val == SYS_CLCD_ID_SANYO_3_8) |
591 | 443 | panel_name = "Sanyo TM38QV67A02A"; | |
592 | return 0; | 444 | else if (val == SYS_CLCD_ID_SANYO_2_5) |
593 | } | 445 | panel_name = "Sanyo QVGA Portrait"; |
446 | else if (val == SYS_CLCD_ID_EPSON_2_2) | ||
447 | panel_name = "Epson L2F50113T00"; | ||
448 | else if (val == SYS_CLCD_ID_VGA) | ||
449 | panel_name = vga_panel_name; | ||
450 | else { | ||
451 | pr_err("CLCD: unknown LCD panel ID 0x%08x, using VGA\n", val); | ||
452 | panel_name = vga_panel_name; | ||
453 | } | ||
594 | 454 | ||
595 | static int realview_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) | 455 | fb->panel = versatile_clcd_get_panel(panel_name); |
596 | { | 456 | if (!fb->panel) |
597 | return dma_mmap_writecombine(&fb->dev->dev, vma, | 457 | return -EINVAL; |
598 | fb->fb.screen_base, | ||
599 | fb->fb.fix.smem_start, | ||
600 | fb->fb.fix.smem_len); | ||
601 | } | ||
602 | 458 | ||
603 | static void realview_clcd_remove(struct clcd_fb *fb) | 459 | return versatile_clcd_setup_dma(fb, framesize); |
604 | { | ||
605 | dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, | ||
606 | fb->fb.screen_base, fb->fb.fix.smem_start); | ||
607 | } | 460 | } |
608 | 461 | ||
609 | struct clcd_board clcd_plat_data = { | 462 | struct clcd_board clcd_plat_data = { |
610 | .name = "RealView", | 463 | .name = "RealView", |
464 | .caps = CLCD_CAP_ALL, | ||
611 | .check = clcdfb_check, | 465 | .check = clcdfb_check, |
612 | .decode = clcdfb_decode, | 466 | .decode = clcdfb_decode, |
613 | .disable = realview_clcd_disable, | 467 | .disable = realview_clcd_disable, |
614 | .enable = realview_clcd_enable, | 468 | .enable = realview_clcd_enable, |
615 | .setup = realview_clcd_setup, | 469 | .setup = realview_clcd_setup, |
616 | .mmap = realview_clcd_mmap, | 470 | .mmap = versatile_clcd_mmap_dma, |
617 | .remove = realview_clcd_remove, | 471 | .remove = versatile_clcd_remove_dma, |
618 | }; | 472 | }; |
619 | 473 | ||
620 | #ifdef CONFIG_LEDS | 474 | #ifdef CONFIG_LEDS |